JTable - Problems with Boolean.class Cell Renderer and Nimbus Look and Feel
Asked Answered
P

4

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

Perfunctory answered 17/4, 2013 at 7:43 Comment(1)
+1 nice question, good catch, could be very good question for future readers in the case that you'll post an SSCCE, short, runnable, compilableRisorgimento
E
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;
        }
    }

}
Egesta answered 17/4, 2013 at 8:4 Comment(3)
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 @Risorgimento answer since its LAF independent.Perfunctory
Nice solution. I admit that it's better to change the look at L&F level, rather than hardcoding it like other answers suggest.Bordie
@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, IMHOEgesta
R
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);
    }
}
Risorgimento answered 17/4, 2013 at 8:0 Comment(7)
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 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.Perfunctory
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 UIManagerRisorgimento
As I said in my edit: even with your code I get a different result. Pretty weird..Perfunctory
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.04Perfunctory
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 ....Risorgimento
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)Risorgimento
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..Perfunctory
L
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().

Loutish answered 10/5, 2013 at 11:44 Comment(0)
H
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.

Hannan answered 9/3, 2014 at 23:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.