Swing/TerminateEdit のバックアップの現在との差分(No.17)
TITLE:JTableのセルの編集をコミット
Posted by aterai at 2007-04-16
JTableのセルの編集をコミット
- category: swing folder: TerminateEdit title: JTableのセルの編集をコミット tags: [JTable, Focus, JTableHeader, TableCellEditor] author: aterai pubdate: 2007-04-16T12:24:10+09:00 description: セルの編集中、フォーカスが別のコンポーネントに移動した場合、その編集を確定する方法をテストします。 image:
概要
セルの編集中、フォーカスが別のコンポーネントに移動した場合、その編集を確定する方法をテストします。- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
サンプルコード
解説
デフォルトのJTable
では、Tabキーやマウスのクリックなどで同じテーブルの別セルにフォーカスが移動すると編集が確定しますが、別のコンポーネントにフォーカスが移動しても編集は確定しません。
-
terminateEditOnFocusLost
-
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
を設定 - 同じフレームを親に持つコンポーネントにフォーカスが移動したとき編集が確定する
- 別フレームのコンポーネントにフォーカスが移動しても編集中の状態が継続する
- ヘッダをクリックしたり、列の入れ替え、サイズ変更を実行すると編集はキャンセルされる
-
-
DefaultCellEditor:focusLost
-
DefaultCellEditor
からエディタコンポーネントを取得してこれにFocusListener
を設定し、セルが編集中ならtable.getCellEditor().stopCellEditing();
を実行 - 別フレームのコンポーネントにフォーカスが移動したときも、編集が確定する
- ヘッダのクリック、入れ替え、サイズ変更などで編集はキャンセルされる
#spandel DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(Object.class); #spanend #spanadd DefaultCellEditor dce = (DefaultCellEditor) table.getDefaultEditor(Object.class); #spanend dce.getComponent().addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { if(!focusCheck.isSelected()) return; if(table.isEditing()) { if (!focusCheck.isSelected()) { return; } if (table.isEditing()) { table.getCellEditor().stopCellEditing(); } } });
-
-
TableHeader:mousePressed
-
TableHeader
にMouseListener
を設定してセルが編集中ならtable.getCellEditor().stopCellEditing();
を実行 - ヘッダをクリックしたとき編集が確定する
-
JDK 1.7.0
ではこのようなMouseListener
をTableHeader
に設定しなくても編集が確定するように修正されている - Bug ID: 4330950 Lost newly entered data in the cell when resizing column width
table.getTableHeader().addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if(!headerCheck.isSelected()) return; if(table.isEditing()) { if (!headerCheck.isSelected()) { return; } if (table.isEditing()) { table.getCellEditor().stopCellEditing(); } } });
-
解説
デフォルトの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();とすると、
- ヘッダをクリックしたとき、編集が確定するようになります。
- JDK 1.7.0 では、TableHeaderにこのMouseListenerを設定しなくても編集が確定するように修正されています。
- Bug ID: 4330950 Lost newly entered data in the cell when resizing column width
親フレームの状態変化でテーブルのヘッダのサイズ変更が発生する場合、ヘッダのリサイズモデルによって、編集中のセルの状態変化が異なります(JDK 1.7.0 では修正されています。Bug ID: 4330950 Lost newly entered data in the cell when resizing column width)。
- JTable.AUTO_RESIZE_OFF
- 親フレームのリサイズや最大化は編集中のまま
- JTable.AUTO_RESIZE_ALL_COLUMNSなど
- 親フレームのリサイズや最大化を行うとヘッダのサイズが変化するため、キャンセル扱い
- 親フレームの状態変化に応じて編集の確定を行う場合は、以下のように
JTable#columnMarginChanged
メソッドなどをオーバーライドしたり、各種リスナーを設定する必要がある
- 親フレームの最小化(アイコン化)は編集中のまま
- 親フレームを閉じる場合はキャンセル扱い
table = new JTable(sorter) {
@Override public void columnMarginChanged(ChangeEvent e) {
if(table.isEditing()) {
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
super.columnMarginChanged(e);
}
};
frame.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
if(table.isEditing()) {
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
}
});
frame.addWindowStateListener(new WindowStateListener() {
@Override public void windowStateChanged(WindowEvent e) {
if(frame.getExtendedState()==JFrame.MAXIMIZED_BOTH
&& table.isEditing()) {
if (frame.getExtendedState() == JFrame.MAXIMIZED_BOTH && table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
}
});
参考リンク
参考リンク
コメント
- どわー。助かりましたっ! -- shun?
- お役に立てて何よりです(自分もこの辺りよく混乱します)。 -- aterai
- columnMarginChanged、役に立ちました。ありがとうございます。 -- はじめ?
- どうもです。JTable#columnMarginChangedメソッドの JavaDoc の説明では、"If a cell is being edited, then editing is stopped and the cell is redrawn."となっているので、JTable#editingStoppedメソッドを使っている(現在の文字列が新しい値となる)のかなと思ったら、実際は、JTable#editingCanceledメソッド(=JTable#removeEditorメソッド)でキャンセルしている(編集内容は適用されない)ので、ちょっと注意が必要なんですよね。 -- aterai
- 1.7.0 では、Bug ID: 4330950 Lost newly entered data in the cell when resizing column width で、修正済みになっているのですが、getCellEditor().cancelCellEditing()を使うように変更されているので、編集が消えてしまうのは同じような・・・。 -- aterai
コメント
- どわー。助かりましたっ! -- shun
- お役に立てて何よりです(自分もこの辺りよく混乱します)。 -- aterai
-
columnMarginChanged
、役に立ちました。ありがとうございます。 -- はじめ- どうもです。
JTable#columnMarginChanged
メソッドのJavaDoc
の説明では、"If a cell is being edited, then editing is stopped and the cell is redrawn."となっているので、JTable#editingStopped
メソッドを使っている(現在の文字列が新しい値となる)のかなと思ったら、実際は、JTable#editingCanceled
メソッド(=JTable#removeEditor
メソッド)でキャンセルしている(編集内容は適用されない)ので、ちょっと混乱してしまいます。 -- aterai -
1.7.0
では、Bug ID: 4330950 Lost newly entered data in the cell when resizing column width で、修正済みになっているのですが、getCellEditor().cancelCellEditing()
を使うように変更されているので、編集が消えてしまうのは同じような・・・。 -- aterai
- どうもです。