【问题标题】:Coloring a single cell in a JTable when representing Color objects表示颜色对象时为 JTable 中的单个单元格着色
【发布时间】:2015-03-28 12:34:47
【问题描述】:

我有一个 JTable,用于在不同的行中显示许多不同的数据类型。只有两列,其中左列是变量名称,右列是与变量关联的变量(因此使用 ColumnModel 不适合我的解决方案)。到目前为止,这对于原语非常有效,而用于 JComboBox 和 JCheckBox 的 DefaultRenderer 也非常有效。

我现在正在尝试将 java.awt.Color 集成到表格中,但我希望它被渲染,以便单元格实际上被颜色填充,并且根本没有文本(我不相信这会很困难当我到达那一点时)。到目前为止,我已经完成了单元格的功能;单击单元格会弹出一个 JColorChooser 并返回颜色,然后将其应用于与单元格关联的对象。我使用的代码是:

JTable table = new JTable(new CustomModel(columnNames, values))
{
    //Other functions inside here are excluded to keep it concise

    public void changeSelection(int row, int col, boolean toggle, boolean extend)
    {
        /*Row is a custom object I am using for each row in the table. Its purpose is to
        hold more information about the rows than I would normally be able to. Suffice
        to say for this example, it will be returning something with a Color in it*/
        Row obj = ((CustomModel)(table.getModel())).getRow(row);

        /*ObjectProperties is essentially a modified version of a hashmap that also
        stores the objects type among other things*/
        if(obj.getType() == ObjectProperties.TYPE.COLOR)
        {
            Color newColor = JColorChooser.showDialog(null, "Pick color", Color.RED);

            if(newColor != null)
            {
                table.getModel().setValueAt(newColor, row, col);
            }
        }
        super.changeSelection(row, col, toggle, extend);
    }
}

所以这似乎工作得很好,但现在用于渲染。我想如果我尝试设置一个 DefaultRenderer,它会起作用,所以我使用了以下代码:

table.setDefaultRenderer(Color.class, new ColorRenderer());

我的 ColorRenderer 类如下:

public class ColorRenderer extends JLabel implements TableCellRenderer
{
    public ColorRenderer() 
    {
        setOpaque(true);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
    {
        Color newColor = (Color)value;
        setBackground(newColor);

        return this;
    }
}

但是,当我确实使用它时,我没有运气显示实际的颜色,而是得到了颜色的字符串表示形式(我认为这意味着我的渲染器根本不工作)。所以我还没有真正让它以正确的方式呈现,更不用说在用户选择新东西时改变显示的颜色了。

很长时间以来,我一直在努力让 CustomRenderer 工作,并查看了我可以得到的所有资源。我认为Oracle's JTable section 的教程相当有用,但最终并没有像我希望的那样工作。这个论坛的其他问题已经接近适用于我的情况,但往往缺乏适用于特定对象类型的关键要素,而不仅仅是特定的单元格。如果要在我的表中存储大量 Color 对象,我希望它们都以相同的方式运行。

如果我的实现中存在明显错误或缺失的地方,能指出这一点真是太好了。仔细查看代码(在发布之前我已经重读了很多次,以确保我已经包含了所有内容),我相信问题可能出在我的 Row 类中。它包含一个名为 getValue() 的方法,该方法将返回该对象,因此从技术上讲,我可以调用类似的方法:

if(rowObject.getValue() instanceof Color)
   //Apply renderer

但是如何使用为特定类设置默认渲染器的代码来做到这一点?

【问题讨论】:

  • 你应该使用 Swing 标签来获得更好的答案...
  • @mKorbel 没问题,我会在以后有关于挥杆的问题时这样做。

标签: java swing colors jtable cellrenderer


【解决方案1】:

不知道这是否是最好的方法,但覆盖 getCellRenderer(int row, int col) 可能会对您有所帮助:

public TableCellRenderer getCellRenderer(int row, int col){
            //Only care about the first column
            if(col == 1){
                Row obj = ((CustomModel)(table.getModel())).getRow(row);
                //Check to see if this is a color
                if(obj.getType() == ObjectProperties.TYPE.COLOUR){
                    return super.getDefaultRenderer(Color.class);
                }
            }
            //Either this wasn't a color or it wasn't the first column, either way its super.getCellRenderer's problem now
            return super.getCellRenderer(row, col);
        }

getCellRenderer(int row, int col) 似乎仅适用于列上的单元格渲染器位置,因此如果您只想以不同方式渲染单个单元格,则效果不佳。

我看到的另一种选择是定义一个单元格渲染器,将其应用于列,并在单元格渲染器的getTableCellRendererComponent(...) 函数中确定这是哪种数据类型以及是否渲染它或将其传递给另一个渲染器。

我个人更喜欢第一个选项,但如果您有大量不同的自定义单元格类型要渲染并且希望将所有渲染代码保留在一个类中,那么我可以看到第二个选项的吸引力。

【讨论】:

  • 第一个选项效果很好。我在第二列中确实有几种不同的单元格类型,所以第二个选项可能是我需要研究的。但现在第一个选择是做我需要的。谢谢!
【解决方案2】:

您必须在您的 tablemodel 中覆盖方法 getColumnClass(int c)(最好使用 DefaultTableModel...)

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = ...//same as before...
    private Object[][] data = ...//same as before...

   //taken from http://docs.oracle.com/javase/tutorial/uiswing/components/table.html

    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    public Class getColumnClass(int c) {
        //here - check that the proper class is returned!
        return getValueAt(0, c).getClass();
    }

}

【讨论】:

  • 这真的很接近工作,但对我来说唯一的问题是每一行在第二列中可能包含不同的数据类型。因此,例如,第一行可能代表一个字符串,但第二行可能代表一个颜色。在这种情况下,我看不到在调用 getColumnClass() 时传入我所指的行的方法,这将导致错误的类返回。
猜你喜欢
  • 2013-03-14
  • 1970-01-01
  • 2012-10-03
  • 2013-04-09
  • 2023-04-04
  • 2015-08-13
  • 2015-11-29
  • 1970-01-01
  • 2013-06-30
相关资源
最近更新 更多