Java JTable无法正确返回所选行
我正在使用DefaultTableModel的扩展,如下所示: 这是更新后的新AchievementAttableModel,以反映一些答案的输入Java JTable无法正确返回所选行,java,user-interface,jtable,selection,Java,User Interface,Jtable,Selection,我正在使用DefaultTableModel的扩展,如下所示: 这是更新后的新AchievementAttableModel,以反映一些答案的输入 public AchievementTableModel(Object[][] c, Object[] co) { super(c,co); } public boolean isCellEditable(int r, int c) {return false;} public void replace(Object[][] c, Objec
public AchievementTableModel(Object[][] c, Object[] co) {
super(c,co);
}
public boolean isCellEditable(int r, int c) {return false;}
public void replace(Object[][] c, Object[] co) {
setDataVector(convertToVector(c), convertToVector(co));
fireTableDataChanged();
}
我的GUI是一个JTable,具有以下属性:
if(table==null)
table = new JTable(model);
else
table.setModel(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
table.getTableHeader().setReorderingAllowed(false);
table.getTableHeader().setResizingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
我有一个JComboBox,用于选择要显示的数据。通过调用model.replace(单元格)更新TableModel,然后再次运行上述表格创建代码
在GUI JTable中选择一行并打印table.getSelectedRow()值时,在使用model.replace(cells)调用从第一个选择更改表数据后,我总是得到-1,即使我重新选择了第一个JComboBox选项。有什么我不知道的原因吗?我应该更改一些代码吗
编辑:在试图回答这个问题的过程中,代码发生了很大的变化,下面是更新后的代码。新的成就问题模型如上图所示
这将设置要在滚动窗格中正确查看和显示的模型和表格
if(model==null)
model = new AchievementTableModel(cells, columns);
else
model.replace(cells, columns);
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
} else
table.setModel(model);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
重新排序JTable时,需要跟踪TableModel中数据的原始索引,而不是JTable上的当前索引。从视觉上看,表可能已经移动,但基础数据模型没有移动。重新排序JTable时,需要跟踪TableModel中数据的原始索引,而不是JTable上的当前索引。从视觉上看,表可能已经移动,但基础数据模型没有移动。当它交换数据并删除选择时(因为索引现在不同),您需要重新计算选择并以编程方式进行设置
我要指出的是,根据我的经验,这就是为什么我倾向于扩展
AbstractTableModel
,或者直接实现我自己的TableModel
接口的原因。在这里修改备份数据引用总是会导致大量问题。当它交换数据并删除选择时(因为索引现在不同),您需要重新计算选择并以编程方式进行设置
我要指出的是,根据我的经验,这就是为什么我倾向于扩展
AbstractTableModel
,或者直接实现我自己的TableModel
接口的原因。在这里修改备份数据引用总是会导致大量问题。听起来像是更改选择丢失了
在“更改模型”之前,“getSelectedRow()”是否返回任何内容
如果是这样,则保持该索引,更改模型,然后再次设置该索引
可能您需要使用一个自定义设置,当更改选择丢失时听起来像是这样 在“更改模型”之前,“getSelectedRow()”是否返回任何内容 如果是这样,则保持该索引,更改模型,然后再次设置该索引
可能您需要为此使用自定义表在调用replace之后,不应使用新的JTable重新初始化表。fireTableDataChanged()方法将提醒您的现有表应该重新绘制。发生的情况是,您正在查看放入面板中的表,但您正在将变量更改为JTable的另一个实例。当您查询新的但不可见的表时,所选行数的值将为-1。如果您编辑您的帖子以显示代码中该区域的情况,这可能会有所帮助 第二次编辑: 与此相反:
if(model==null)
model = new AchievementTableModel(cells, columns);
else
model.replace(cells, columns);
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
} else
table.setModel(model);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
改为这样做:
if(model==null) {
model = new AchievementTableModel(cells, columns);
} else {
model.setDataVector(cells, columns);
}
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
} else {
table.setModel(model);
}
您无需将表格添加到新的滚动窗格中,并在每次型号更改时将其重新添加到面板中。在调用“替换”后,您不应使用新的JTable重新初始化表格。fireTableDataChanged()方法将提醒您的现有表应该重新绘制。发生的情况是,您正在查看放入面板中的表,但您正在将变量更改为JTable的另一个实例。当您查询新的但不可见的表时,所选行数的值将为-1。如果您编辑您的帖子以显示代码中该区域的情况,这可能会有所帮助 第二次编辑: 与此相反:
if(model==null)
model = new AchievementTableModel(cells, columns);
else
model.replace(cells, columns);
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
} else
table.setModel(model);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
改为这样做:
if(model==null) {
model = new AchievementTableModel(cells, columns);
} else {
model.setDataVector(cells, columns);
}
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
} else {
table.setModel(model);
}
您不需要将表格添加到新的滚动窗格中,并在每次型号更改时将其重新添加到面板中。可以尝试使用
super.setDataVector(Vector dataVector,Vector ColumnNames)
来自JavaDoc
替换当前数据向量
使用新向量的实例变量
行,数据向量。每行都是
在数据向量中表示为向量
对象值的定义。列标识符
是新列的名称。这个
列标识符中的第一个名称是
映射到dataVector中的列0。每个
调整dataVector中的行以匹配
中的列数
列标识符可以通过截断
向量太长,或
如果太短,则添加空值。
请注意,为
dataVector导致未指定的错误
行为,可能是一个例外。
参数:dataVector-新数据
向量列标识符-名称
列的
也许可以尝试使用
super.setDataVector(Vector dataVector,Vector ColumnNames)
来自JavaDoc
替换当前数据向量
使用新向量的实例变量
行,数据向量。每行都是
在数据向量中表示为向量
对象值的定义。列标识符
是新列的名称。这个
列标识符中的第一个名称是
映射到dataVector中的列0。每个
调整dataVector中的行以匹配
中的列数
列标识符可以通过截断
向量太长,或
如果太短,则添加空值。
请注意,为
dataVector导致未指定的错误
行为,可能是一个例外。
参数:dataVector-新数据
向量列标识符-名称
列的
我想到的另一件事,
class AchievementTableModel extends DefaultTableModel {
public AchievementTableModel(Object[][] c, Object[] co) {
super.dataVector = super.convertToVector(c);
super.columnIdentifiers = super.convertToVector(co);
}
public int getColumnCount() {return super.columnIdentifiers.size();}
public int getRowCount() {return super.dataVector.size();}
public String getColumnName(int c) {return (String)super.columnIdentifiers.get(c);}
@SuppressWarnings("unchecked")
public Object getValueAt(int r, int c) {return ((Vector<Object>)super.dataVector.get(r)).get(c);}
public boolean isCellEditable(int r, int c) {return false;}
public void replace(Object[][] c) {
super.dataVector = super.convertToVector(c);
super.fireTableDataChanged();
}
}
final int selectedRowIndex = table.rowAtPoint(mouseEvent.getPoint());
final int modelRowIndex = table.convertRowIndexToModel(selectedRowIndex);