Swing/CellEditorLayout のバックアップの現在との差分(No.4)
TITLE:TableCellEditorのレイアウトを変更
Posted by aterai at 2009-02-02
TableCellEditorのレイアウトを変更
TableCellEditorのレイアウトを変更して、CellEditorの隣にJButtonを配置します。- category: swing folder: CellEditorLayout title: TableCellEditorのレイアウトを変更 tags: [JTable, TableCellEditor, BorderLayout, JTextField, JButton, Focus, KeyboardFocusManager] author: aterai pubdate: 2009-02-02T14:08:34+09:00 description: TableCellEditorのレイアウトを変更して、CellEditorの隣にJButtonを配置します。 image:
概要
TableCellEditor
のレイアウトを変更して、CellEditor
の隣にJButton
を配置します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
class CustomComponentCellEditor extends DefaultCellEditor {
protected final JTextField field;
protected JButton button;
private final JPanel panel = new JPanel(new BorderLayout());
#spanadd
#spanend
public CustomComponentCellEditor(JTextField field) {
super(field);
this.field = field;
button = new JButton();
button.setPreferredSize(new Dimension(25, 0));
field.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
field.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
panel.add(field);
panel.add(button, BorderLayout.EAST);
panel.setFocusable(false);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//System.out.println("getTableCellEditorComponent");
field.setText(value!=null?value.toString():"");
#spanadd
#spanend
@Override public Component getTableCellEditorComponent(
JTable table, Object value,
boolean isSelected, int row, int column) {
// System.out.println("getTableCellEditorComponent");
field.setText(Objects.toString(value, ""));
EventQueue.invokeLater(new Runnable() {
public void run() {
@Override public void run() {
field.requestFocusInWindow();
}
});
return panel;
}
public boolean isCellEditable(final java.util.EventObject e) {
//System.out.println("isCellEditable");
if(e instanceof KeyEvent) {
//System.out.println("KeyEvent");
#spanadd
#spanend
@Override public boolean isCellEditable(final EventObject e) {
// System.out.println("isCellEditable");
if (e instanceof KeyEvent) {
// System.out.println("KeyEvent");
EventQueue.invokeLater(new Runnable() {
public void run() {
char kc = ((KeyEvent)e).getKeyChar();
if(!Character.isIdentifierIgnorable(kc)) {
field.setText(field.getText()+kc);
@Override public void run() {
char kc = ((KeyEvent) e).getKeyChar();
if (!Character.isIdentifierIgnorable(kc)) {
field.setText(field.getText() + kc);
}
field.setCaretPosition(field.getText().length());
//field.requestFocusInWindow();
// field.requestFocusInWindow();
}
});
}
return super.isCellEditable(e);
}
#spanadd
#spanend
@Override public Component getComponent() {
return panel;
}
}
解説
- 0列目
- DefaultCellEditorを継承するCustomComponentCellEditorを作成
- JTextFieldをコンストラクタの引数にしているが、ダミー
- 実体はJPanelで、これをセルエディタとして表示(TableCellEditor#getTableCellEditorComponentがJPanelを返す)
- このJPanelのレイアウトをBorderLayoutにして、JTextFieldとJButtonを配置
- TableCellEditor#getCellEditorValueはJTextFieldの値を返し、フォーカス、キー入力時の編集開始などもJTextFieldになるように変更
- 参考: Swing - JTable editor issue:Darryl.Burke さんの投稿(2009/01/27 20:12 (reply 6 of 8))
解説
-
0
列目-
DefaultCellEditor
を継承するCustomComponentCellEditor
を作成 -
JTextField
をコンストラクタの引数にしているがこれは使用せず、実際のセルエディタはJPanel
で作成して使用-
TableCellEditor#getTableCellEditorComponent
がJPanel
を返す
-
- この
JPanel
のレイアウトをBorderLayout
にしてJTextField
とJButton
を配置 -
TableCellEditor#getCellEditorValue
はJTextField
の値を返し、フォーカス、キー入力時の編集開始などもJTextField
になるように変更 - 参考: Swing - JTable editor issueの、Darryl.Burke さんの投稿(2009/01/27 20:12 (reply 6 of 8))
-
-
1
列目-
DefaultCellEditor
を継承するCustomCellEditor
を作成 -
JTextField
をコンストラクタの引数(セルエディタの実体)として使用 -
JTextField
にJButton
の幅の右余白を設定 -
JTextField
が表示されたときに、余白にJButton
をsetBounds
で配置 - 参考: JTextField内にアイコンを追加
-
- 1列目
- DefaultCellEditorを継承するCustomCellEditorを作成
- JTextFieldをコンストラクタの引数(セルエディタの実体)として使用
- JTextFieldにJButtonの幅の右余白を設定
- JTextFieldが表示されたときに、余白にJButtonをsetBoundsで配置
- 参考:JTextField内にアイコンを追加
class CustomCellEditor extends DefaultCellEditor {
private static final int BUTTON_WIDTH = 20;
protected final JButton button = new JButton();
#spanadd
#spanend
public CustomCellEditor(final JTextField field) {
super(field);
field.add(button);
field.setBorder(BorderFactory.createEmptyBorder(0,2,0,BUTTON_WIDTH));
field.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, BUTTON_WIDTH));
field.addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent e) {
if((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED)!=0
@Override public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0
&& field.isShowing()) {
field.removeAll();
field.add(button);
Rectangle r = field.getBounds();
button.setBounds(r.width-BUTTON_WIDTH, 0, BUTTON_WIDTH, r.height);
button.setBounds(r.width - BUTTON_WIDTH, 0, BUTTON_WIDTH, r.height);
}
}
});
}
#spanadd
#spanend
@Override public Component getComponent() {
// @see JTable#updateUI()
SwingUtilities.updateComponentTreeUI(button);
return super.getComponent();
}
}
- 2列目
- DefaultCellEditorを継承するCustomComponentCellEditor2を作成
- JTextFieldをコンストラクタの引数にしているが、ダミー
- 実体はJPanelを継承するCustomComponentで、これをセルエディタとして表示
- CustomComponent#processKeyBinding(...)をオーバーライドして、キー入力開始時にKeyboardFocusManager.getCurrentKeyboardFocusManager().redispatchEvent(field, e);を呼び出している
- あとは、0列目のCustomComponentCellEditorと同様
-
2
列目-
DefaultCellEditor
を継承するCustomComponentCellEditor2
を作成-
JTextField
をDefaultCellEditor
のコンストラクタの引数にしているがこれは使用せず、実際のセルエディタはJPanel
を継承するCustomComponent
で作成して使用
-
-
CustomComponent#processKeyBinding(...)
をオーバーライドしてキー入力開始時にKeyboardFocusManager.getCurrentKeyboardFocusManager().redispatchEvent(field, e);
を呼び出している -
0
列目のCustomComponentCellEditor
と同様
-
class CustomComponent extends JPanel {
public final JTextField field = new JTextField();
protected JButton button;
#spanadd
#spanend
public CustomComponent() {
super(new BorderLayout(0,0));
super(new BorderLayout(0, 0));
button = new JButton();
this.add(field);
this.add(button, BorderLayout.EAST);
}
@Override protected boolean processKeyBinding(
final KeyStroke ks, final KeyEvent e, int condition, boolean pressed) {
if(!field.isFocusOwner() && !pressed) {
#spanadd
#spanend
@Override protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (!field.isFocusOwner() && !pressed) {
field.requestFocusInWindow();
SwingUtilities.invokeLater(new Runnable() {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.redispatchEvent(field, e);
}
});
}
return super.processKeyBinding(ks, e, condition, pressed);
}
}
#spanadd
#spanend
class CustomComponentCellEditor2 extends DefaultCellEditor {
private final CustomComponent component;
#spanadd
#spanend
public CustomComponentCellEditor2(CustomComponent component) {
super(component.field);
this.component = component;
}
#spanadd
#spanend
@Override public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
component.field.setText(value!=null?value.toString():"");
return this.component;
component.field.setText(value != null ? value.toString() : "");
return component;
}
#spanadd
#spanend
@Override public Component getComponent() {
return component;
}
}
- 3列目
- デフォルト
-
3
列目- デフォルト
参考リンク
参考リンク
コメント
- F2で編集開始した場合、フォーカスできない問題を修正。 -- aterai
- ソースコードだけ変更して、こちらのページの修正を忘れていたorzので、新しく追加した2列目の解説と、最終列はデフォルトであることを追記。スクリーンショットは面倒なので更新しない。 -- aterai
コメント
- F2で編集開始した場合、フォーカスできない問題を修正。 -- aterai
- ソースコードだけ変更して、こちらのページの修正を忘れていたので、新しく追加した
2
列目の解説などを追記。スクリーンショットは面倒なので更新しない。 -- aterai