7

I am using a JTable to visualize some data. One column ist destined to show boolean data through a checkbox. I achieved this by returning Boolean.class from my overriden getColumnClass() function in my table model.

Unfortunately this results in a cell with a checkbox but without a background color appropriate for the current row.

Original

I fixed this by using the answer from this post: JTable - Boolean Cell Type - Background

Boolean.class fix

Now I was trying to increase the contrast of the alternate rows. I achieved this by setting the appropriate property of the Nimbus LAF, which I am using.

UIDefaults defaults = UIManager.getLookAndFeelDefaults();
defaults.put("Table.alternateRowColor", new Color(217, 217, 217));

With set Nimbus property

As you see, the background of the Boolean cells is still the old Nimbus Table.alternateRowColor color.

Is there a way to change this? Am I doing this completely wrong? Is there a better way to achieve alternating background color and more contrast?

EDIT

caused on

java version "1.7.0_17" Java(TM) SE Runtime Environment (build 1.7.0_17-b02) Java HotSpot(TM) Server VM (build 23.7-b01, mixed mode), OS is Ubuntu 12.04

Community
  • 1
  • 1
padde
  • 621
  • 8
  • 19
  • 5
    +1 nice question, good catch, could be very good question for future readers in the case that you'll post an [SSCCE](http://sscce.org/), short, runnable, compilable – mKorbel Apr 17 '13 at 07:47

4 Answers4

7

I was (finally) able to get it to work. The secret was to change the defaults BEFORE you create anything.

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.UIResource;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class TestTable10 {

    public static void main(String[] args) {
        new TestTable10();
    }

    public TestTable10() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                UIManager.getLookAndFeelDefaults().put("Table.alternateRowColor", Color.RED);

                JTable table = new JTable(new MyModel());
                ((JComponent) table.getDefaultRenderer(Boolean.class)).setOpaque(true);


                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MyModel extends AbstractTableModel {

        @Override
        public int getRowCount() {
            return 10;
        }

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

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return "Hello";
                case 1:
                    return true;
            }
            return "?";
        }

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

}
MadProgrammer
  • 323,026
  • 21
  • 204
  • 329
  • Thanks, looks good. Unfortunately I am working with the Netbeans Platform here, so "before you change anything" might be hard to determine. I am currently trying to use an Module Installer to do this at startup and see how it goes. I am also trying @mKorbel answer since its LAF independent. – padde Apr 17 '13 at 08:21
  • Nice solution. I admit that it's better to change the look at L&F level, rather than hardcoding it like other answers suggest. – Adam Dyga May 10 '13 at 11:51
  • @AdamDyga I see a lot of people jumping straight and updating the `JTable` for a lot of reasons, I have a personal issue with this, as it tightly couples the solution with the extension. If you can find ways to allow to keep the code portable, then it's got to be worth the effort, IMHO – MadProgrammer May 10 '13 at 11:57
6
  • I'd be to use standard Renderer concept for this job, instead of playing with Nimbus Constants

  • Renderer works for Nimbus, override all Colors, excluding JTableHeader

  • code based on @camickrs Table Row Rendering

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableRowRenderingTip extends JPanel {

    private static final long serialVersionUID = 1L;

    public TableRowRenderingTip() {
        Object[] columnNames = {"Type", "Company", "Shares", "Price", "Boolean"};
        Object[][] data = {
            {"Buy", "IBM", new Integer(1000), new Double(80.5), Boolean.TRUE},
            {"Sell", "Dell", new Integer(2000), new Double(6.25), Boolean.FALSE},
            {"Short Sell", "Apple", new Integer(3000), new Double(7.35), Boolean.TRUE},
            {"Buy", "MicroSoft", new Integer(4000), new Double(27.50), Boolean.FALSE},
            {"Short Sell", "Cisco", new Integer(5000), new Double(20), Boolean.TRUE}
        };
        DefaultTableModel model = new DefaultTableModel(data, columnNames) {
            private static final long serialVersionUID = 1L;

            @Override
            public Class getColumnClass(int column) {
                return getValueAt(0, column).getClass();
            }
        };
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.addTab("Alternating", createAlternating(model));
        add(tabbedPane);
    }

    private JComponent createAlternating(DefaultTableModel model) {
        JTable table = new JTable(model) {
            private static final long serialVersionUID = 1L;

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                if (!isRowSelected(row)) { //  Alternate row color
                    c.setBackground(row % 2 == 0 ? getBackground() : Color.orange);
                }
                return c;
            }
        };
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        ((JComponent) table.getDefaultRenderer(Boolean.class)).setOpaque(true);
        return new JScrollPane(table);
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            return;
        }
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(false);
        JFrame frame = new JFrame("Table Row Rendering");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TableRowRenderingTip());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
mKorbel
  • 108,320
  • 17
  • 126
  • 296
  • At first this looked awesome. But I am not getting the same results as you are. My Boolean.class column is stil not looking like the others. Unfortunately I don't have an [SSCCE](http://sscce.org/) which I can post here, but I am working on it. **EDIT:** Very strange. I copied your code into a new class and still get a different [look](http://www.abload.de/img/tableweytc.png). – padde Apr 17 '13 at 08:27
  • everything is hidden in your Renderer, there is something ..., please be sure that you'll put Boolean(true/false) to JTable not JCheckBox, nor there isn't something about JCheckBox, then you are out of luck, required to override all key for JCheckBox in UIManager – mKorbel Apr 17 '13 at 08:36
  • As I said in my edit: even with your code I get a different result. Pretty weird.. – padde Apr 17 '13 at 08:41
  • 1
    java version "1.7.0_17" Java(TM) SE Runtime Environment (build 1.7.0_17-b02) Java HotSpot(TM) Server VM (build 23.7-b01, mixed mode), OS is Ubuntu 12.04 – padde Apr 17 '13 at 08:45
  • or (by reading comment to @MadProgrammer) , GUI builedr has onw Bugs, their life_cycle haven't something with standard Oracles JDK, those Framework has Oracles and own Bugs .... – mKorbel Apr 17 '13 at 08:46
  • Win user sorry, I edited tags, have to waiting, there are a few answrers from US zore they are ***nix users, but from Australian too (if I remember correctly) – mKorbel Apr 17 '13 at 08:49
  • Yes, I was suspecting the Netbeans GUI Builder myself. But seeing that I even get different results with your code, I am suspecting Java or Ubuntu.. – padde Apr 17 '13 at 08:50
0

to solve this problem I used jxtable() instead jtable() and I used own prepareRenderer for row colors (you can use mKorbel's one, to put it to table in netbeans just Customize code for jxtable() component), because this solution: JTable - Boolean Cell Type - Background does not work for multi color rows for me. My platform: Windows 7 32bit, java version "1.7.0_21", Java(TM) SE Runtime Environment (build 1.7.0_21-b11), Java HotSpot(TM) Client VM (build 23.21-b01, mixed mode, sharing), netbeans IDE 7.3

Here is png (dont have enought reputation :D): jxtable().

Community
  • 1
  • 1
LuciusAgarthy
  • 65
  • 1
  • 6
0

Immediately after setting Nimbus L&F, add this lines:

    UIManager.getLookAndFeelDefaults().put("Table:\"Table.cellRenderer\".background", Color.DARK_GRAY);
    UIManager.getLookAndFeelDefaults().put("Table.background",new ColorUIResource(Color.DARK_GRAY));
    UIManager.getLookAndFeelDefaults().put("Table.alternateRowColor",Color.DARK_GRAY.brighter());

Note usage of ColorUIResource for Table.background. This fixed the checkbox background issue for me.