简体   繁体   English

表示Color对象时为JTable中的单个单元格着色

[英]Coloring a single cell in a JTable when representing Color objects

I have a JTable that is used to display numerous different data types in different rows. 我有一个JTable,用于在不同的行中显示许多不同的数据类型。 There are only two columns, where the left column is the variable name and the right column is the variable associated with the variable (so using a ColumnModel is not appropriate for my solution). 只有两列,其中左列是变量名,右列是与变量关联的变量(因此,使用ColumnModel不适合我的解决方案)。 So far this works really well for primitives, and the DefaultRenderer's for JComboBox's and JCheckBox's works well. 到目前为止,这对于基元确实非常有效,对于JComboBox和JCheckBox的DefaultRenderer效果很好。

I am now trying to integrate java.awt.Color into the table, but I would like it rendered so that the cell is actually filled with the Color, and simply have no text (I don't believe that will be difficult at all when I get to that point). 我现在正在尝试将java.awt.Color集成到表中,但是我希望将其呈现为使得单元格实际上充满了Color,并且根本没有文本(我不相信这在任何时候都不会很困难我明白了这一点。 So far I have the functionality of the cell complete; 到目前为止,我已经完成了单元的功能; clicking on the cell brings up a JColorChooser and returns the Color, where it will then be applied to the object that is associated with the cell. 单击单元格将弹出JColorChooser并返回Color,然后将其应用于与该单元格关联的对象。 The code I am using for that is: 我为此使用的代码是:

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);
    }
}

So this seems to work nicely, but now for the rendering. 因此,这似乎工作得很好,但现在用于渲染。 I figured if I tried to set a DefaultRenderer, it would work, so I used the line: 我发现如果尝试设置DefaultRenderer,它将起作用,所以我使用了以下代码:

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

My ColorRenderer class is as follows: 我的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;
    }
}

When I did use this however, I had no luck in displaying the actual Color, instead I got a String representation of the Color (I figure this means that my renderer isn't working at all). 但是,当我使用它时,我并没有显示实际的Color,而是获得了Color的String表示(我认为这意味着我的渲染器根本无法工作)。 So I'm still yet to actually make it render the correct way, let alone have the ability to change the Color displayed when the user chooses something new. 因此,我仍然没有真正使它呈现正确的方式,更不用说当用户选择新内容时,它还可以更改显示的颜色。

I have been struggling with getting CustomRenderer's working for a long time now, having looked through every resource I could get my hands on. 我一直在努力让CustomRenderer正常工作,已经浏览了我可以使用的所有资源。 The tutorial at Oracle's JTable section was fairly useful I thought, but in the end did not work as I'd hoped. 我认为Oracle的JTable部分中的教程非常有用,但最终并没有按我希望的那样工作。 Other questions around this forum have been close to applying to my situation, but have often lacked the crucial element of applying to a particular object type, not just a particular cell. 这个论坛上的其他问题已经接近于适用于我的情况,但是通常缺少适用于特定对象类型(而不仅仅是特定单元格)的关键要素。 If I were to have numerous Color objects stored in my table, I would ideally like them all to behave the same way. 如果我要在表中存储许多Color对象,则理想情况下,我希望它们都以相同的方式运行。

If there is something glaringly wrong or missing from my implementation, it would be fantastic to have this pointed out. 如果我的实现中存在明显的错误或遗漏,那么指出这一点将是很棒的。 Looking at the code closer (I have reread this before posting it numerous times to make sure I have included everything), I believe the issue may be in my Row class. 仔细研究一下代码(在多次发布之前,我已经重新阅读了一下,以确保我已经包括了所有内容),我相信问题可能出在我的Row类中。 It contains a method called getValue() that will return the object, so technically I could call something like: 它包含一个名为getValue()的方法,该方法将返回该对象,因此从技术上讲,我可以调用以下方法:

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

But how could I do this with the code that sets a Default Renderer for a particular class? 但是,如何使用为特定类设置默认渲染器的代码来做到这一点呢?

No idea if its the best way to do this but overriding getCellRenderer(int row, int col) may help you: 不知道它是否是执行此操作的最佳方法,但重写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) appears to only work with cell renderers places on columns so not much good if you want to only render a single cell differently. getCellRenderer(int row, int col)似乎仅适用于列上的单元格渲染器位置,因此如果您只想以不同的方式渲染单个单元格,则效果不佳。

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. 我见过的另一种替代方法是定义一个单元格渲染器,将其应用于列,并在您的单元格渲染器的getTableCellRendererComponent(...)函数中确定这是哪种数据类型,以及是否渲染它或将其传递给另一个渲染器。

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. 就我个人而言,我更喜欢第一种选择,但是如果您要渲染大量不同的自定义单元格类型,并且希望将所有呈现代码保留在一个类中,那么我可以看到第二种选择的吸引力。

you must override the methode getColumnClass(int c) int your tablemodel (best you use DefaultTableModel...) 您必须重写方法getColumnClass(int c) int您的表模型中(最好使用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();
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM