I named my JTable tblList and I wanted a certain column to be not-editable. I have found the below code that should do the job however, i cannot for the life of me make it work on my existing table. I guess my question in particular is, how do I call the below codes to be set on my existing table named tblList?
JTable model = new JTable(){
#Override
public boolean isCellEditable(int row, int column){
return column==3 false;
};
};
The way of doing this would be to have your own TableModel and override the public boolean isCellEditable(int rowIndex, int columnIndex);. As a rule of thumb, we should not override a JTable method. For your reference, this is what JTable does - delegates the call to the data model:
public boolean isCellEditable(int row, int column) {
return getModel().isCellEditable(convertRowIndexToModel(row),
convertColumnIndexToModel(column));
}
The way we do it is:
Step 1: Create a Table model:
public class SimpleTableModel extends DefaultTableModel {
#Override
boolean isCellEditable(int row, int col) {
// Your logic goes here
}
}
Step 2: Pass an instance of this class to the constructor of JTable
JTable table = new JTable (new SimpleTableModel());
Please find a working example below (this is not the way I usually write code and nor should you but just to give you an example):
static class Table extends JFrame {
public Table() {
String[] columns = new String[] {
"Id", "Name", "Hourly Rate", "Part Time"
};
//actual data for the table in a 2d array
Object[][] data = new Object[][] {
{1, "John", 40.0, false },
{2, "Rambo", 70.0, false },
{3, "Zorro", 60.0, true },
};
TableModel m = new AbstractTableModel() {
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public int getColumnCount() {
return data[0].length;
}
#Override
public boolean isCellEditable (int row, int col) {
return false;
}
};
//create table with data
JTable table = new JTable(m);
//add the table to the frame
this.add(new JScrollPane(table));
this.pack();
this.setVisible(true);
}
}
Related
My next annoying problem is to set Space between cells so that content of cells doesn't get erased.
I tried already all Internet solutions but they don't help because as I encrease border then content of cell is erased.
Here is what I tried:
public class DateFormatDemo extends JFrame
{
private Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
private JTable dataSearchResultTable;
public DateFormatDemo()
{
JPanel panel = new JPanel(new GridLayout(2, 1, 5, 10));
panel.setPreferredSize(new Dimension(500, 300));
panel.add(new JScrollPane(initDataSearchResultTable()));
super.getContentPane().add(panel);
super.pack();
super.setDefaultCloseOperation(EXIT_ON_CLOSE);
super.setVisible(true);
}
private JTable initDataSearchResultTable()
{
dataSearchResultTable = new JTable(new MyTableModel()) {
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
{
JComponent component = (JComponent) super.prepareRenderer(renderer, row, column);
// component.setBorder(emptyBorder);
return component;
}
};
dataSearchResultTable.setIntercellSpacing(new Dimension(5, 10));
dataSearchResultTable.setSelectionBackground(new Color(0xaaaaff));
dataSearchResultTable.setFillsViewportHeight(true);
dataSearchResultTable.setRowSelectionAllowed(true);
dataSearchResultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dataSearchResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
dataSearchResultTable.setDefaultRenderer(String.class, new DefaultTableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column)
{
JComponent component = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
component.setBorder(emptyBorder);
return component;
}
});
return dataSearchResultTable;
}
class MyTableModel extends AbstractTableModel
{
private String[] columnNames = { "First Name", "Last Name", "Timestamp", "Number", "Vegetarian" };
private Object[][] data ;
MyTableModel()
{
data = new Object[][] {
{ "Vova", "KipokKipokKipokKipok", Timestamp.valueOf("2013-04-12 11:20:41"), new Integer(5),
new Boolean(true) },
{ "Olia", "Duo", Timestamp.valueOf("2010-01-11 11:11:41"), new Integer(3), new Boolean(false) },
{ "Oksana", "Stack", Timestamp.valueOf("2012-04-12 11:20:41"), new Integer(2), new Boolean(false) },
{ "Petro", "White", Timestamp.valueOf("2010-04-12 11:20:21"), new Integer(20), new Boolean(true) },
{ "Ivan", "Brown", Timestamp.valueOf("2011-04-11 11:20:41"), new Integer(10), new Boolean(true) } };
fireTableDataChanged();
}
public int getColumnCount()
{
return columnNames.length;
}
public int getRowCount()
{
return data.length;
}
public String getColumnName(int col)
{
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
if (data.length > 0 && data[0] != null) {
return data[row][col];
}
return null;
}
/*
* JTable uses this method to determine the default renderer/ editor for
* each cell. If we didn't implement this method, then the last column
* would contain text ("true"/"false"), rather than a check box.
*/
public Class getColumnClass(int c)
{
Object valueAt = getValueAt(0, c);
return valueAt == null ? Object.class : valueAt.getClass();
}
/*
* Don't need to implement this method unless your table's editable.
*/
public boolean isCellEditable(int row, int col)
{
return true;
}
/*
* Don't need to implement this method unless your table's data can
* change.
*/
public void setValueAt(Object value, int row, int col)
{
if (data.length > 0 && data[0] != null) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
}
public static void main(String[] args) throws ParseException
{
new DateFormatDemo();
}
}
Does anybody know how to set space between cells so that cell's content is not erased?
SOLVED:
dataSearchResultTable.setRowHeight(25);
dataSearchResultTable.setRowMargin(5);
dataSearchResultTable.getColumnModel().setColumnMargin(20);
But rowMargin causes selected row to be narrower than row borders. The solution is to set rowHeight only without rowMargin. This ensures that selection is not narrower than row itself.
Thanks!
Instead of using setRowHeight() method as you mentioned, I recommend you to use next method for your table(found here):
private void updateRowHeights(JTable table ) {
for (int row = 0; row < table.getRowCount(); row++) {
int rowHeight = table.getRowHeight();
for (int column = 0; column < table.getColumnCount(); column++) {
Component comp = table.prepareRenderer(table.getCellRenderer(row, column), row, column);
rowHeight = Math.max(rowHeight,comp.getPreferredSize().height);
}
table.setRowHeight(row, rowHeight);
}
}
Because it calculates height for each row. In this case all your rows will be look fine.
When you use setRowHeight() isn't always solve problems of system default properties, try to add that line to your code for example and you will see what I mean dataSearchResultTable.setFont(new Font("Arial", 1, 25));
I need some help with my JTable. I am writing a program, wich extracts data from a database into a JTable. The first column should be a editable JCheckBox so I am able to work with the checked (true or false) rows and the data.
I am using a AbstractTableModel(with class extends AbstractTableModel) and override these five methods:
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0;
}
#Override
public Class<?> getColumnClass(int col) {
if (col == 0) {
return Boolean.class;
}
return super.getColumnClass(col);
}
#Override
public int getColumnCount() {
return header.length;
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
To display the JTable I use:
JTable table = new JTable();
JScrollPane scrollpane = new JScrollPane();
.
.
.
table = new JTable(data, header);
table.setModel(this);
scrollpane = new JScrollPane(table);
I read the data with a for loop into the data array. The header array I defined.
Basically I need the checked rows to send a mail with the right data in it.
EDIT:
package test;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
public class TestCode extends AbstractTableModel {
private static final long serialVersionUID = -7051817393770003705L;
String[] header = {"", "header", "header", "header"};
Object[][] data = {{new Boolean(false), "Text", "Text", "Text"}, {new Boolean(false), "Text", "Text", "Text"}, {new Boolean(false), "Text", "Text", "Text"}};
public TestCode() {
JFrame frame = new JFrame();
JTable table = new JTable(data, header);
table.setModel(this);
JScrollPane scrollpane = new JScrollPane(table);
frame.add(scrollpane);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
#Override
public boolean isCellEditable(int row, int col) {
return col == 0;
}
#Override
public Class<?> getColumnClass(int col) {
if (col == 0) {
return Boolean.class;
}
return super.getColumnClass(col);
}
#Override
public int getColumnCount() {
return header.length;
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
public static void main(String[] args) {
TestCode code = new TestCode();
}
}
This is a short snippet of my code to execute to make it easier for you. I want be able to check the JCheckBoxes at the firt column so I am able to read a true or false boolen from that column.
Thank you for help!
You have to override AbstractTableModel#setValueAt
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// super.setValueAt(aValue, rowIndex, columnIndex); by default empty implementation is not necesary if direct parent is AbstractTableModel
data[rowIndex][columnIndex] = aValue;
fireTableCellUpdated(rowIndex, columnIndex);// notify listeners
}
Result.
BTW : Don't use new Boolean(false) instead use Boolean.FALSE
Okay leaving aside the structure of the code (I agree that the creation of the table should not be done in the model and things should be separated out better) the reason this is not working is that your table model does not implement setValueAt(Object value, int row, int column).
So when you click on a cell, that method is called, but your data array is not updated so the value for the cell is always false.
Adding
#Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
}
to your model means the table behaves as you would expect
Simply add implementation of value setter
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
data[rowIndex][columnIndex] = aValue;
}
I am using DefaultTableModel as follows:
DefaultTableModel model = new DefaultTableModel (COLUMNS, 0 )
{
#Override
public boolean isCellEditable(int row, int column)
{
return (getColumnName(column).equals("Selected"));
}
public Class getColumnClass(int columnIndex)
{
if(getColumnName(columnIndex).equals("Selected"))
return Boolean.class;
return super.getColumnClass(columnIndex);
}
};
Now I want to make only one checkbox selectable in the column "Selected". How can this be done. I have tried following method also but its not working.
public void fireTableCellUpdated(int row,int column)
{
if(getColumnName(column).equals("Selected"))
{
for(int i = 0; i<getRowCount() && i!=row;i++)
setValueAt(Boolean.FALSE, row, column);
}
}
#eatSleepCode wrote #mKorbel can you please give example code for implementing setValueAt method.
code for (OP used) DefaultTableModel,
for code based on AbstractTableModel is required to hold code ordering for notifier fireTableCellUpdated(rowIndex, columnIndex);, because/otherwise nothing will be repainted in JTables view,
there are a few important differencies betweens those two models and its notifiers, and (my view) there isn't reason to bothering with and to use AbstractTableModel for basic stuff (99pct of table models)
. . . . . . . .
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class TableRolloverDemo {
private JFrame frame = new JFrame("TableRolloverDemo");
private JTable table = new JTable();
private String[] columnNames = new String[]{"Column"};
private Object[][] data = new Object[][]{{false}, {false}, {true}, {true},
{false}, {false}, {true}, {true}, {false}, {false}, {true}, {true}};
public TableRolloverDemo() {
final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
private boolean ImInLoop = false;
#Override
public Class<?> getColumnClass(int columnIndex) {
return Boolean.class;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
if (!ImInLoop) {
ImInLoop = true;
Boolean bol = (Boolean) aValue;
super.setValueAt(aValue, rowIndex, columnIndex);
for (int i = 0; i < this.getRowCount(); i++) {
if (i != rowIndex) {
super.setValueAt(!bol, i, columnIndex);
}
}
ImInLoop = false;
}
} else {
super.setValueAt(aValue, rowIndex, columnIndex);
}
}
};
table.setModel(model);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TableRolloverDemo tableRolloverDemo = new TableRolloverDemo();
}
});
}
}
You get an stack overflow exception because setValueAt() method triggers fireTableCellUpdated() method once again and again.
Instead, try using a table listener which would listen to check box's value change and would set all other check boxes' value to false.
You can create your own custom cell editor that joins all check boxes in a column in a ButtonGroup. here's how:
public class VeryComplicatedCellEditor extends DefaultCellEditor {
private ArrayList<ButtonGroup> groups;
public getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JCheckBox checkBox = new JCheckBox();
growToSize(column);
groups.get(column).add(checkBox);
return checkBox;
}
private growToSize(int size) {
groups.ensureCapacity(size);
while (groups.size() < size)
groups.add(new ButtonGroup());
}
}
There are some complications that come from the fact that we don't know how big the table is, which are mostly taken care of in the growToSize method.
The way this works is by maintaining a list of ButtonGroups, one for each column. The editor component for each cell is added to the button group for its column.
I have a JTable that uses an AbstractTableModel. I'm trying to make the first row of the table a row of JCheckboxes.
EDIT: The goal is to take the columns with checked checkboxes and create a new table. This is my first time trying something like this, so I'm open to suggestions.
Here is the code I'm trying in NetBeans 7.1.1 :
private void selectSourceCBActionPerformed(java.awt.event.ActionEvent evt) {
int sourceNum = selectSourceCB.getSelectedIndex();
DataSource currentDS = datSourceArrList.get(sourceNum);
final ArrayList<Object[]> workArrLst1 = currentDS.getSampSet();
sourceDetailTable.setAutoResizeMode(sourceDetailTable.AUTO_RESIZE_OFF);
sourceDetailTable.setColumnSelectionAllowed(true);
JTableHeader header = sourceDetailTable.getTableHeader();
AbstractTableModel mytable1 = new AbstractTableModel() {
Object colNames[] = workArrLst1.get(0);
#Override
public int getRowCount() {
return workArrLst1.size();
}
#Override
public int getColumnCount() {
return workArrLst1.get(1).length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return workArrLst1.get(rowIndex+1)[columnIndex];
}
#Override
public void setValueAt(Object value, int row, int col) {
if(row == 1){
workArrLst1.get(row)[col] = Boolean(false);
fireTableCellUpdated(row, col);
}
workArrLst1.get(row)[col] = (String) value;
fireTableCellUpdated(row, col);
}
#Override
public String getColumnName(int column) {
return (String) colNames[column];
}
};
}
Is there anything obvious I'm missing here?
I am trying to make all the cells of a JTable uneditable when double clicked by the user. I have read a lot of forum posts and the general consensus is to create a new table model class, extend DefaultTableModel and then override method isCellEditable(int row, int column). I did all of this and now when I run my program (applet) Nothing shows up in the cells. NOTE I have a prof this semester that does not think applets are outdated...
Code for the table model:
public class MyTableModel extends DefaultTableModel
{
public boolean isCellEditable(int row, int column) //override isCellEditable
//PRE: row > 0, column > 0
//POST: FCTVAL == false always
{
return false;
}
}
Code in my class: **NOTE** this class extends JPanel
private JScrollPane storesPane;
private JTable storesTable;
Code in the Constructor:
storesTable = new JTable(tableData, COL_NAMES); //tableData and COL_NAMES are passed in
storesTable.setModel(new MyTableModel());
storesPane = new JScrollPane(storesTable);
storesTable.setFillsViewportHeight(true);
add(storesPane, BorderLayout.CENTER);
Hopefully some of you Java Gurus can find my error :)
This line creates a new JTable and implicitly creates a DefaultTableModel behind the scenes, one that holds all the correct data needed for the JTable:
storesTable = new JTable(tableData, COL_NAMES);
And this line effectively removes the table model created implicitly above, the one that holds all of the table's data and replaces it with a table model that holds no data whatsoever:
storesTable.setModel(new MyTableModel());
You need to give your MyTableModel class a constructor and in that constructor call the super constructor and pass in the data that you're currently passing to the table in its constructor.
e.g.,
public class MyTableModel extends DefaultTableModel {
public MyTableModel(Object[][] tableData, Object[] colNames) {
super(tableData, colNames);
}
public boolean isCellEditable(int row, int column) {
return false;
}
}
Then you can use it like so:
MyTableModel model = new MyTableModel(tableData, COL_NAMES);
storesTable = new JTable(model);
Earlier today I had the same problem. This solved it for me.
JTable table = new JTable( data, headers ){
public boolean isCellEditable(int row, int column){
return false;
}
};
works great!
Just override the isCellEditable method of the DefaultTableModel class. The quick way to do this:
JTable table = new JTable();
DefaultTableModel dtm = new DefaultTableModel(0, 0) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
table.setModel(dtm);
Hello Friend am also working on table please try my code
import javax.swing.table.AbstractTableModel;
public class Table extends AbstractTableModel {
private boolean DEBUG = false;
private String[] columnNames = {" Date Time", " Parameter",
" Barometric Pressure (hPa)", " Temperature (°C)", " Battery Voltage (V)"};
public static Object[][] data = {};
public TableControllerViewdataTabTableModel() {
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
#Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
#Override
public boolean isCellEditable(int row, int col) {
return false;
}
#Override
/**
* The setValueAt.
*/
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
if (DEBUG) {
printDebugData();
}
}
/**
* The printDebugData.
*/
private void printDebugData() {
int numRows = getRowCount();
int numCols = getColumnCount();
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
}
}
}
}