15

当我们执行 a或from时,我们看到JTable选择被清除。fireTableDataChanged()fireTableRowsUpdated()TableModel

这是预期的,还是我们做错了什么?我没有在JTable(或其他相关类)上看到任何关于清除/保留模型更新选择的属性。

如果这是默认行为,是否有防止这种情况的好方法?也许某种方式可以在更新之前“锁定”选择并在之后解锁?

开发人员一直在尝试在更新之前保存选择并重新应用它。这有点慢。

这是 Windows XP 上的 Java 1.4.2,如果这很重要的话。根据我们使用的一些供应商代码,我们仅限于该版本。

4

7 回答 7

4

您需要保留选择,然后重新应用它。

首先,您需要获取所有选定单元格的列表。

然后,当您使用新数据重新加载 JTable 时,您需要以编程方式重新应用这些相同的选择。

我要说的另一点是,如果每次重新加载表模型后表中的行数或列数都在增加或减少,那么请不要费心保留选择。

在模型更新之前,用户可以选择具有“鸭子”值的第 2 行第 1 列。但是在模型更新之后,相同的数据现在可以出现在第 4 行第 1 列中,并且您的原始单元格第 2 行第 1 列可能有新数据,例如“Pig”。现在,如果您强制将选择设置为模型更新之前的状态,这可能不是用户想要的。

因此,以编程方式选择单元格可能是一把双刃剑。如果您不确定,请不要这样做。

于 2008-11-01T19:53:21.063 回答
4

如果该表的 STRUCTURE 未更改(即,如果您未添加/删除任何列/行),您可以自动保留该表的选择,如下所示。

如果您已经编写了自己的 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,后者充当一个不仅具有所有表中的数据发生了变化,但行数也可能发生了变化。

于 2012-03-20T12:21:59.463 回答
1

这是默认行为。如果您调用fireTableDataChanged()整个表是从头开始重建,因为您设置了全新的模型。在这种情况下,选择自然会丢失。如果您调用fireTableRowsUpdated()选择也清除在一般情况下。唯一的方法是记住选择然后设置它。不幸的是,不能保证选择仍然有效。恢复选择时要小心。

于 2008-11-02T12:26:04.913 回答
1

我在应用程序中遇到了同样的问题。在我的例子中,表中的模型是一个对象列表,其中对象属性映射到列。在这种情况下,当列表被修改时,我检索了选定的索引并存储了在更新列表之前选择的对象。修改列表后,更新表格之前,我会计算所选对象的位置。如果修改后它仍然存在,那么我会将选择设置为新索引。

修改后只在表格中设置选定的索引是行不通的,因为对象可能会改变列表中的位置。

附带说明一下,我发现使用 GlazedLists 可以让处理表格时的生活变得更加轻松。

于 2008-11-07T08:26:59.870 回答
1

作为参考,正如@Swapnonil Mukherjee 所说,这对带有可选行的表格起到了作用:

// preserve selection calling fireTableDataChanged()
final int[] sel = table.getSelectedRows();

fireTableDataChanged();

for (int i=0; i<sel.length; i++)
    table.getSelectionModel().addSelectionInterval(sel[i], sel[i]);
于 2015-08-25T10:58:38.723 回答
0

如果我没记错的话,保存选择并重新应用它也是我们所做的......

于 2008-10-31T17:10:56.713 回答
-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

于 2013-08-09T08:55:15.693 回答