我在JTable实例上选择行时遇到问题。
这就是我想要的: 我想在行中有两个相等的表,并且它们的数据相同。当您在第一张表上选择一行时,例如第三行,我也希望第二张表上的第三行被自动选择。我通过ListSelectionListener在JTable中添加一个更新了仅包含所选值的类的方法解决了这一问题。然后,该类使用从第一个中选择的值来触发另一个JTable。
ListSelectionListener
我的问题是: 用户对表之一进行排序时,会发生我的问题。然后,视图发生改变,但模型中的基础对象没有改变,其顺序与以前相同。
假设当我启动应用程序时,表格如下所示:
Column_1_header_in_table_1 Column_1_header_in_table_2 Peter Peter John John Steve Steve
当选择第一行table 1(即Peter)时,则应选择包含Peter的行table 2,第一行也是第一行。 但是,如果我按列标题,table 1以便对列进行排序,那么该表的视图将更改为:
table 1
table 2
Column_1_header_in_table_1 Column_1_header_in_table_2 John Peter Steve John Peter Steve
现在,如果选择其中的 第一 行table 1(即John),table 2则将选择其中的第一行(即Peter)。但我希望在table 1上选择与in具有相同名称的行table 2,即上的第2行table 2。
有什么办法可以解决这个问题?
编辑
好,我将尝试使用下面没有编辑器编写的代码来描述我的解决方案,因此我可能会包含一些错误。但是我只想从概念上展示它现在如何工作。首先,我完成了MyTable实现的接口:
public interface TableUpdater { public void updateTable(int age); }
PersonHolder类仅保留最后一个选择的值,并从第一个选择新值时触发另一个表。
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; } }
然后,我们有了表本身:
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()); } } }
您应该使用:javax.swing.JTable.convertRowIndexToModel(int)将当前选择索引转换为模型索引值,然后在另一个表中,将模型索引转换回为的视图索引,javax.swing.JTable.convertRowIndexToView(int)并将该索引设置为选定行(假设两个表中的模型相同或相等,否则您将不得不根据值进行查找)。
javax.swing.JTable.convertRowIndexToModel(int)
javax.swing.JTable.convertRowIndexToView(int)
这是我想到的一个示例(我什至改组了两个JTable的baseModel并在另一个中执行了索引查找):
import java.awt.BorderLayout; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; public class TestSortedTable { class MyTableModel extends AbstractTableModel { private List<Person> baseModel; public MyTableModel(List<Person> baseModel) { super(); this.baseModel = new ArrayList<Person>(baseModel); } @Override public int getRowCount() { return baseModel.size(); } @Override public String getColumnName(int column) { switch (column) { case 0: return "First Name"; case 1: return "Last Name"; } return null; } @Override public int getColumnCount() { return 2; } @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case 0: return getPersonAtIndex(rowIndex).getFirstName(); case 1: return getPersonAtIndex(rowIndex).getLastName(); } return null; } public Person getPersonAtIndex(int rowIndex) { return baseModel.get(rowIndex); } public int getIndexOfPerson(Person person) { return baseModel.indexOf(person); } } protected void initUI() { List<Person> personModel = new ArrayList<TestSortedTable.Person>(); personModel.add(new Person("John", "Smith")); personModel.add(new Person("Peter", "Donoghan")); personModel.add(new Person("Amy", "Peterson")); personModel.add(new Person("David", "Anderson")); JFrame frame = new JFrame(TestSortedTable.class.getSimpleName()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Collections.shuffle(personModel); final MyTableModel table1Model = new MyTableModel(personModel); final JTable table1 = new JTable(table1Model); table1.setAutoCreateRowSorter(true); Collections.shuffle(personModel); final MyTableModel table2Model = new MyTableModel(personModel); final JTable table2 = new JTable(table2Model); table2.setAutoCreateRowSorter(true); table1.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } int index = table1.getSelectedRow(); if (index > -1) { int table1ModelIndex = table1.convertRowIndexToModel(table1.getSelectedRow()); Person p = table1Model.getPersonAtIndex(table1ModelIndex); int table2ModelIndex = table2Model.getIndexOfPerson(p); int indexInTable2 = table2.convertRowIndexToView(table2ModelIndex); table2.getSelectionModel().setSelectionInterval(indexInTable2, indexInTable2); } } }); table2.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } int index = table2.getSelectedRow(); if (index > -1) { int table2ModelIndex = table2.convertRowIndexToModel(table2.getSelectedRow()); Person p = table2Model.getPersonAtIndex(table2ModelIndex); int table1ModelIndex = table1Model.getIndexOfPerson(p); int indexInTable1 = table1.convertRowIndexToView(table1ModelIndex); table1.getSelectionModel().setSelectionInterval(indexInTable1, indexInTable1); } } }); frame.add(new JScrollPane(table1), BorderLayout.WEST); frame.add(new JScrollPane(table2), BorderLayout.EAST); frame.pack(); frame.setVisible(true); } public class Person { private final String firstName; private final String lastName; public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new TestSortedTable().initUI(); } }); } }