JTable - 使用Boolean.class单元格渲染器和Nimbus外观存在问题

7
我正在使用JTable来可视化一些数据。其中一列通过复选框显示布尔数据。我通过在表格模型中覆盖getColumnClass()函数并返回Boolean.class来实现这一点。
不幸的是,这会导致一个带有复选框但没有适合当前行的背景颜色的单元格。
我通过使用此帖子的答案进行修复:JTable - Boolean Cell Type - Background 现在,我尝试增加交替行的对比度。我通过设置我正在使用的Nimbus LAF的适当属性来实现这一点。
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
defaults.put("Table.alternateRowColor", new Color(217, 217, 217));

设置 Nimbus 属性

正如你所看到的,布尔单元格的背景仍然是旧的 Nimbus Table.alternateRowColor 颜色。

有没有办法改变这个?我做错了吗?有更好的方法来实现交替的背景颜色和更强烈的对比度吗?

编辑

发生在

java 版本 "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),操作系统是 Ubuntu 12.04


5
+1 不错的问题,很好的发现。如果您发布一个SSCCE,即短小、可运行、可编译的代码示例,这可能是未来读者非常感兴趣的好问题。 - mKorbel
4个回答

7

最终我终于使它工作了。秘诀是在创建任何东西之前更改默认值。

在此输入图片描述

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

}

谢谢,看起来不错。不幸的是,我正在使用Netbeans平台,所以“在更改任何内容之前”可能很难确定。我目前正在尝试使用模块安装程序在启动时执行此操作,并查看效果如何。我还在尝试@mKorbel的答案,因为它与LAF无关。 - padde
不错的解决方案。我承认,在外观和感觉(L&F)层面上进行更改比像其他答案建议的那样硬编码更好。 - Adam Dyga
@AdamDyga 我看到很多人因为各种原因直接跳过并更新 JTable,我个人对此有些问题,因为它会将解决方案与扩展紧密耦合。如果您能找到方法使代码具有可移植性,那么这肯定是值得努力的,我的看法是这样的。 - MadProgrammer

6
  • 我建议使用标准的Renderer概念来完成此任务,而不是玩弄Nimbus Constants

  • Renderer适用于Nimbus,覆盖所有颜色,但不包括JTableHeader

  • 代码基于@camickrs的表格行渲染

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

起初看起来很棒。但是我得到的结果与你不同。我的Boolean.class列仍然不像其他列那样。不幸的是,我没有可以在这里发布的SSCCE,但我正在努力解决。编辑:非常奇怪。我将你的代码复制到一个新类中,仍然得到不同的外观 - padde
正如我在编辑中所说的:即使使用您的代码,我也得到了不同的结果。相当奇怪... - padde
1
Java版本为"1.7.0_17" Java(TM) SE运行时环境版本为(1.7.0_17-b02) Java HotSpot(TM) Server虚拟机版本为(23.7-b01, 混合模式) 操作系统为Ubuntu 12.04 - padde
GUI构建器有一个Bug,它们的生命周期与标准的Oracle JDK没有关系,这些框架有Oracle和自己的Bug... - mKorbel
抱歉,Win用户,我编辑了标签,需要等待一下。有一些来自美国的答案者是***nix用户,但也有来自澳大利亚的(如果我没记错的话)。 - mKorbel
显示剩余2条评论

0

在设置Nimbus L&F之后,添加以下行:

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

请注意在Table.background中使用ColorUIResource。 这为我解决了复选框背景问题。

0
为了解决这个问题,我使用jxtable()代替jtable(),并使用自己的prepareRenderer来设置行颜色(您可以使用mKorbel的方法将其放置在Netbeans中的jxtable()组件上),因为对于我而言,JTable - Boolean Cell Type - Background 这个解决方案无法实现多彩色的行。我的平台是:Windows 7 32位,java版本为"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。

这里有个png(没足够的声望:D):jxtable()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接