I have a DefaultTableModel which is populated with an Object[][] array.
Now I want to add a column with checkBoxes and perform operations accordingly.
When I add the checkbox into the Object[][] array and view it, I get text displayed
'javax.swing.JCheckBox[,0,0,0x0....', how do I get it to show a checkbox and add actions to it?
JTable have default checkbox renderer/editor for boolean values. Just make your TableModel#getColumnClass return Boolean.class for given column.
how do I get it to show a checkbox
See Uhlen's answer
and add actions to it?
Use a TableModelListener. Something like:
public void tableChanged(TableModelEvent e)
{
if (e.getType() == TableModelEvent.UPDATE)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == ?)
{
TableModel model = (TableModel)e.getSource();
Boolean value = (Boolean)model.getValueAt(row, column));
if (value.booleanValue())
// add your code here
}
}
}
You could also just get the class, instead of hard coding each return type. Here is an example for the override method :
//create the table
DefaultTableModel tableModel = new DefaultTableModel(data, columnNames)
//override the method
{
public Class<?> getColumnClass(int colIndex) {
return getValueAt(0, colIndex).getClass();
}
Then, when you create the table you initialize it this way:
data[i][12] = new Boolean(false);
which makes the box appear unticked :)
You could use a custom table cell renderer.
See here
http://www.exampledepot.com/egs/javax.swing.table/CustRend.html
No you cannot provide swing component as model object[] array. That should be registered as cell editor on column.
Anyway by default DefaultTableModel supports checkbox as editor for columns under which Boolean class type values are stored.
So, in the array pass Boolean.TRUE/Boolean.FALSE object and set table as editable. Then table automatically renders checkbox for you.
Are you need to register editor for each class type
Related
I want to disable the possibility to select particular columns in a Jtable.
It's easy to disable the selection of certain rows with using the DefaultListSelectionModel class
But I don't know how to do that for columns.
Can any one give me a clue to implement this feature ?
You can override the method isCellEditable and implement as you want for example,
try this :
DefaultTableModel tableModel = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
//Only the column nb 2
return column == 2;
}
};
table.setModel(tableModel);
I have a JTable with a model created like this :
DefaultTableModel model = new DefaultTableModel(new Object[][] {},new String[] {"Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "Col7", "Col8"}) {
#Override
public Class<?> getColumnClass(int column) {
switch (column) {
case 0: return ImageIcon.class;
case 7: return JButton.class;
default: return String.class;
}
}
};
table = new JTable(model);
But when I use the addRow method, My ImageIcon appears properly but not the JButton. In fact, I get something like javax.Swing.JButt... instead of the JButton!
When you are adding a new row, it is being populated correctly. (You can see the ImageIcon).
So, the JButton object is also being inserted correctly.
The only difference here, JTable does not know how to display it or handle events on it.
That is why JTable calls toString() method on JButton and displays the text (as you mentioned).
javax.swing.JButt......
To overcome this problem, we need to supply two additional objects to the JTable.
TableCellEditor to handle events.
TableCellRenderer to handle painting.
You can find additional information about implementation details here : How to use custom JTable cell editor and cell renderer
Hope this helps.
Good luck.
Edit in response to the comment.
table.getColumnModel().getColumn(7).setCellRenderer(new MyCellRenderer());
// Put painting logic in MyCellRenderer class.
This way you can assign different renderer objects to different columns.
The problem is that JTable doesn’t support a button renderer or editor. You can overcome it using a custom cell editor, ButtonColumn : http://tips4java.wordpress.com/2009/07/12/table-button-column/
Background
I have a JTable called table, and I have a column that is not part of the DefaultTableModel so its invisible:
final JTable table = new JTable(new DefaultTableModel(new Object[]{"Title", "Artist",
"Album", "Time"}, 0)
I add the respective rows like this:
int upTo = songList.size();
int idx = 0;
while (idx < upTo) {
SongObject curSong = songList.get(idx);
model.addRow(new Object[]{
curSong.toString(),
curSong.getArtist(),
"-",
curSong.getDuration(),
curSong});
idx++;
}
Where curSong is the the current song object that it is adding, the SongObject contains all data about the song. The toString() returns the title of the song.
Problem:
The problem is that when I try to access the column like this:
SongObject songToPlay = (SongObject) table.getModel().getValueAt(table.getSelectedRow(), 4);
It throws a java.lang.ArrayIndexOutOfBoundsException: 4 >= 4 exception.
Can anyone explain why and propose a solution?
Thanks in advance :)
DefaultTableModel.addRow() somewhere down the chain executes private justifyRows() method, which trims the unused columns from the row to the size equal to getColumnCount(). So the fifth column is never added to the model. As a result, you get ArrayIndexOutOfBoundsException when you're attempting to access this column.
If you need access to the actual SongObject then you can have a custom model that would return SongObject for a given row index. Make an extension of AbstractTableModel. See How to Use Tables tutorial for examples.
As an alternative, you can still use SongObject in a visible column. Just use a custom renderder that would renderer SongObject as a string for example. See Using Custom Renderers for details. You can reuse DefaultTableModel in this case.
Thanks to Aqua I overrode the following:
final JTable table = new JTable(new DefaultTableModel(new Object[]{"Title", "Artist", "Album", "Time"}, 0) {
#Override
public void addRow(Object[] rowData) {
Vector blah = DefaultTableModel.convertToVector(rowData);
insertRow(super.getRowCount(), blah);
}
#Override
public void insertRow(int row, Vector data) {
super.dataVector.insertElementAt(data, row);
super.fireTableRowsInserted(row, row);
}
});
Then I accessed the item in the fifth column (which is not part of the model!) like this:
SongObject songToPlay = (SongObject) table.getModel().getValueAt(table.convertRowIndexToModel(
table.getSelectedRow()), 4); //get the value at the VIEW location NOT THE MODEL collection
Sorry for the messy code but it worked. Home I could help someone with a similar problem. The solution just misses the justifyRows() method found in DefaultTableModel
I want to prevent column from being resized larger than 10px. I want it to be small because it contains only checkbox.
I instantiate JTable here:
private void initDataSearchResultTable()
{
dataSearchResultTable = new JTable();
dataSearchResultTable.setSelectionBackground(new Color(0xaaaaff));
dataSearchResultTable.setFillsViewportHeight(true);
dataSearchResultTable.setRowSelectionAllowed(true);
dataSearchResultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dataSearchResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
I set Table model for table(when user clicks button) here:
void updateDataSearchTableModel(CachedRowSet cachedRowSet)
{
TableModel tableModel = dataSearchResultTable.getModel();
if (tableModel instanceof DataSearchTableModel) {
((DataSearchTableModel) tableModel).updateModel(cachedRowSet);
} else {
tableModel = new DataSearchTableModel(cachedRowSet);
dataSearchResultTable.setModel(tableModel);
this.setCellRendererForDataSearchTable();
((DataSearchTableModel) tableModel).structureChanged();
}
}
In method structureChanged() I call method fireTableStructureChanged(). This ensures that boolean columns are rendered as check boxes.
Next I try to set width of 0 and 1 columns and make them resizable. It doesn't work:
private void setCellRendererForDataSearchTable()
{
DataSearchResultTableCellRenderer cellRenderer = new DataSearchResultTableCellRenderer();
TableColumnModel columnModel = dataSearchResultTable.getColumnModel();
for (int i = 0; i < columnModel.getColumnCount(); i++) {
TableColumn column = columnModel.getColumn(i);
if (i == 0) {
column.setMaxWidth(15);
column.setResizable(false);
} else if (i == 1) {
column.setMaxWidth(30);
column.setResizable(false);
}
column.setCellRenderer(cellRenderer);
}
}
My renderer sets only border for selected cells.
My table model is more interesting:
public DataSearchTableModel(CachedRowSet cachedRowSet)
{
this.cachedRowSet = cachedRowSet;
updateModel(this.cachedRowSet);
}
public void updateModel(CachedRowSet cachedRowSet)
{
try {
metaData = this.cachedRowSet.getMetaData();
this.numOfCols = metaData.getColumnCount();
// Retrieve the number of rows.
this.cachedRowSet.beforeFirst();
this.numOfRows = 0;
while (this.cachedRowSet.next()) {
this.numOfRows++;
}
this.cachedRowSet.beforeFirst();
} catch (SQLException e) {
e.printStackTrace();
}
}
But this doesn't work, those columns are still resized and with wrong width?
Thanks!
In method structureChanged() I call method
fireTableStructureChanged(). This ensures that boolean columns are
rendered as check boxes.
(and...............)
But this doesn't work, those columns are still resized and with wrong
width?
with JTable.setModel(model) call or upon receiving the event fired by fireTableStructureChanged function call, if autoCreateColumnsFromModel is set(true) JTable will discards any table columns that it had prior to these function call and reallocates default columns in the order they appear in the model. Which means all the options related to column(width, renderer, etc) you set to the column previously will be lost. Setting autoCreateColumnsFromModel flag to false should be sufficient. To set or unset this flag use:
JTable.setAutoCreateColumnsFromModel(boolean)
Or, you may need to reset all the options to column after these function call.
Reference:
public void fireTableStructureChanged()
You can use:
public void resizeColumn(JTable tbl, int column) {
tbl.getColumnModel().getColumn(column).setPrefferedSize(new Dimension(/*width*/, /*height*/));
}
I found solution.
You should never call fireTableStructureChanged after you customize your TableColumns.
But to update table after its model and renderer was set you need fireTableStructureChanged.
So at first set cell renderers then call fireTableStructureChanged to make boolean columns displaed with checkboxes and only then change your TableColumns.
It will work.
I am trying to use an update method on my jtable that's connected to the database and would like to fill in the textfields on the form depending on which row the users clicks. I understand I will be needing a getValueAt() method however I am uncertain of how to fill in which row depending on which row the user clicks. I am unable to find anything on Google or anything so any information would be helpful!
private final UrTableModel urTableModel;
private JTable urTable;
...
// 1. Create your table model class that should extends from DefaultTableModel, instantiate it
urTableModel=new UrTableModel();
// 2. creates table
table = TableUtils.createStandardSortableTable(urTableModel);
// 3. customize your table
table.setBackground(Color.WHITE);
table.getTableHeader().setReorderingAllowed(false);
// 4. Add the mouse listner to it
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(final MouseEvent e) {
if (e.getClickCount() == 1) {
final JTable target = (JTable)e.getSource();
final int row = target.getSelectedRow();
final int column = target.getSelectedColumn();
// Cast to ur Object type
final UrObjctInCell urObjctInCell = (UrObjctInCell)target.getValueAt(row, column);
// TODO WHAT U WANT!
}
}
});
Cheers,
You will need to call getValueAt() your table's model to get the values you need. You will also need a listener on the table to listen for selections. So that once a user selects a row you call getValueAt() to get the value for the specific column of data in that row.