Changing Swing JTable Cell Colors
Asked Answered
I

5

6

I'm trying to get comfortable with JTables, TableModels, JTableHeaders, renderers, etc. I am trying to make a simple dummy table (for practice purposes) that looks like this:

-    1    2   3
A    A1   A2  A3
B    B1   B2  B3
C    C1   C2  C3

I also want the B2 cell - and only that cell - to have a blue (Color.BLUE) background - all other cells can have the Swing default color they are assigned automagically.

My code is below and is based off countless examples I have found on this website and the internet at large. But I am not getting the results I want. Instead I'm getting a table that looks like this:

A    A1   A2  A3
B    B1   B2  B3
C    C1   C2  C3

Notice that the first row (the header) isn't there at all. Additionally, with the code I list below, this executes and sets the color of all the cells that color, not just the B2 cell that I want.

The code:

public class MyTable
{
    public static void main(String[] args)
    {
        String[][] data = getTableData();
        String[] cols = getTableCols();

        JFrame frame = magicallyCreateJFrame();     // I promise this works!
        MyRenderer myRenderer = new MyRenderer();   // See below

        DefaultTableModel defModel = new DefaultTableModel(data, cols);
        JTable myTable = new JTable(defModel);

        myTable.setDefaultRenderer(Object.class, myRenderer);

        frame.add(myTable);
        frame.pack();
        frame.setVisible(true);            
    }
}

public static String[] getTableCols()
{
    String cols =
    {
        "-",
        "1",
        "2",
        "3",
    };
}

public static String[][] getTableData()
{
    String[][] data =
    {
        {
            "A",
            "A1",
            "A2",
            "A3",
        },
        {
            "B",
            "B1",
            "B2",
            "B3",
        },
        {
            "C",
            "C1",
            "C2",
            "C3",
        },
    };

    return data;
}

And the quick-n-dirty MyRenderer class:

public class MyRenderer extends DefaultTableCellRenderer  
{ 
    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); 

    if(row == 2 && column == 2)
        c.setBackground(new java.awt.Color(0, 0, 255)); 

    return c; 
} 

} 

Besides the fact that this is horrible code and breaks a lot of "best practices"-type patterns and techniques (remember this is just something I'm playing around with), is there anything I'm doing here that is glaringly-obvious? Why am I not getting a table header (first row "- 1 2 3")? Why is my default cell renderer not working on the specific B2 cell I am specifying?

JTables seem to be strange, beautiful and powerful beasts. I'm slowly wrapping my mind around them but am choking on the implementation. Thanks to any that can help!

Illative answered 24/8, 2011 at 20:15 Comment(1)
See also this related example.Quinone
C
15

You need to make sure you reset the renderer to its default background color (and handle row selection):

if (! table.isRowSelected(row))
{
    if(row == 2 && column == 2)
        c.setBackground(new java.awt.Color(0, 0, 255));
    else
        c.setBackground(table.getBackground());
}

In the future post a proper SSCCE with your question.

Chaunceychaunt answered 24/8, 2011 at 20:41 Comment(0)
I
4

Half-answer:

You need to put your JTable inside a JScrollPane to have the header displayed. Or alternatively you can manually add to the layout the component returned by myTable.getTableHeader(). I recommend using a JScrollPane though.

EDIT:

As suggested below, to turn the background blue for just one specific cell, all you need to do is add a test like this one:

if(column == 2 && row == 1) {
    c.setBackground(Color.BLUE); 
} else {
    c.setBackground(Color.WHITE);
}
Isisiskenderun answered 24/8, 2011 at 20:19 Comment(6)
And: what happens if in myTable.setDefaultRenderer(Object.class, myRenderer); you replace Object.class with String.class?Isisiskenderun
how is that going to help his problem?Cuticula
All of the data in my table will be Strings. Do I need to change that invocation to using String.class instead, and if so, will that break anything? What would I need to change to fix such a break?Illative
You're right, it does not help, the custom cell renderer is correctly invoked.Isisiskenderun
@Mara: no, I was wrong, don't change Object.class to String.class. If you have a look at DefaultTableModel's documentation you'll see that it returns Object.class for every column (behavior inherited from AbstractTableModel). So you were right, you need to have myTable.setDefaultRenderer(Object.class, myRenderer);. But look above, I've posted a solution to your problem — just tested, works fine.Isisiskenderun
Hi ChrisJ - The JScrollPane hint worked great and now I am seeing my header, however the MyRenderer conditional check (actually, both the ones you posted as well as the one @Chaunceychaunt posted) code does not work. Table maintains system default color for all cells. Could something be overriden here?Illative
C
3

Where do you specify the renderer to color B2 and only B2? Perhaps you want to place an if block in your getTableCellRendererComponent method so that the background color is set to blue only if the JTable's value object's toString() is "B2" or if the row and column values correspond to the B2 cell.

And to see your table header, you should first add the table to a JScrollPane and then add the JScrollPane to the parent.

Most important: read the Swing tutorials on JTables as this is all explained in there.

Cuticula answered 24/8, 2011 at 20:18 Comment(1)
Thanks Hovercraft - please reference the added conditional in the Renderer class. It's still not working though - what am I missing?Illative
H
0

Perhaps, myTable.setDefaultRenderer(String.class, myRenderer); would work correct.

Henleyonthames answered 24/8, 2011 at 20:35 Comment(0)
G
0

I believe the correct way to do table colouring is via a ColorHighlighter. I have given an example here.

Glue answered 25/5, 2015 at 15:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.