I have a table with x num of rows, I have a second table with the same number of rows but different columns and metadata, they have different table models. but each row represents the same object (a song).
I want to synchronize row sorting between the two tables so for example if I sort on column 2 of table 1 then rows of the table will be sorted in the same order. But currently, I just have sorted by matching sort keys so sort on the same column (but because different data get different results)
e.g
Starting point
Table 1
1 tom
2 jane
3 fred
4 steve
5 jim
Table 2
1 oranges
2 apples
3 pears
4 lemons
5 plums
If I sort by table 1, column 2 Ascending I want to get
Table 1
2 jane
5 jim
3 fred
4 steve
1 tom
Table 2
2 apples
5 plums
3 pears
4 lemons
1 oranges
but I get
Table 1
2 jane
5 jim
3 fred
4 steve
1 tom
Table 2
2 apples
4 lemons
1 oranges
3 pears
5 plums
My sorting is done by calling setSortKeys() on table 2 to the getSortKeys() of table 1 and vice versa. I can see why it doesn't work, I am telling table 2 to sort by column 2 ascending the same as table 1 but of course these columns have different data in each table. But I can't work out a way to get table 2 to sort to the final order of table 1 instead.
One solution would be for both tables to share the same table model and just show the columns relevant to their table, but that would require a major rework of the code, so I am hoping for a more specific solution just to resolve the sorting issue.
I am using Java 11, and swingx latest version 1.6.4 (i know very old) but this delegates sorting to standard Java (earlier version that I was previously using had its own sorting) so not really a swingx question.
The real world situation, within my application is as follows, each row represents a song, and the tabs show metadata for that song. the tabs under the edit menu all share same model and all work using the setSortKeys() method described above. So here i have sorted on Mood Aggressive column
Edit metadata tab
and if I go to another tab, we see the rows are sorted in same order
Another Edit metadata tab, sorted same order
but if I go to the Edit ID3 tab, we see the rows have been sorted in different order.
ID3 Edit tab sorted different order
This is because ID3 Edit tab shows the metadata in different format (ID3) and has different table model so column x represent in the model stores different data.
Note because all models store the rowno in first column, sorting my the rowno column works for all tabs.
So from a user point of view they are just viewing different tabs of the same table, and therefore would expect sort to be consistent for the tabs
CodePudding user response:
Here is what I meant in the comments:
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import java.awt.*;
public class TablesExample extends JPanel {
static class MyTableModel extends AbstractTableModel {
private String[] columnNames = {"Row Id",
"Person",
"Fruit"};
private Object[][] data = {
{"1", "Tom", "Orange"},
{"2", "Jane", "Apple"},
{"3", "Fred", "Pear"},
{"4", "Steve", "Lemon"},
{"5", "Jim", "Plum"}
};
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) {
return data[row][col];
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Tables Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setPreferredSize(new Dimension(500, 100));
TablesExample newContentPane = new TablesExample();
newContentPane.setOpaque(true);
MyTableModel model = new MyTableModel();
TableRowSorter<MyTableModel> sorter = new TableRowSorter<>(model);
JTable table = new JTable(model);
table.setRowSorter(sorter);
TableColumn column2 = table.getColumnModel().getColumn(2);
column2.setMinWidth(0);
column2.setMaxWidth(0);
column2.setWidth(0);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(table);
tabbedPane.add("Persons", scrollPane);
JTable table2 = new JTable(model);
table2.setRowSorter(sorter);
TableColumn column1 = table2.getColumnModel().getColumn(1);
column1.setMinWidth(0);
column1.setMaxWidth(0);
column1.setWidth(0);
JScrollPane scrollPane2 = new JScrollPane();
scrollPane2.setViewportView(table2);
tabbedPane.add("Fruits", scrollPane2);
frame.setContentPane(tabbedPane);
frame.pack();
frame.setVisible(true);
}
}
CodePudding user response:
Have a prototype working.
So using swingx we implement a subclass of TableSortController
and override toggleSortOrder()
and set this as the rowSorter of the main table
public void toggleSortOrder(int column)
{
.........
setSortKeys(newKeys);
for(int i=0; i < getModelWrapper().getRowCount(); i )
{
SecondTable.instanceOf().getRealModel()
.setValueAt(convertRowIndexToView(i), i, ID3TagNames.INDEX_SYNC_SORT);
}
newKeys = new ArrayList<>();
SecondTable.instanceOf().getTable().getRowSorter().setSortKeys(newKeys);
newKeys.add(new SortKey(ID3TagNames.INDEX_SYNC_SORT, this.getFirstInCycle()));
SecondTable.instanceOf().getTable().getRowSorter().setSortKeys(newKeys);
}
Logic is does a normal sort on main table, then sets hidden column on second table to store the view index of each row. Then remove any existing sort on second table, then sort by hidden column.
Note the two calls to setSortKey() are needed because if you sort by one column on main table, and then do another sort in both cases will be sorting second table by INDEX_SYNC_SORT ascending and hence the following code in superclass DefaultRowSorter.setSortKeys()
will prevent a sort being done because the sortkey will be the same as previous sort
if (!this.sortKeys.equals(old)) {
fireSortOrderChanged();
if (viewToModel == null) {
// Currently unsorted, use sort so that internal fields
// are correctly set.
sort();
} else {
sortExistingData();
}
}
For now in this prototype we have a default sort controller on the SecondTable
as we don't want this to do the special processing as well. But probably want to sort on both and therefore would need the toggleSort() code to check what table they are linked to and act accordingly.