我对Java有些新手,特别是对表的新手,我对一个特定的任务有点麻烦。
我有一个JTable,它使用扩展DefaultTableModel的自定义表模型,并且我已经将TableRowSorter附加到表中。下面的示例应用程序有两个按钮 - 一个将在表中加载行,另一个将从表中删除所有选定的行。
出于某种原因,如果您选择表格中的最后一行以及任何其他行,当您单击“删除”按钮时,它将删除除最后一行之外的所有选定行。您可以删除任何其他行组合,它可以正常工作。
更重要的是,如果您首先单击列标题对行进行排序(即使行的顺序没有更改),它也能正常工作。如果我在加载后添加一行来明确地对表中的行进行排序,问题就“消失了”,但我想知道为什么我所做的不正确。
要查看行为,请单击“加载”按钮以填充表格,选择表格中的所有行,然后单击“删除”按钮。它将删除除最后一行之外的所有行。
正如对println的调用所示,循环的第一次迭代将选定的行数减少了两个。无论表中有多少行,此行为都是一致的,但前提是您已选择表中的最后一行。
我正在使用Java版本1.6.0_16。关于我做错了什么的想法?
谢谢,
乔
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.util.Arrays;
public class TableTest
extends JFrame
{
private JTable widgetTable;
private WidgetTableModel widgetTableModel;
public static void main(String[] args)
{
TableTest frame = new TableTest();
frame.setSize(600, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public TableTest()
{
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
EventQueue.invokeLater(new Runnable() { public void run() { createUI(); } });
}
private void createUI()
{
this.setLayout(new BorderLayout());
JButton loadButton = new JButton("Load");
loadButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
loadPerformed();
}
});
this.add(loadButton, BorderLayout.NORTH);
widgetTableModel = new WidgetTableModel();
widgetTable = new JTable(widgetTableModel);
widgetTable.setRowSorter(new TableRowSorter<WidgetTableModel>(widgetTableModel));
this.add(new JScrollPane(widgetTable), BorderLayout.CENTER);
JButton removeButton = new JButton("Remove");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removePerformed();
}
});
this.add(removeButton, BorderLayout.SOUTH);
}
private void loadPerformed()
{
widgetTableModel.addRow(new Object[] {"Widget 1"});
widgetTableModel.addRow(new Object[] {"Widget 2"});
widgetTableModel.addRow(new Object[] {"Widget 3"});
widgetTableModel.addRow(new Object[] {"Widget 4"});
widgetTableModel.addRow(new Object[] {"Widget 5"});
}
private void removePerformed()
{
int selectedRow = widgetTable.getSelectedRow();
while (selectedRow >= 0) {
System.out.println("selectedRowCount=" + widgetTable.getSelectedRowCount());
int modelRow = widgetTable.convertRowIndexToModel(selectedRow);
widgetTableModel.removeRow(modelRow);
selectedRow = widgetTable.getSelectedRow();
}
}
}
class WidgetTableModel
extends DefaultTableModel
{
public WidgetTableModel()
{
this.addColumn("Column 1");
}
}
答案 0 :(得分:0)
将“while”更改为“if”。选择所有行,然后单击按钮。由于某种原因,最后一行丢失了它的选择。我不知道为什么。
我发现删除逻辑通常应该从最后一行向下完成0.这样,您不必担心行索引值的更改会删除行。因此,您需要使用getSelectedRows()方法并以相反的顺序遍历数组。虽然,我必须承认我从未在排序的桌子上做过这个,所以我不确定它是否会引起问题。
答案 1 :(得分:0)
还讨论了java.net:http://www.java.net/node/698236
核心DefaultRowSorter中的bug #6894632:在其基础(如报告中所述)是getModelRowCount()的一个定义不太好的语义。它已在SwingX DefaultSortController
中修复/**
* Additionally, this implementation contains a fix for core
* <a href=http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6894632>Issue 6894632</a>.
* It guarantees to only touch the underlying model during sort/filter and during
* processing the notification methods. This implies that the conversion and size query
* methods are valid at all times outside the internal updates, including the critical
* period (in core with undefined behaviour) after the underlying model has changed and
* before this sorter has been notified.
*/
不幸的是,在项目迁移后,SwingLabs论坛中包含完整分析的线程(http://www.java.net/jive/thread.jspa?threadID=77343)不再可用...