JTable 未正确返回所选行
我正在使用 DefaultTableModel 的扩展,如下所示:
这是更新它以反映一些答案的输入后的新成就表模型。
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,用于选择要显示的数据。 TableModel 通过调用 model.replace(cells) 进行更新,然后再次运行上述表创建代码。
在 GUI JTable 中选择一行并打印 table.getSelectedRow() 值时,即使我重新选择第一个 JComboBox,在使用第一个选择中的 model.replace(cells) 调用更改表数据后,我总是得到 -1选项。 我失踪了有什么原因吗? 我应该更改一些代码吗?
编辑:代码在尝试回答这个问题时发生了很大的变化,所以这里是更新的代码。 新的 AchievementTableModel 如下所示。
这会将模型和表格设置为可以正确查看并显示在 ScrollPane 中
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);
I am working with an extension of the DefaultTableModel as follows:
This is the NEW AchievementTableModel after updating it to reflect input from some answers.
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();
}
My GUI is a JTable that has the following properties:
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);
I have a JComboBox that selects which data to display. The TableModel is updated with a call to model.replace(cells) and then runs through the above table creation code again.
When selecting a row in the GUI JTable, and printing the table.getSelectedRow() value, I ALWAYS get -1 after changing the table data with a model.replace(cells) call from the first selection, even if I reselect the first JComboBox option. Is there a reason for this that I'm missing? Should I change some code?
EDIT: The code has changed a lot over trying to answer this question so here is the updated code. The new AchievementTableModel is above.
This sets up the model and table to be viewed correctly and displayed in a ScrollPane
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我遇到了同样的问题,getSelectedRow() 总是得到 -1。 问题现在本来可以解决了。 尽管如此,发布解决我的问题的代码:
I had the same problem of getting a -1 always for getSelectedRow(). The problem could have got solved by now. Nonetheless, posting the code which fixed my problem:
在调用替换后,您不应该使用新的 JTable 重新初始化表。 fireTableDataChanged() 方法将提醒您现有的表应该重新绘制。 发生的情况是,您正在查看放入面板中的表,但您正在将变量更改为 JTable 的不同实例。 当您查询该新的但不可见的表时,它将为您提供所选行数的 -1。 如果您编辑帖子以显示该代码区域中发生的情况可能会有所帮助。
第二次编辑:
而不是这样:
改为这样做:
您不需要将表添加到新的滚动窗格,并在每次模型更改时将其重新添加到面板。
you shouldnt reinitialize your table with a new JTable after you call replace. the fireTableDataChanged() method will alert your existing table that it should repaint. what is happening is that you are looking at the table that you put into the panel, but you are changing the variable to a different instance of JTable. When you query that new, but not visible table, it will give you -1 for the selected row count. it might be helpful if you edit your post to display what is going on in that area of the code.
2nd edit:
instead of this:
do this instead:
you dont need to add the table to a new scrollpane and re-add it to the panel on each model change.
好吧,现在我感兴趣了,
看起来你必须真正清理你的代码,因为周围有很多参考资料。
您看不到具有选定索引的表的原因是,每次创建新的
JTable
时,打印选定记录的方法仍然指向原始记录。 由于您现在显示的是“新”创建的表,因此旧表会打印-1
。使用
DefaultTableModel
时得到空表的原因是向量为null
(可能从组合中获得),因此数据和标题都从表中消失。无论如何,如果您使用
Object[][]
作为数据,则不需要子类。因此,这里有一个更简单的测试类,您可以查看它来纠正您的测试类。
我使用您的自定义
TableModel
和DefaultTableModel
进行测试,这与您的自定义表格模型无关而是你使用参考文献的方式。
我希望这有帮助。
你的子类不变。
尝试一下,看看它如何不会丢失表引用并始终打印正确的
selectedRow
。将其与您的代码进行比较并从那里修复它。
Ok, now I'm interested
It looks like you have to really really clean up your code because there are a lot of reference all around.
The reason you are not seeing the table with a selected index is because each time you create a new
JTable
the method where you print the selected record still points to the original. Since you're displaying now a "newly" created table the old one prints-1
.The reason you get empty table when using the
DefaultTableModel
is because the vectors arenull
( perhaps obtained from the combo ) and thus both the data and the headers disappear from the table.You don't need a subclass if you're using
Object[][]
as data anyway.So here is a somehow simpler test class that you can see to correct yours.
I test it with both, your custom
TableModel
and theDefaultTableModel
This has nothing to do with your custom table model but the way you're using your references.
I hope this helps.
Your subclass unchanged.
Try it and see how it doesn't lose the table reference and always print the correct
selectedRow
.Compare it with your code and fix it from there.
也许尝试使用
super.setDataVector(Vector dataVector, Vector ColumnNames);
Maybe try using
super.setDataVector(Vector dataVector, Vector ColumnNames);
当它交换数据时,它会删除选择(因为索引现在不同),您需要重新计算选择并以编程方式设置它。
我要指出的是,根据我的经验,这就是为什么我倾向于扩展
AbstractTableModel
或从头开始正确实现我自己的TableModel
接口。 恕我直言,像这里一样修改支持数据引用总是会导致一百万个问题。When it swaps out the data its removing the selection (since the index is now different), you'll need recalculate the selection and set it programmatically.
I'll point out that in my experience, this is why I tend to extend
AbstractTableModel
or out right implement my ownTableModel
interface from the ground up. Modifying the backing data reference as here, always causes a million problems IMHO.当您重新排序 JTable 时,您需要跟踪数据 TableModel 中的原始索引,而不是 JTable 上的当前索引。 从视觉上看,表可能已发生变化,但基础数据模型并未发生变化。
When you reorder a JTable you need to keep track of the original indexes in the TableModel for your data, not the current indexes on the JTable. Visually the table may have shifted but the underlying data model has not.
听起来好像更改选择时丢失了。
“getSelectedRow()”在更改模型“之前”是否返回任何内容?
如果是这样,则保留该索引,更改模型,然后再次设置该索引。
可能您需要使用自定义 ListSelectionModel为了那个原因
Sounds like when changing your selection is lost.
Does "getSelectedRow()" return anything "BEFORE" you change the model?
If so, then hold that index, change the model and then set that index again.
Probably you need to use a custom ListSelectionModel for that
我想到的另一件事是,当您执行
table= new JTable(model);
时,您正在更改变量“table”所引用的表,但这可能不会自动导致新表被更改呈现。如果您的表格包含在 ScrollPane 中,您可能需要调用 ScrollPane.setViewportView(table);
Another thing I thought of, when you do
table= new JTable(model);
you are changing the table that the variable 'table' is referring to, however that may not automatically cause the new table to be rendered.If you table is contained within a ScrollPane, you may need to call
ScrollPane.setViewportView(table);