15

からまたはJTableを実行すると、選択がクリアされます。fireTableDataChanged()fireTableRowsUpdated()TableModel

これは予想されることですか、それとも何か間違ったことをしていますか?JTableモデルの更新時に選択をクリア/保持することについて、(または他の関連クラス)にプロパティが表示されませんでした。

これがデフォルトの動作である場合、これを防ぐ良い方法はありますか?おそらく、更新前に選択を「ロック」し、更新後にロックを解除する方法はありますか?

開発者は、更新前に選択範囲を保存して再適用することを試みてきました。少し遅いです。

それが重要な場合、これはWindowsXP上のJava1.4.2です。使用するベンダーコードに基づいて、そのバージョンに制限されています。

4

7 に答える 7

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 が Integer.MAX_VALUE の代わりに lastRow 引数に渡されることです。テーブル内のデータが変更されましたが、行数も変更された可能性があります。

于 2012-03-20T12:21:59.463 に答える
4

選択を保持してから、再度適用する必要があります。

まず、選択したすべてのセルのリストを取得する必要があります。

次に、新しいデータで JTable を再ロードするときに、同じ選択をプログラムで再適用する必要があります。

もう 1 点言いたいのは、テーブル モデルをリロードするたびにテーブル内の行または列の数が増減している場合は、わざわざ選択を保持しないでください。

ユーザーは、モデルの更新前に、「Duck」という値を持つ行 2 列 1 を選択した可能性があります。ただし、モデルの更新後、同じデータが行 4 列 1 に発生する可能性があり、元のセル行 2 列 1 に「豚」などの新しいデータが含まれる可能性があります。ここで、モデルの更新前の選択を強制的に設定すると、これはユーザーが望んでいたものではない可能性があります。

したがって、プログラムでセルを選択することは両刃の剣になる可能性があります。よくわからない場合は、実行しないでください。

于 2008-11-01T19:53:21.063 に答える
1

これはデフォルトの動作です。fireTableDataChanged()完全に新しいモデルを設定すると、テーブル全体がゼロから再構築されます。この場合、選択は当然失われます。呼び出しfireTableRowsUpdated()た場合、通常は選択もクリアされます。唯一の方法は、選択を記憶してから設定することです。残念ながら、選択が有効であるという保証はありません。選択を復元する場合は注意してください。

于 2008-11-02T12:26:04.913 に答える
1

アプリケーションで同じ問題が発生しました。私の場合、テーブルのモデルはオブジェクトのリストであり、オブジェクトのプロパティが列にマップされていました。その場合、リストが変更されたときに、選択したインデックスを取得し、リストを更新する前に選択したオブジェクトを保存しました。リストが変更された後、テーブルが更新される前に、選択したオブジェクトの位置を計算します。変更後もまだ存在する場合は、選択を新しいインデックスに設定します。

オブジェクトがリスト内の位置を変更する可能性があるため、変更後にテーブルで選択したインデックスを設定するだけでは機能しません。

余談ですが、GlazedLists を使用すると、テーブルを扱う際の作業がはるかに簡単になることがわかりました。

于 2008-11-07T08:26:59.870 に答える
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 に答える