当我们从JTable
执行fireTableDataChanged()
或fireTableRowsUpdated()
时,我们看到TableModel
选项已被清除。
这是预期的,还是我们做错了什么?我没有在JTable
(或其他相关类)上看到关于清除/保留模型更新选择的任何属性。
如果这是默认行为,是否有一种防止这种情况的好方法?也许某种方法可以在更新之前“锁定”选择并在之后解锁?
开发人员一直在尝试在更新之前保存选择并重新应用它。这有点慢。
这是Windows XP上的Java 1.4.2,如果这很重要的话。我们仅限于基于我们使用的某些供应商代码的版本。
答案 0 :(得分:4)
您需要保留选择,然后重新应用它。
首先,您需要获取所有选定单元格的列表。
然后,当您使用新数据重新加载JTable时,您需要以编程方式重新应用这些相同的选择。
我想要做的另一点是,如果表格中的数字或行数或列数在每个表格模型重新加载后增加或减少,那么请不要费心保留选择。
在模型更新之前,用户可以选择具有值“Duck”的第2行第1列。但是在模型更新之后,相同的数据现在可以在第4行第1列中出现,而原始单元格第2列第1列可能有新数据,例如“Pig”。现在,如果您强制将选择设置为模型更新之前的选择,则可能不是用户想要的。
因此,以编程方式选择单元格可能是一把双刃剑。如果你不确定,不要这样做。
答案 1 :(得分:4)
如果表格的结构未发生变化(即如果您没有添加/删除任何列/行),则可以自动保留表格的选择,如下所示。
如果您已经编写了自己的TableModel实现,则可以简单地覆盖fireTableDataChanged()方法:
@Override
public void fireTableDataChanged() {
fireTableChanged(new TableModelEvent(this, //tableModel
0, //firstRow
getRowCount() - 1, //lastRow
TableModelEvent.ALL_COLUMNS, //column
TableModelEvent.UPDATE)); //changeType
}
这应确保维持您的选择,前提是只有数据而不是表的结构发生了变化。这个方法之间的唯一区别是,如果不重写此方法将会调用的是getRowCount() - 1为lastRow参数而不是Integer.MAX_VALUE传递,后者的作用是一个不仅具有能力的能指表中的所有数据都已更改,但行数也可能已更改。
答案 2 :(得分:1)
这是默认行为。如果您调用fireTableDataChanged()
,则在设置全新模型时,将从头开始重建整个表。在这种情况下,选择自然会丢失。如果您致电fireTableRowsUpdated()
,一般情况下也会清除选择。唯一的方法是记住选择,然后设置它。遗憾的是,无法保证选择仍然有效。恢复选择时要小心。
答案 3 :(得分:1)
我在应用程序中遇到了同样的问题。在我的例子中,表中的模型是一个对象列表,其中对象属性映射到列。在这种情况下,当列表被修改时,我检索了所选索引并存储了在更新列表之前选择的对象。修改列表后,在更新表之前,我将计算所选对象的位置。如果修改后它仍然存在,那么我会将选择设置为新索引。
修改后在表格中设置选定的索引将不起作用,因为该对象可能会更改列表中的位置。
作为旁注,我发现使用GlazedLists可以在处理表格时更轻松。
答案 4 :(得分:0)
如果我没记错的话,保存选择并重新应用它也是我们所做的......
答案 5 :(得分:-1)
我遇到了同样的问题,当我试图搜索我得到这个问题的原因但它似乎是Java SDK中的一个错误。 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4276786
周围的工作
可以进行临时解决。一旦修复了这个错误就应该将其删除,因为它的适用性尚未针对固定版本进行测试。
使用JTable的这个子类。
注意:这适用于MetalLookAndFeel。如果使用其他外观,内部FixedTableUI子类将必须扩展TableUI子类以获得该外观。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
public class FixedTable extends JTable {
private boolean isControlDownInDrag;
public FixedTable(TableModel model) {
super(model);
setUI(new FixedTableUI());
}
private class FixedTableUI extends BasicTableUI {
private MouseInputHandler handler = new MouseInputHandler() {
public void mouseDragged(MouseEvent e) {
if (e.isControlDown()) {
isControlDownInDrag = true;
}
super.mouseDragged(e);
}
public void mousePressed(MouseEvent e) {
isControlDownInDrag = false;
super.mousePressed(e);
}
public void mouseReleased(MouseEvent e) {
isControlDownInDrag = false;
super.mouseReleased(e);
}
};
protected MouseInputListener createMouseInputListener() {
return handler;
}
}
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if (isControlDownInDrag) {
ListSelectionModel rsm = getSelectionModel();
ListSelectionModel csm = getColumnModel().getSelectionModel();
int anchorRow = rsm.getAnchorSelectionIndex();
int anchorCol = csm.getAnchorSelectionIndex();
boolean anchorSelected = isCellSelected(anchorRow, anchorCol);
if (anchorSelected) {
rsm.addSelectionInterval(anchorRow, rowIndex);
csm.addSelectionInterval(anchorCol, columnIndex);
} else {
rsm.removeSelectionInterval(anchorRow, rowIndex);
csm.removeSelectionInterval(anchorCol, columnIndex);
}
if (getAutoscrolls()) {
Rectangle cellRect = getCellRect(rowIndex, columnIndex, false);
if (cellRect != null) {
scrollRectToVisible(cellRect);
}
}
} else {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
}
}
注意 Curtsey到http://bugs.sun.com