简体   繁体   中英

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

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.

原版的

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

Boolean.class修复

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

设置Nimbus属性

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

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

在此输入图像描述

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

}
  • 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

在此输入图像描述

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

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() .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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