TITLE:JTableのセルの編集をコミット

JTableのセルの編集をコミット

編集者:Terai Atsuhiro~

作成日:2007-04-16
更新日:2022-10-01 (土) 04:56:39
  • category: swing folder: TerminateEdit title: JTableのセルの編集をコミット tags: [JTable, Focus, JTableHeader, TableCellEditor] author: aterai pubdate: 2007-04-16T12:24:10+09:00 description: セルの編集中、フォーカスが別のコンポーネントに移動した場合、その編集を確定する方法をテストします。 image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTVKX5loMI/AAAAAAAAAnM/hbhZT30xAgc/s800/TerminateEdit.png

概要

セルの編集中、フォーカスが別のコンポーネントに移動した場合、その編集を確定する方法をテストします。

概要

セルの編集中、フォーカスが別のコンポーネントに移動した場合、その編集を確定する方法をテストします。

サンプルコード

#spanend
#spanadd
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
#spanend
#spanadd
View in GitHub: Java, Kotlin

#screenshot

解説

デフォルトのJTableでは、Tabキーやマウスのクリックなどで同じテーブルの別セルにフォーカスが移動すると編集が確定しますが、別のコンポーネントにフォーカスが移動しても編集は確定しません。

サンプルコード

  • terminateEditOnFocusLost
    • table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);を設定
    • 同じフレームを親に持つコンポーネントにフォーカスが移動したとき編集が確定する
    • 別フレームのコンポーネントにフォーカスが移動しても編集中の状態が継続する
    • ヘッダをクリックしたり、列の入れ替え、サイズ変更を実行すると編集はキャンセルされる
  • DefaultCellEditor:focusLost
    • DefaultCellEditorからエディタコンポーネントを取得してこれにFocusListenerを設定し、セルが編集中ならtable.getCellEditor().stopCellEditing();を実行
    • 別フレームのコンポーネントにフォーカスが移動したときも、編集が確定する
    • ヘッダのクリック、入れ替え、サイズ変更などで編集はキャンセルされる
      #spandel
      table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
      #spanend
      #spandel
      
      #spanend
      #spandel
      DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(Object.class);
      #spanend
      #spanadd
      DefaultCellEditor dce = (DefaultCellEditor) table.getDefaultEditor(Object.class);
      #spanend
      dce.getComponent().addFocusListener(new FocusAdapter() {
        public void focusLost(FocusEvent e) {
          if(!focusCheck.isSelected()) return;
          if(table.isEditing()) {
        @Override public void focusLost(FocusEvent e) {
          if (!focusCheck.isSelected()) {
            return;
          }
          if (table.isEditing()) {
            table.getCellEditor().stopCellEditing();
          }
        }
      });
      #spanadd
      
  • TableHeader:mousePressed
    • TableHeaderMouseListenerを設定してセルが編集中ならtable.getCellEditor().stopCellEditing(); を実行
    • ヘッダをクリックしたとき編集が確定する
    • JDK 1.7.0ではこのようなMouseListenerTableHeaderに設定しなくても編集が確定するように修正されている
    • Bug ID: 4330950 Lost newly entered data in the cell when resizing column width
      #spanend
      table.getTableHeader().addMouseListener(new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
          if(!headerCheck.isSelected()) return;
          if(table.isEditing()) {
        @Override public void mousePressed(MouseEvent e) {
          if (!headerCheck.isSelected()) {
            return;
          }
          if (table.isEditing()) {
            table.getCellEditor().stopCellEditing();
          }
        }
      });
      
  • &jnlp;
  • &jar;
  • &zip;

解説

デフォルトのJTableの場合、タブキー、リターンキー、マウスのクリックなどで、別のセルにフォーカスが移動した場合、編集が確定しますが、別のコンポーネントにフォーカスが移っても編集は確定しません。
  • -
  • table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);とすると、
    • 同じフレームを親に持つコンポーネントにフォーカスが移動したとき、編集が確定するようになります。
    • 別フレームのコンポーネントにフォーカスが移動しても編集中のままです。
    • ヘッダをクリック、入れ替え、サイズ変更すると、編集はキャンセルされます。
  • JTable.AUTO_RESIZE_OFF
    • 親フレームのリサイズや最大化は編集中のまま
  • JTable.AUTO_RESIZE_ALL_COLUMNSなど
    • 親フレームのリサイズや最大化を行うとヘッダのサイズが変化するため、キャンセル扱い
  • ヘッダのサイズが変化しない場合は、どちらの設定でも以下のようになる
    • 親フレームの最小化(アイコン化)は編集中のまま
    • 親フレームを閉じる場合はキャンセル扱い
  • DefaultCellEditorからエディタコンポーネントを取得し、FocusListenerを設定して、セルが編集中ならtable.getCellEditor().stopCellEditing();とすると、
    • 別フレームのコンポーネントにフォーカスが移動したときも、編集が確定するようになります。
    • ヘッダをクリック、入れ替え、サイズ変更すると、編集はキャンセルされます。
  • TableHeaderにMouseListenerを設定して、セルが編集中ならtable.getCellEditor().stopCellEditing();とすると、
    • ヘッダをクリックしたとき、編集が確定するようになります。

親フレームの状態変化でテーブルのヘッダのサイズ変更が発生する場合、ヘッダのリサイズモデルによって、編集中のセルの状態変化が異なります。
  • JTable.AUTO_RESIZE_OFF
    • 親フレームのリサイズや最大化は編集中のまま
  • JTable.AUTO_RESIZE_ALL_COLUMNSなど
    • 親フレームのリサイズや最大化を行うとヘッダのサイズが変更するため、キャンセル扱い
  • 親フレームの状態変化に応じて編集の確定を行う場合は、以下のようにJTable#columnMarginChangedメソッドなどをオーバーライドしたり、各種リスナーを設定する必要がある
ヘッダのサイズ変更が発生しない変化では、どちらの場合でも以下のようになります。
  • 親フレームの最小化(アイコン化)は編集中のまま
  • 親フレームを閉じる場合はキャンセル扱い
親フレームの状態変化に応じて編集の確定を行う場合は、以下のように、JTable#columnMarginChangedメソッドなどをオーバーライドしたり、各種リスナーを設定する必要があります。
table = new JTable(sorter) {
  public void columnMarginChanged(ChangeEvent e) {
    if(table.isEditing()) {
  @Override public void columnMarginChanged(ChangeEvent e) {
    if (table.isEditing()) {
      table.getCellEditor().stopCellEditing();
    }
    super.columnMarginChanged(e);
  }
};

frame.addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent e) {
    if(table.isEditing()) {
  @Override public void windowClosing(WindowEvent e) {
    if (table.isEditing()) {
      table.getCellEditor().stopCellEditing();
    }
  }
});

frame.addWindowStateListener(new WindowStateListener() {
  public void windowStateChanged(WindowEvent e) {
    if(frame.getExtendedState()==JFrame.MAXIMIZED_BOTH
       && table.isEditing()) {
  @Override public void windowStateChanged(WindowEvent e) {
    if (frame.getExtendedState() == JFrame.MAXIMIZED_BOTH && table.isEditing()) {
      table.getCellEditor().stopCellEditing();
    }
  }
});

コメント

参考リンク

コメント