1

我有一个 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 的 JTable 部分的教程相当有用,但最终并没有像我希望的那样工作。这个论坛上的其他问题已经接近适用于我的情况,但往往缺乏适用于特定对象类型的关键要素,而不仅仅是特定的单元格。如果我要在我的表中存储大量 Color 对象,我希望它们都以相同的方式运行。

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

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

但是我怎么能用为特定类设置默认渲染器的代码来做到这一点呢?

4

2 回答 2

1

No idea if its the best way to do this but overriding getCellRenderer(int row, int col) may help you:

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) appears to only work with cell renderers places on columns so not much good if you want to only render a single cell differently.

Another alternative that I have seen done is to define a cell renderer, apply it to the collumn and within your cell renderer's getTableCellRendererComponent(...) function determine which data type this is and whether or not to render it or to pass it onto another renderer.

Personally I prefer the first option but if you had heaps of different custom cell types to render and wanted to keep all your rendering code in one class then I can see the appeal of the second option.

于 2015-01-29T11:44:07.830 回答
0

您必须覆盖getColumnClass(int c)tablemodel 中的方法(最好使用 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();
    }

}
于 2015-01-29T11:22:02.000 回答