【问题标题】:Removing rows from a DefaultTableModel with a RowSorter attached doesn't remove last row从附加了 RowSorter 的 DefaultTableModel 中删除行不会删除最后一行
【发布时间】:2009-10-20 22:02:02
【问题描述】:

我对 Java 有点陌生,尤其是对表格很陌生,但我在完成一项特定任务时遇到了一些麻烦。

我有一个 JTable,它使用扩展 DefaultTableModel 的自定义表模型,并且我已将 TableRowSorter 附加到表中。下面的示例应用程序有两个按钮——一个将行加载到表中,一个将从表中删除所有选定的行。

由于某种原因,如果您选择表格中的最后一行以及任何其他行,当您单击“删除”按钮时,它将删除除最后一行之外的所有选定行。您可以删除任何其他行组合,它工作正常。

更重要的是,如果您首先单击列标题对行进行排序(即使行的顺序没有改变),它也会正常工作。如果我在加载后添加一行以显式对表中的行进行排序,则问题“消失”,但我想知道为什么我所做的不正确。

要查看行为,请单击“加载”按钮填充表格,选择表格中的所有行,然后单击“删除”按钮。它将删除除最后一行之外的所有行。

正如对 println 的调用所示,循环的第一次迭代将选定的行数减少了 2。无论表中有多少行,此行为都是一致的,但前提是您选择了表中的最后一行。

我使用的是 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");
  }
}

【问题讨论】:

    标签: java swing jtable tablerowsorter


    【解决方案1】:

    将“while”更改为“if”。选择所有行,然后单击按钮。由于某种原因,最后一行失去了选择。我不知道为什么。

    我发现删除逻辑通常应该从最后一行到 0 完成。这样您就不必担心行索引值在删除一行时会发生变化。因此,您需要使用 getSelectedRows() 方法并以相反的顺序遍历数组。虽然,我必须承认我从来没有在排序表上这样做过,所以我不确定它是否会导致问题。

    【讨论】:

    • 以相反的顺序遍历选定的行应该可以工作,但似乎没有必要。该示例现在的工作方式应该同样可靠——始终获取表中的第一个选定行。这也消除了跟踪索引更改的需要。问题似乎是导致最后一行被取消选择的“错误”(或任何来源)。
    【解决方案2】:

    也在 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)在项目迁移后不再可用...

    【讨论】:

      猜你喜欢
      • 2013-12-18
      • 2017-01-20
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 2016-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多