TITLE:JTableのセルにJCheckBoxを表示して行背景色を変更

JTableのセルにJCheckBoxを表示して行背景色を変更

Posted by terai at 2008-07-14
  • category: swing folder: CheckedRowColor title: JTableのセルにJCheckBoxを表示して行背景色を変更 tags: [JTable, JCheckBox, TableModelListener, TableCellRenderer, TableCellEditor] author: aterai pubdate: 2008-07-14T14:18:45+09:00 description: JTableのセルに表示されているJCheckBoxがチェックされていれば、その行の背景色を変更します。 image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTI7wkSMbI/AAAAAAAAATk/uGVLWCqLJUI/s800/CheckedRowColor.png

概要

JTableのセルに表示されているJCheckBoxがチェックされていれば、その行の背景色を変更します。

概要

JTableのセルに表示されているJCheckBoxがチェックされていれば、その行の背景色を変更します。
  • &jnlp;
  • &jar;
  • &zip;

#screenshot

サンプルコード

#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
JTable table = new JTable(model) {
    @Override
    public Component prepareEditor(TableCellEditor editor, int row, int column) {
        Component cmp = super.prepareEditor(editor, row, column);
        if(convertColumnIndexToModel(column) == BOOLEAN_COLUMN) {
            //System.out.println("JTable: prepareEditor");
            JCheckBox c = (JCheckBox)cmp;
            c.setBackground(c.isSelected()? Color.ORANGE:getBackground());
        }
        return cmp;
  @Override public Component prepareEditor(
        TableCellEditor editor, int row, int column) {
    Component cmp = super.prepareEditor(editor, row, column);
    if (convertColumnIndexToModel(column) == BOOLEAN_COLUMN) {
      JCheckBox c = (JCheckBox) cmp;
      c.setBackground(c.isSelected() ? Color.ORANGE : getBackground());
    }
    @Override
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        Boolean isChecked = (Boolean) model.getValueAt(
            convertRowIndexToModel(row), BOOLEAN_COLUMN);
        c.setForeground(getForeground());
        c.setBackground(isChecked? Color.ORANGE:getBackground());
        return c;
    }
    return cmp;
  }
#spanadd

#spanend
  @Override public Component prepareRenderer(
        TableCellRenderer renderer, int row, int column) {
    Component c = super.prepareRenderer(renderer, row, column);
    Boolean isChecked = (Boolean) model.getValueAt(
      convertRowIndexToModel(row), BOOLEAN_COLUMN);
    c.setForeground(getForeground());
    c.setBackground(isChecked ? Color.ORANGE : getBackground());
    return c;
  }
};

解説

上記のサンプルでは、JTableのprepareEditor、prepareRendererをオーバーライドしてセルエディタや行の背景色を変更しています。

解説

上記のサンプルでは、JTableprepareEditorprepareRendererをオーバーライドして編集中のセルエディタ(JCheckBox)や同じ行の背景色を変更しています。
  • - 以下のように、TableCellRendererやCellEditorを利用して、JTableをオーバーライドしない方法*1もあります。
  • デフォルトのセルレンダラーの場合、例えばチェックボックスがクリックされてモデルが更新されるとその対応するセルのみ再描画さる
  • このサンプルでは対象セルだけではなくそのセルが存在する行全体の背景色を変更しているので、TableModelListenerでモデルの更新を検出し、以下のようにJTable#repaint(...)メソッドを使って行を再描画
    #spandel
    private static JTable makeTable2(final DefaultTableModel model) {
    #spanend
        final JTable table = new JTable(model);
        TableColumnModel columns = table.getColumnModel();
        for(int i=0;i<columns.getColumnCount();i++) {
            columns.getColumn(i).setCellRenderer(new RowColorTableRenderer(
                table.getDefaultRenderer(model.getColumnClass(i))));
    #spanadd
    model.addTableModelListener(new TableModelListener() {
    #spanend
      @Override public void tableChanged(TableModelEvent e) {
        if (e.getType() == TableModelEvent.UPDATE) {
          // rowRepaint(table, table.convertRowIndexToView(e.getFirstRow()));
          Rectangle r = table.getCellRect(
              table.convertRowIndexToView(e.getFirstRow()), 0, true);
          r.width  = table.getWidth();
          // table.repaint(); // table全体をリペイントする必要はないので
          table.repaint(r);   // 一行だけリペイント
        }
        DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(model.getColumnClass(BOOLEAN_COLUMN));
        final JCheckBox check = (JCheckBox)dce.getComponent();
        check.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                System.out.println("JCheckBox: focusGained");
                JCheckBox c = (JCheckBox)e.getSource();
                c.setBackground(c.isSelected()?Color.ORANGE:table.getBackground());
            }
        });
        table.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                int col = table.columnAtPoint(e.getPoint());
                if(table.convertColumnIndexToModel(col)==BOOLEAN_COLUMN) {
                    System.out.println("JTable: mousePressed");
                    int row = table.rowAtPoint(e.getPoint());
                    Boolean isChecked = (Boolean) model.getValueAt(table.convertRowIndexToModel(row), BOOLEAN_COLUMN);
                    check.setBackground(isChecked?Color.ORANGE:table.getBackground());
                }
            }
        });
        return table;
    #spandel
    }
    #spanend
    #spandel
    static class RowColorTableRenderer implements TableCellRenderer {
    #spanend
        private final Color evenColor = new Color(240, 240, 255);
        private final TableCellRenderer renderer;
        public RowColorTableRenderer(TableCellRenderer renderer) {
            this.renderer = renderer;
        }
        public Component getTableCellRendererComponent(JTable table, Object value,
                    boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            TableModel model = table.getModel();
            Boolean isChecked = (Boolean) model.getValueAt(table.convertRowIndexToModel(row), BOOLEAN_COLUMN);
            c.setForeground(table.getForeground());
            c.setBackground(isChecked?Color.ORANGE:table.getBackground());
            return c;
        }
    #spandel
    }
    #spanend
      }
    #spanadd
    });
    #spanend
    

参考リンク

参考リンク

コメント

コメント