【问题标题】:Change background color of one cell in JTable [duplicate]更改JTable中一个单元格的背景颜色[重复]
【发布时间】:2012-09-03 03:46:01
【问题描述】:

可能重复:
Changing Swing JTable Cell Colors

我开发了一个显示 JTable 的 swing 应用程序。我希望当用户修改单元格值时,修改后的单元格会改变颜色。

这是我在用户修改单元格时运行的代码:

this.myTable.getColumnModel().getColumn(column).setCellRenderer(new StatusColumnCellRenderer()); 

这是我的单元格渲染类的代码:

public class StatusColumnCellRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {

        //Cells are by default rendered as a JLabel.
        JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);

        //Get the status for the current row.
        TableModelLotti tableModel = (TableModelLotti) table.getModel();

        if(isSelected)
            l.setBackground(Color.GREEN);

        //Return the JLabel which renders the cell.
        return l;
    }
}

【问题讨论】:

  • 当用户修改单元格值时:你必须在你的(看不见的)TableModel 中保持这个状态。
  • @trashgod 颜色单元格与表格模型无关,但与 cellRender 相关。
  • 单元格的状态进入TableModel;它的结果颜色应用在渲染器中。
  • @Vinesh - 我刚刚看了这个答案,但没有解决我的问题!我希望用户修改单元格值后单元格颜色发生变化,并且单元格必须保持这种颜色!
  • @trashgod - 你能告诉我怎么做吗?

标签: java swing jtable tablecellrenderer


【解决方案1】:

当您的模型中的单元格被标记为已修改时,您需要一个自定义渲染器来显示绿色。

您还需要一个自定义编辑器来在您的stopCellEditing() 实现中设置模型的已修改 状态,提到了here

自定义渲染器和编辑器的相关示例显示为here

附录:这是所描述方法的一个示例。

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

/**
 * @see https://stackoverflow.com/a/12352838/230513
 */
public class ModifiedCells extends JPanel {

    public ModifiedCells() {
        final MyModel model = new MyModel();
        JTable table = new JTable(model);
        table.setDefaultRenderer(String.class, new MyRenderer());
        table.setDefaultEditor(String.class, new MyEditor(table));
        this.add(table);
    }

    private static class MyRenderer extends DefaultTableCellRenderer {

        Color backgroundColor = getBackground();

        @Override
        public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {
            Component c = super.getTableCellRendererComponent(
                table, value, isSelected, hasFocus, row, column);
            MyModel model = (MyModel) table.getModel();
            if (model.getState(row)) {
                c.setBackground(Color.green.darker());
            } else if (!isSelected) {
                c.setBackground(backgroundColor);
            }
            return c;
        }
    }

    private static class MyEditor extends DefaultCellEditor {

        private JTable table;
        private MyModel model;

        public MyEditor(JTable table) {
            super(new JTextField());
            this.table = table;
            this.model = (MyModel) table.getModel();
        }

        @Override
        public boolean stopCellEditing() {
            model.setState(table.getEditingRow(), true);
            return super.stopCellEditing();
        }
    }

    private static class MyModel extends AbstractTableModel {

        private final List<Row> list = new ArrayList<Row>();

        public MyModel() {
            list.add(new Row("One", true));
            list.add(new Row("Two", false));
            list.add(new Row("Three", false));
        }

        public boolean getState(int row) {
            return list.get(row).state.booleanValue();
        }

        public void setState(int row, boolean state) {
            list.get(row).state = state;
        }

        @Override
        public int getRowCount() {
            return list.size();
        }

        @Override
        public int getColumnCount() {
            return 1;
        }

        @Override
        public Object getValueAt(int row, int col) {
            return list.get(row).name;
        }

        @Override
        public void setValueAt(Object aValue, int row, int col) {
            list.get(row).name = (String) aValue;
            fireTableCellUpdated(row, col);
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        private static class Row {

            private String name;
            private Boolean state;

            public Row(String name, Boolean state) {
                this.name = name;
                this.state = state;
            }
        }
    }

    private void display() {
        JFrame f = new JFrame("ModifiedCells");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ModifiedCells().display();
            }
        });
    }
}

【讨论】:

  • hmm .. 有点在边界线上:a)通常 cellEditor 不能更改模型(此处有所缓解,因为状态不是真正的模型属性,这是另一个边界故事 :-) b ) 应该在改变状态之前调用 super (因为如果 super 返回 false 则不应该调用
  • @kleopatra:我希望你的洞察力;谢谢。 a) 我同意CellEditor;它应该是Row.class 编辑器,而不是String.class;它会做实验。 b) super 调用delegate.stopCellEditing(),在fireEditingStopped() 之后无条件返回true,使table.getEditingRow() 无效。
  • 啊(或者更好的beeee :-)..好点!但是,超类行为是一个不可依赖的实现细节。一个出路(防止在super拒绝停止的情况下设置状态),抓取之前的editingRow,消息super,然后设置状态(或不设置)。
猜你喜欢
  • 2011-09-24
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 2015-10-24
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
  • 1970-01-01
相关资源
最近更新 更多