Swing/DeleteButtonInCell のバックアップの現在との差分(No.12)
TITLE:JTableのセルにJButtonを追加して行削除
Posted by aterai at 2007-10-22
JTableのセルにJButtonを追加して行削除
JTableのセルにJButtonを追加し、クリックされたらその行を削除します。主にSwing - JButton inside JTable Cellの投稿を参考にしています。- category: swing folder: DeleteButtonInCell title: JTableのセルにJButtonを追加して行削除 tags: [JTable, JButton, TableCellRenderer, TableCellEditor, ActionListener] author: aterai pubdate: 2007-10-22T07:55:05+09:00 description: JTableのセルにJButtonを追加し、クリックされたらその行を削除します。 image:
概要
JTable
のセルにJButton
を追加し、クリックされたらその行を削除します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spanadd
class DeleteButton extends JButton {
#spanend
@Override public void updateUI() {
super.updateUI();
setBorder(BorderFactory.createEmptyBorder());
setFocusable(false);
setRolloverEnabled(false);
setText("X");
}
#spanadd
}
#spanend
#spandel
**サンプルコード [#i9dca28f]
#spanend
#spandel
#code{{
#spanend
#spandel
class ButtonColumn extends AbstractCellEditor
#spanend
implements TableCellRenderer, TableCellEditor {
private static final String LABEL = "X";
private final JButton renderButton = new JButton(LABEL);
private final JButton editorButton;
public ButtonColumn() {
#spanadd
class DeleteButtonRenderer extends DeleteButton implements TableCellRenderer {
#spanend
public DeleteButtonRenderer() {
super();
editorButton = new JButton(new AbstractAction(LABEL) {
public void actionPerformed(ActionEvent e) {
setName("Table.cellRenderer");
}
#spanadd
#spanend
@Override public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int column) {
return this;
}
#spanadd
}
#spanend
#spanadd
#spanend
#spanadd
class DeleteButtonEditor extends DeleteButton implements TableCellEditor {
#spanend
public DeleteButtonEditor(final JTable table) {
super();
addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
int row = table.convertRowIndexToModel(table.getEditingRow());
fireEditingStopped();
((DefaultTableModel) table.getModel()).removeRow(row);
}
});
editorButton.setBorder(BorderFactory.createEmptyBorder());
renderButton.setBorder(BorderFactory.createEmptyBorder());
editorButton.setFocusPainted(false);
editorButton.setRolloverEnabled(false);
//renderButton.setToolTipText("Delete(renderButton)");
//editorButton.setToolTipText("Delete(editorButton)");
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
return renderButton;
#spanadd
#spanend
@Override public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
return this;
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
return editorButton;
#spanadd
#spanend
@Override public Object getCellEditorValue() {
return "";
}
public Object getCellEditorValue() {
return LABEL;
}
#spanadd
#spanend
// Copied from AbstractCellEditor
// protected EventListenerList listenerList = new EventListenerList();
// transient protected ChangeEvent changeEvent = null;
// ...
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、ボタンがクリックされたときの削除自体は、JTableに追加したマウスリスナーで行っており、セルエディタやセルレンダラーに使っているJButtonは表示のためのダミーです。#spanend
#spandel
table.addMouseListener(new MouseAdapter() {
#spanend
private int targetRow = -1;
@Override public void mousePressed(MouseEvent e) {
Point pt = e.getPoint();
int mcol = table.convertColumnIndexToModel(table.columnAtPoint(pt));
int vrow = table.rowAtPoint(e.getPoint());
int mrow = (vrow>=0)?table.convertRowIndexToModel(vrow):-1;
if(mrow>=0 && mcol==BUTTON_COLUMN) {
targetRow = mrow;
}
}
@Override public void mouseReleased(MouseEvent e) {
Point pt = e.getPoint();
int mcol = table.convertColumnIndexToModel(table.columnAtPoint(pt));
int vrow = table.rowAtPoint(e.getPoint());
int mrow = (vrow>=0)?table.convertRowIndexToModel(vrow):-1;
if(targetRow==mrow && mcol==BUTTON_COLUMN) {
model.removeRow(mrow);
}
targetRow = -1;
}
#spandel
});
#spanend
#spandel
解説
- セルレンダラーに使用する
JButton
は表示専用でクリックイベントなどは無視される - セルエディタとして使用する
JButton
にActionListener
を追加し、このJButton
がクリックされたらAbstractCellEditor
からコピーしたfireEditingStopped()
メソッドでセルの編集を終了し、TableModel
から対象行を削除- セルレンダラー、セルエディタがコンポーネント(もしくは
DefaultCellEditor
)を継承していないとJTable
のLookAndFeel
を変更てもセルレンダラー、セルエディタのupdateUI()
が呼ばれない-
JTable#updateUI()
、Java 1.6.0
のJTable#updateSubComponentUI(...)
、Java 1.7.0
のSwingUtilities#updateRendererOrEditorUI(Object)
を参照
-
-
AbstractCellEditor
を継承していてもupdateUI()
は呼ばれない、DefaultCellEditor
は継承しづらい…
- セルレンダラー、セルエディタがコンポーネント(もしくは
#spanend
#spandel
public ButtonColumn(final JTable table) {
#spanend
super();
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
editorButton = new JButton(new AbstractAction(LABEL) {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
int row = table.convertRowIndexToModel(table.getSelectedRow());
((DefaultTableModel)table.getModel()).removeRow(row);
}
});
//...
#spandel
複数選択を許可する場合は、Ctrlキーなどを押しながらのボタンクリックに注意する必要があります。
参考リンク
- Swing - JButton inside JTable Cell
- JTableの行を追加、削除
- JTableの行を全削除
- JTableのセルに複数のJButtonを配置する
- JTableのセルにHyperlinkを表示
参考リンク
- Swing - JButton inside JTable Cell
- JTableの行を追加、削除
- JTableの行を全削除
- JTableのセルに複数のJButtonを配置する
- JTableのセルにHyperlinkを表示
コメント
- ボタンのセル内でマウスを移動しても削除するように変更。 -- aterai
- メモ:
修正済み: Bug ID: 6291631 JTable: rowAtPoint returns 0 for negative y (追記: このバグは未修正になっているけど、0
行目のボタンをクリックし、真上のヘッダ上でリリースしても削除可能JDK 1.6, 1.7
などのソースではコメントにある修正が追加されている) -- aterai
- メモ:
コメント
- ボタンのセル内でマウスを移動しても削除するように変更。 -- aterai
- メモ: 0行目のボタンをクリックし、真上のヘッダ上でリリースしても削除できる -> Bug ID: 6291631 JTable: rowAtPoint returns 0 for negative y -- aterai
//上記のBug Databaseにある回避方法 JTable table = new JTable(model) { @Override public int rowAtPoint(Point pt) { return (pt.y<0)?-1:super.rowAtPoint(pt); return (pt.y < 0) ? -1 : super.rowAtPoint(pt); } };
- メモ: 0行目のボタンをクリックし、真上のヘッダ上でリリースしても削除できる -> Bug ID: 6291631 JTable: rowAtPoint returns 0 for negative y -- aterai
- テスト -- aterai
- テスト -- aterai
- JTableのセルに複数のJButtonを配置するに移動。 -- aterai