I have a problem with the selection of rows on my JTable instances.
This is what I would like to to:
I want to have two equal tables with the same data in the rows. When you select a row on the first table, e g the third row, I also want the third row on the second table to be selected automatically. I have solved this by adding a ListSelectionListener
to the JTable that updates a class that just hold the selected value. Then that class triggers the other JTable with the selected value from the first.
What my problem is:
My problem occurs when the user sorts the rows on one of the tables. Then the view changes, but not the underlying objects in the model, that has the same order as before.
Let´s say the tables looks like this when I start the application:
Column_1_header_in_table_1 Column_1_header_in_table_2
Peter Peter
John John
Steve Steve
When selecting the first row in table 1
(which is Peter), then the row containing Peter shall be selected on table 2
which is also the first row.
But if I press the column header on table 1
so the column is sorted, then the view of that table changes to this:
Column_1_header_in_table_1 Column_1_header_in_table_2
John Peter
Steve John
Peter Steve
Now, if I select the first row in table 1
(that is John), the first row in table 2
will be selected (that is Peter). But I want the row with the same name as in table 1
to be selected on table 2
, which is row 2 on table 2
.
Is there some approach I can use to tackle this problem?
EDIT
Ok, I will try to describe my solution with the below code that I have written without an editor, so I may contain some errors. But I just want to show conceptually how it works right now.
First I have done this interface that the MyTable implements:
public interface TableUpdater {
public void updateTable(int age);
}
The PersonHolder class just holds the last selected value and triggers the other table when a new value is selected from the first.
public class PersonHolder {
private static int age;
private List<TableUpdater> tables = new ArrayList<>();
public static void subscribe(TableUpdater table){
tables.add(table);
}
public static void setValue(int value){
age = value;
for(TableUpdater table : tables) {
table.updateTable(age);
}
}
public static int getValue(){
return age;
}
}
Then we have the Table itself:
public class MyTable extends JTable implements TableUpdater {
public MyTable {
table.getSelectionModel().addListSelectionListener(new MySelectionListener());
PersonHolder.subscribe(this);
}
...
@Override
public void updateTable(int age) {
this.getSelectionModel().setSelectionInterval(age, age);
}
private class MySelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
Person p = (Person)getValueAt(e.getLastIndex(), 0);
PersonHolder.setValue(p.getAge());
}
}
}
You should use:
javax.swing.JTable.convertRowIndexToModel(int)
to convert the current selection index to a model index value and then, in the other table, convert the model index back to a view index withjavax.swing.JTable.convertRowIndexToView(int)
and set that index as the selected row (this assuming that the model in both tables is the same or is equivalent, otherwise you will have to make a look-up based on values).Here is an example of what I have in mind (I even shuffled the baseModel of both JTable's and perform an index lookup in the other one):