0

私はJavaにやや慣れておらず、特にテーブルに慣れていません。特定の1つのタスクで少し問題が発生しています。

DefaultTableModelを拡張するカスタムテーブルモデルを使用するJTableがあり、TableRowSorterをテーブルにアタッチしました。以下のサンプルアプリケーションには2つのボタンがあります。1つは行をテーブルにロードし、もう1つは選択したすべての行をテーブルから削除します。

何らかの理由で、テーブルの最後の行を他の行と一緒に選択した場合、[削除]ボタンをクリックすると、最後の行を除くすべての選択した行が削除されます。他の行の組み合わせは削除でき、正常に機能します。

さらに、最初に列ヘッダーをクリックして行を並べ替えると(行の順序が変更されていない場合でも)、正しく機能します。ロード後にテーブル内の行を明示的に並べ替える行を追加すると、問題は「解消」されますが、私が行っていることが正しくない理由を知りたいのです。

動作を確認するには、[ロード]ボタンをクリックしてテーブルにデータを入力し、テーブル内のすべての行を選択してから、[削除]ボタンをクリックします。最後の行を除くすべての行が削除されます。

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");
  }
}
4

2 に答える 2

0

「while」を「if」に変更します。すべての行を選択して、ボタンをクリックします。何らかの理由で、最後の行は選択を失います。どうしてか分かりません。

削除ロジックは通常、最後の行から0まで実行する必要があると思います。これにより、行が削除されるときに行のインデックス値が変化することを心配する必要がなくなります。したがって、getSelectedRows()メソッドを使用して、逆の順序で配列を反復処理する必要があります。ただし、ソートされたテーブルでこれを行ったことがないことを認めなければならないので、問題が発生するかどうかはわかりません。

于 2009-10-20T22:13:12.633 に答える
0

java.net でも議論されています: http://www.java.net/node/698236

これは、コア DefaultRowSorter のバグ #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 ) は、プロジェクトの移行後に利用できなくなりました ...

于 2011-12-14T13:59:33.620 に答える