我有一個行數為 x 的表,我有第二個表,行數相同但列和元資料不同,它們有不同的表模型。但每一行代表同一個物件(一首歌)。
我想在兩個表之間同步行排序,例如,如果我對表 1 的第 2 列進行排序,那么表的行將以相同的順序排序。但目前,我只是通過匹配的排序鍵排序,所以在同一列上排序(但因為不同的資料得到不同的結果)
例如
初始點
Table 1
1 tom
2 jane
3 fred
4 steve
5 jim
Table 2
1 oranges
2 apples
3 pears
4 lemons
5 plums
如果我按表 1 第 2 列升序排序,我想得到
Table 1
2 jane
5 jim
3 fred
4 steve
1 tom
Table 2
2 apples
5 plums
3 pears
4 lemons
1 oranges
但我明白了
Table 1
2 jane
5 jim
3 fred
4 steve
1 tom
Table 2
2 apples
4 lemons
1 oranges
3 pears
5 plums
我的排序是通過將表 2 上的 setSortKeys() 呼叫到表 1 的 getSortKeys() 來完成的,反之亦然。我知道為什么它不起作用,我告訴表 2 按與表 1 相同的第 2 列升序排序,但當然這些列在每個表中都有不同的資料。但我無法找到一種方法讓表 2 排序為表 1 的最終順序。
一種解決方案是兩個表共享相同的表模型并僅顯示與其表相關的列,但這需要對代碼進行重大修改,因此我希望有一個更具體的解決方案來解決排序問題。
我正在使用 Java 11 和 swingx 最新版本 1.6.4(我知道很舊),但這會將排序委托給標準 Java(我之前使用的早期版本有自己的排序),所以并不是一個真正的 swingx 問題。
在我的應用程式中,真實世界的情況如下,每一行代表一首歌曲,選項卡顯示該歌曲的元資料。編輯選單下的選項卡都共享相同的模型,并且都使用上述 setSortKeys() 方法作業。所以在這里我在Mood Aggressive列上進行了排序
編輯元資料選項卡
如果我轉到另一個選項卡,我們會看到行以相同的順序排序
另一個編輯元資料選項卡,排序相同
但如果我轉到 Edit ID3 選項卡,我們會看到行已按不同順序排序。
ID3 編輯選項卡排序不同的順序
這是因為 ID3 Edit 選項卡以不同的格式 (ID3) 顯示元資料并且具有不同的表模型,因此模型中表示的列 x 存盤不同的資料。
請注意,因為所有模型都將 rowno 存盤在第一列中,所以對我的 rowno 列進行排序適用于所有選項卡。
因此,從用戶的角度來看,他們只是查看同一個表的不同選項卡,因此希望選項卡的排序是一致的
uj5u.com熱心網友回復:
我想出了以下方法,該方法rowIndex使用第一個表轉換為第二個rowSorter表。
TableOneModel tableOneData = new TableOneModel( /* omitted */ );
JTable tableOne = new JTable(tableOneData);
TableRowSorter<TableOneModel> sorterOne = new TableRowSorter<>(tableOneData);
tableOne.setRowSorter(sorterOne);
TableTwoModel tableTwoData = new TableTwoModel(
/* omitted */,
sorterOne);
JTable tableTwo = new JTable(tableTwoData);
第一個表的模型是實作所需方法TableOneModel的子類:AbstractTableModel
private static class TableOneModel extends AbstractTableModel {
private final String[] columnNames;
private final Object[][] data;
public TableOneModel(String[] columnNames, Object[][] data) {
this.columnNames = columnNames;
this.data = data;
}
public int getRowCount() { return data.length; }
public int getColumnCount() { return columnNames.length; }
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
}
第二個表的模型TableTwoModel,存盤對rowSorter第一個表的參考以進行行索引的轉換:
private static class TableTwoModel extends TableOneModel
implements RowSorterListener {
private final RowSorter<? extends TableModel> otherSorter;
public TableTwoModel(String[] columnNames, Object[][] data,
RowSorter<? extends TableModel> sorter) {
super(columnNames, data);
this.otherSorter = sorter;
installListeners();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return super.getValueAt(
otherSorter.convertRowIndexToModel(rowIndex),
columnIndex);
}
private void installListeners() {
otherSorter.addRowSorterListener(this);
}
@Override
public void sorterChanged(RowSorterEvent e) {
fireTableDataChanged();
}
}
當第一個表的排序順序發生變化時,第二個表模型呼叫fireTableDataChanged()通知視圖它需要更新所有資料。
編輯:正如保羅在評論中提到的,第二個表的排序順序也應該改變第一個表。所以同步應該雙向作業。
在更新版本中,兩個表都使用TableTwoModel和第一個表將自己標識為前導表. (正如我一直在寫更新,我意識到這沒有必要。)因此,實作TableTwoModel基本保持不變。我更改sorterChanged為僅TableTwoModel呼叫表排序完成時的事件型別。這是一個小優化。fireTableDataChanged()SORTED
棘手的部分是同步/重置RowSorter表格。然而,解決方案被證明非常簡單。這是通過安裝RowSorterListener到每個行排序器來實作的。如果事件型別是,并且thisSORT_ORDER_CHANGED的排序鍵串列非空,則將 other 的排序鍵設定為 null。因此,只有一張表被排序,而另一張表按照排序后的排序順序排列。RowSorter
uj5u.com熱心網友回復:
這是我在評論中的意思:
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);
}
}
uj5u.com熱心網友回復:
有一個原型作業。
所以使用swingx我們實作了一個子類TableSortController并覆寫toggleSortOrder()并將其設定為主表的rowSorter
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);
}
邏輯是對主表進行正常排序,然后在第二個表上設定隱藏列來存盤每一行??的視圖索引。然后洗掉第二個表上的任何現有排序,然后按隱藏列排序。
請注意,需要對 setSortKey() 進行兩次呼叫,因為如果您按主表上的一列排序,然后在這兩種情況下進行另一次排序,則會按 INDEX_SYNC_SORT 升序對第二個表進行排序,因此超類中的以下代碼DefaultRowSorter.setSortKeys()
將阻止排序完成因為排序鍵將與之前的排序相同
if (!this.sortKeys.equals(old)) {
fireSortOrderChanged();
if (viewToModel == null) {
// Currently unsorted, use sort so that internal fields
// are correctly set.
sort();
} else {
sortExistingData();
}
}
現在在這個原型中,我們有一個默認的排序控制器,SecondTable因為我們不希望它也進行特殊處理。但可能想要對兩者進行排序,因此需要 toggleSort() 代碼來檢查它們鏈接到的表并采取相應措施。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/429902.html
