質問

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

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

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

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

これは、Windows XP上のJava 1.4.2です。使用するベンダーコードに基づいて、そのバージョンに制限されています。

役に立ちましたか?

解決

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

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

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

もう1つ言いたいのは、各テーブルモデルのリロード後にテーブル内の行または列の数が増加または減少している場合、選択を保持することを気にしないでください。

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

したがって、プログラムでセルを選択すると、両刃の剣になります。わからない場合は、それをしないでください。

他のヒント

次のように、テーブルの構造が変更されていない場合(つまり、列/行を追加/削除していない場合)、テーブルの選択を自動的に保持できます。

TableModelの独自の実装を作成した場合、単にfireTableDataChanged()メソッドをオーバーライドできます:

        @Override
        public void fireTableDataChanged() {
            fireTableChanged(new TableModelEvent(this, //tableModel
                                                 0, //firstRow
                                                 getRowCount() - 1, //lastRow 
                                                 TableModelEvent.ALL_COLUMNS, //column 
                                                 TableModelEvent.UPDATE)); //changeType
        }

これにより、テーブルの構造ではなくデータのみが変更された場合に、選択が維持されることが保証されます。これと、このメソッドがオーバーライドされない場合に呼び出されるものとの唯一の違いは、Integer.MAX_VALUEの代わりにgetRowCount()-1がlastRow引数に渡されることです。後者は、テーブル内のデータは変更されましたが、行数も同じである可能性があります。

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

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

補足として、GlazedListsを使用すると、テーブルを扱うときに作業がはるかに簡単になることがわかりました。

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

参照用に、@ 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]);

正しく思い出せば、選択を保存して再適用することも私たちがやったことです...

同じ問題に直面していましたが、理由を検索しようとするとこの質問が出ましたが、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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top