Trashgodの優れた例hereに従って、おそらく複雑な方法で単純なタスクを実行する小さなデモをまとめました。以下に示す GUI は、真/偽の値を表すアイコンの列を表示します。アイコンをクリックすると、値が実際とは逆に変更されます。チェックボックスによく似ていますが、外観が異なり、より拡張可能です (たとえば、将来的には、2 つのブール記号だけでなく、12 個の記号を循環するように変更できます)。
JComponent のダミー拡張機能であるカスタム エディタを使用して実行しました。ただし、このダミー コンポーネントが表示されることさえありません。これは、イベントを取得するとすぐにMousePressed
エディターがfireEditingStopped()
. 私が見つけた1つの奇妙なバグを除いて、それはうまく機能します。記号をクリックして変更し、マウスを画面上の別の場所に移動してキーボードのキーを押すと、最後にクリックしたセルにダミー エディターが表示され (効果的にセルが空白になります)、変更するまでそこにとどまります。マウスをセルに移動するか、別のセルをクリックします。
これに対するハックな修正として、レンダリング後にテーブル全体を常に選択解除する行をレンダラーに追加しました。これはうまく機能し、テーブル全体が実際に選択解除されていることを確認しました。ただし、それにもかかわらず、キーボードのキーを押すと、最後に編集されたセルのエディターが引き続き実行されます。この動作を防ぐにはどうすればよいですか? アプリケーションに他のキーボード リスナーがあり、セルが選択されていない場合は、それらのエディターを実行する必要はないと思います。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.imageio.ImageIO;
import javax.swing.AbstractCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
public class JTableBooleanIcons {
private JFrame frame;
private DefaultTableModel tableModel;
private JTable table;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JTableBooleanIcons window = new JTableBooleanIcons();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public JTableBooleanIcons() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tableModel = new DefaultTableModel(new Object[]{"Words", "Pictures"},0);
table = new JTable(tableModel);
table.setRowHeight(40);
tableModel.addRow(new Object[]{"click icon to change", false});
tableModel.addRow(new Object[]{"click icon to change", true});
tableModel.addRow(new Object[]{"click icon to change", false});
tableModel.addRow(new Object[]{"click icon to change", true});
tableModel.addRow(new Object[]{"click icon to change", false});
tableModel.addRow(new Object[]{"click icon to change", true});
tableModel.addRow(new Object[]{"click icon to change", false});
tableModel.addRow(new Object[]{"click icon to change", true});
frame.getContentPane().add(table, BorderLayout.CENTER);
table.getColumn("Pictures").setCellRenderer(new BooleanIconRenderer());
table.getColumn("Pictures").setCellEditor(new BooleanIconEditor());
}
@SuppressWarnings("serial")
private class BooleanIconRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int col) {
String iconFilename = null;
if ((boolean) value) {
iconFilename = "yes.png";
value = true;
} else {
iconFilename = "no.png";
value = false;
}
try {
setIcon(new ImageIcon(ImageIO.read(BooleanIconRenderer.class.getResourceAsStream(iconFilename))));
} catch (Exception e) {
System.err.println("Failed to load the icon.");
}
if (isSelected) {
this.setBackground(Color.white);
} else {
this.setBackground(Color.white);
}
table.getSelectionModel().clearSelection();
return this;
}
}
@SuppressWarnings("serial")
private class BooleanIconEditor extends AbstractCellEditor implements TableCellEditor, MouseListener {
private BooleanComponent boolComp;
public BooleanIconEditor() {
boolComp = new BooleanComponent(false);
boolComp.addMouseListener(this);
}
@Override
public Object getCellEditorValue() {
return boolComp.getValue();
}
@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
boolComp.setValue(! (boolean) value);
return boolComp;
}
@Override
public void mouseClicked(MouseEvent e) {
this.fireEditingStopped();
}
@Override
public void mousePressed(MouseEvent e) {
this.fireEditingStopped();
}
@Override
public void mouseReleased(MouseEvent e) {
this.fireEditingStopped();
}
@Override
public void mouseEntered(MouseEvent e) {
this.fireEditingStopped();
}
@Override
public void mouseExited(MouseEvent e) {
this.fireEditingStopped();
}
}
@SuppressWarnings("serial")
private class BooleanComponent extends JComponent {
private boolean value;
public BooleanComponent(boolean value) {
this.value = value;
}
public boolean getValue() {
return value;
}
public void setValue(boolean value) {
this.value = value;
}
}
}