Javax Swing JTable::getModel vs JTable::getColumnModel - java

Hello I have been working with javax swing and I came across a weird problem and got me questioning.
I can for example:
JTable table = new JTable();
// Indeed, 2 different objects:
// The TableModel (which, i think is supposed to contain rows and columns?
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
// And the column model, supposed to define the columns of a table?
TableColumnModel tcm = table.getColumnModel();
// I can add columns to my table in two different manners
dtm.addColumn("A Column");
// or
TableColumn column = new TableColumn();
column.setHeaderValue("Another column");
column.setWidth(120);
column.setMinWidth(120);
column.setMaxWidth(120);
tcm.addColumn(column);
// And notice that both commands will add a column in the table
// So our table model should now have 2 columns.
// But does it?
System.out.println(dtm.getColumnCount()); // outputs 1;
System.out.println(tcm.getColumnCount()); // outputs 2;
System.out.println(table.getColumnCount()); // outputs 2;
// The visual shows 2 columns, but the model has only 1.
From that I can tell JTable uses tableColumnModel and tableColumnModel gets all the columns added into tableModel, but, when I add a column to the TableModel it gets added to the table, but the tableModel remains outdated.
Now, the problem is: it's really interesting to add a column via columnModel because I can define the sizes, layout, editable options there, but in this way I cannot add any data to it from the tableModel, since that column doesn't appear on the tableModel.
Any thoughts on this?

The TableModel is used to contain data. The data is accessible in row/columns.
The TableColumnModel is used by JTable to control the View of the data. That is it controls the columns that are displayed in the JTable. You can also reorder the columns to display the data in a different order.
...but in this way I cannot add any data to it from the tableModel, since that column doesn't appear on the tableModel
That is correct. The purpose of the TableColumnModel is to simply customize the view, not manipulate data.
Maybe you have an application that contains many columns of data, but access to specific columns is limited by "security level". In this case the data is always stored in the TableModel, but you need to change the view to control which columns of data are visible. So you can remove/add columns from the TableColumnModel.
When you add a column to the TableModel, the JTable gets notified and it recreates all the TableColumns for you. This can be a good or bad thing because when the TableColumnModel is recreated you lose any custom renderers and editor that you may have added to a TableColumn. You can prevent this from happening buy using:
table.setAutoCreateColumnsFromModel( false );
Now the TableColumnModel will not be updated and it is your responsibility to manually create and add the TableColumn to the TableColumnModel.
But in general you:
add/change data through the TableModel.
change the view through the TableColumnModel.

Related

Recreate Jtable or remove all rows and add new rows?

I have a JTable and a DefaultTableModel, I want to delete all the rows of JTable every 3 secondes and add new rows to the JTable. Considering the performance, What's the best choice to do that, recreate Jtable or remove all rows and add rows?
What's the best choice to do that, renew Jtable or remove all rows and addrows?
If you recreate the JTable, all the renderers and editors will be recreated for the table.
If you change the TableModel, then the table will need to recreate the TableColumnModel, and all the TableColumns based on the new TableModel.
There will be many more objects that need to be created to support the JTable/TableModel relationship.
Removing rows and adding rows, will just cause the table to repaint the new data using all the current renderers. I would say this is more efficient. And instead of adding rows one at a time, you should add all the rows at once
You can create a tablemodel that digs into your data object. As soon as you change the underlying data object, you call fireTableDataChanged().
From the JavaDoc for AbstractTableModel#fireTableDataChanged():
Notifies all listeners that all cell values in the table's rows may have changed. The number of rows may also have changed and the JTable should redraw the table from scratch. The structure of the table (as in the order of the columns) is assumed to be the same.

java swing jtable - display row index for each row

I'm working on a java desktop application and I have a Swing JTable for displaying data. I need to have a column for displaying row index for each row in the table. I don't want to add index in the grid data. Here is the way that I'm using to fill my table:
private DefaultTableModel defaultTableModel = new DefaultTableModel();
defaultTableModel.setDataVector(dataArray, headerArray);
jTable.setModel(defaultTableModel);
JTable displays what the TableModel tells it to display. Instead, extend AbstractTableModel. In your implementation of getValueAt(), return the row number for column zero and return the appropriate element of dataArray otherwise. Related examples may be found here and here.
You can add a row header to the scroll pane to display numbers for each row in the table.
Any component can be added to the row header. So one solution is to add a second (custom) JTable that just displays row numbers with a custom renderer so that the number look like the column headers.
Check out Row Table Number for an example of this approach.

Equivalent of getSelected column method of JTable in DefaultTableModel

I was re designing my codes with formerly using
JTable jtable = new JTable();
int selectedIndex = jtable.getSelectedColumn();
//implementations
Now, I need to use DefaultTableModel. Is there a method or implementation that is related to this method of JTable? Thanks!
A TableModel has nothing to do with the selected column of the JTable.
It doesn't matter what TableModel you use with the JTable, you still use
int selectedIndex = table.getSelectedColumn();
method to get the selected column.
Of course, there is no selected column when you first create the JTable. The user must select the column or you must set the selection on a particular cell of the table.
So you only use the getSelectedColumn() method in response to some kind of user event.

The best way to set rows and headers separately after JTable creation?

It means I need setData and setHeaders functions for JTable
Like Gilbert says, there is no method of the AbstractTableModel that will allow you to set the values of the headers after the JTable is up, since it is not a very common requirement. Still there is a simple work-around to that. I can not say if it is the best way to do it, but it will get you there...
columnNumber is the number of the column you want to change and newHeaderString is the new String you want to use.
jTable1.getColumnModel().getColumn(columnNumber).setHeaderValue(newHeaderString);
jScrollPane1.setViewportView(jTable1);
Since there is a getTableHeader() method, you could call it if you need to further modify your table header properties.
As for setting new data in any row, use jTable1.setValueAt(newObject, row, col);
if you use a TableModel, you can change the data contents, but not the column headers.
TableModel model = new DefaultTableModel(rowData, columnNames);
JTable table = new JTable(model)
rowData and columnNames have to be defined before you create the table.
The TableModel interface has a setValueAt method. The TableModel interface has no method for setting column names.

JTable how to hide column in view but keep it in model for use it in background

I have a JTable and am passing a data array into the TableModel. I wish to retain all columns in the data model as I need them all for background data processing, but I wish to show only some of the columns in the JTable.
How do I achieve this -- to remove a data column from the view (the visualized JTable) but not from the model (the TableModel)?
JTable has
public void removeColumn(TableColumn aColumn)
Override getColumnCount of the model to return less columns that there is. Then put your hidden columns as last columns of the model.

Categories

Resources