Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在表格模型更改中保留JTable选择_Java_Swing_Jtable_Tablemodel - Fatal编程技术网

Java 在表格模型更改中保留JTable选择

Java 在表格模型更改中保留JTable选择,java,swing,jtable,tablemodel,Java,Swing,Jtable,Tablemodel,当我们从TableModel执行fireTableDataChanged()或fireTableRowsUpdated()时,我们看到JTable选择被清除 这是意料之中的事,还是我们做错了什么?我在JTable(或其他相关类)上没有看到关于清除/保留模型更新选择的任何属性 如果这是默认行为,有没有好的方法来防止?也许可以在更新前“锁定”选择,然后在更新后解锁 开发人员一直在尝试在更新之前保存选择并重新应用它。有点慢 这是WindowsXP上的Java1.4.2,如果这很重要的话。根据我们使用的

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

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

如果这是默认行为,有没有好的方法来防止?也许可以在更新前“锁定”选择,然后在更新后解锁

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


这是WindowsXP上的Java1.4.2,如果这很重要的话。根据我们使用的某些供应商代码,我们仅限于该版本。

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

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

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

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

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

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


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

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

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

修改后仅在表中设置所选索引将不起作用,因为对象可能会更改列表中的位置


作为补充说明,我发现使用GlazedList可以使处理表时的工作更加轻松。

如果表的结构没有改变(即,如果没有添加/删除任何列/行),则可以自动保留该表的选择,如下所示

如果您已经编写了自己的TableModel实现,只需重写fireTableDataChanged()方法即可:

@覆盖
public void fireTableDataChanged(){
fireTableChanged(新TableModelEvent(此,//tableModel
0,//第一行
getRowCount()-1,//最后一行
TableModelEvent.ALL_列,//列
TableModelEvent.UPDATE));//变更类型
}

这将确保您的选择得到维护,前提是只有数据而不是表的结构发生了更改。这与如果不重写此方法将调用的唯一区别是,为lastRow参数传递getRowCount()-1,而不是Integer.MAX_值,后者充当一个符号,不仅改变了表中的所有数据,而且行数也可能改变

我也面临着同样的问题,当我试图搜索得到这个问题的原因时,它似乎是Java SDK中的一个bug

变通

可提供临时工作环境。一旦修复了这个bug,就应该删除它,因为它的适用性还没有针对固定版本进行测试

使用JTable的这个子类

注意:这是为金属手感设计的。如果使用其他外观,内部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);
      }
  }
}

注意

行屈膝礼作为参考,正如@Swapnonil Mukherjee所说的,这在一张有可选择行的桌子上起到了作用:

//保留调用fireTableDataChanged()的选择
final int[]sel=table.getSelectedRows();
fireTableDataChanged();

对于(int i=0;iWare:这样做可能适得其反-更改的数据可能包括插入/删除。如果是这种情况,侦听器可能会受到严重误导,那么这不是结构更改吗?不,结构更改是指列随数据一起更改,您指的是列和/或行,对吗?插入/删除是指添加列吗ns和/或行或其他什么?抱歉,我想我还是有点困惑,但听起来你在这里说的对我来说非常重要。是的,触发哪个事件的api文档并不太清楚:要理解,我们必须仔细阅读AbstractTableModel.fireXX方法和TableModelEvent;-)tableModel的结构==一组列,因此无论何时删除/插入(或甚至移动)列,都必须触发structureChanged。单边界范围的插入/删除/更新是显而易见的。包含难以表达(以单块表示)的插入/删除的更改必须触发dataChanged