如何正确更改复选框文本呈现行为?

时间:2014-07-21 23:58:40

标签: java swing nimbus

我正在使用Nimbus的外观和感觉。

我有两个JCheckBox,默认情况下,启用JCheckBox时文本为黑色,禁用时显示为灰色。我的新要求是程序应该忽略JCheckBox的启用状态,而是在isSelected()为false时显示为灰色,并在isSelected()为true时显示指定颜色的文本。

我试图通过以下方式做到这一点:

  • 扩展BasicCheckBoxUI
  • 覆盖paintText方法
  • 复制BasicButtonUI.paintText()的内容并修改行为
  • 使用我的新UI类的实例调用相关JCheckBox上的setUI

    private static class MyCheckBoxUI extends BasicCheckBoxUI
    {
        private Color selectedColor;
    
        public MyCheckBoxUI( Color selectedColor )
        {
            this.selectedColor = selectedColor;
        }
    
        @Override
        protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text )
        {
            ButtonModel model = b.getModel();
            FontMetrics fm = SwingUtilities2.getFontMetrics(b, g);
            int mnemonicIndex = b.getDisplayedMnemonicIndex();
    
            if( model.isSelected() ) 
            {
                /*** paint the text normally */
                g.setColor( selectedColor );
                SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemonicIndex,
                                          textRect.x + getTextShiftOffset(),
                                          textRect.y + fm.getAscent() + getTextShiftOffset());
            }
            else 
            {
                /*** paint the text disabled ***/
                g.setColor(b.getBackground().brighter());
                SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemonicIndex,
                                          textRect.x, textRect.y + fm.getAscent());
                g.setColor(b.getBackground().darker());
                SwingUtilities2.drawStringUnderlineCharAt(b, g,text, mnemonicIndex,
                                          textRect.x - 1, textRect.y + fm.getAscent() - 1);
            }
        }
    }
    

在我的JPanel的构造函数中,我有以下内容:

        jCheckBox1.setUI( new MyCheckBoxUI( Color.red ) );
        jCheckBox2.setUI( new MyCheckBoxUI( Color.black ) );

这似乎按预期工作,除非有副作用。现在,复选框不会像以前一样选中框中的勾号(我没想到这一点,因为我只重写了paintText方法)。我错过了什么?

此外,使用SwingUtilities2会让我感到不安,因为我警告说它是一个内部专有API,可以在将来的版本中删除。有更好的方法吗?

1 个答案:

答案 0 :(得分:3)

您需要使用UIManager颜色属性...

Object disabledTextForeground = UIManager.get("CheckBox[Disabled].textForeground");
Object enabledTextForeground =  UIManager.get("CheckBox.foreground");
UIManager.put("CheckBox[Disabled].textForeground", UIManager.get("CheckBox.foreground"));
UIManager.put("CheckBox[Enabled].textForeground", disabledTextForeground);
UIManager.put("CheckBox[Selected+Enabled].textForeground", enabledTextForeground);

此示例允许您在全局级别修改值,这意味着您创建的每个JCheckBox将具有相同的值

Options

例如......

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestNimbus {

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

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

                Object disabledTextForeground = UIManager.get("CheckBox[Disabled].textForeground");
                Object enabledTextForeground =  UIManager.get("CheckBox.foreground");
                UIManager.put("CheckBox[Disabled].textForeground", UIManager.get("CheckBox.foreground"));
                UIManager.put("CheckBox[Enabled].textForeground", disabledTextForeground);
                UIManager.put("CheckBox[Selected+Enabled].textForeground", enabledTextForeground);

                JCheckBox cb1 = new JCheckBox("Option #1");
                JCheckBox cb2 = new JCheckBox("Option #2");
                JCheckBox cb3 = new JCheckBox("Option #3");

                cb1.setSelected(true);
                cb3.setEnabled(false);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = gbc.REMAINDER;
                frame.add(cb1, gbc);
                frame.add(cb2, gbc);
                frame.add(cb3, gbc);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

要仅影响JCheckBox的给定实例,您需要直接向要生效的JCheckBox的每个实例提供覆盖...

LocalOptions

前三个值已被覆盖,而后三个值未受影响且使用UI默认值

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestNimbus {

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

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

                UIDefaults checkBoxDefaults = new UIDefaults();

                Object disabledTextForeground = UIManager.get("CheckBox[Disabled].textForeground");
                Object enabledTextForeground = UIManager.get("CheckBox.foreground");
                checkBoxDefaults.put("CheckBox[Disabled].textForeground", UIManager.get("CheckBox.foreground"));
                checkBoxDefaults.put("CheckBox[Enabled].textForeground", disabledTextForeground);
                checkBoxDefaults.put("CheckBox[Selected+Enabled].textForeground", enabledTextForeground);

                JCheckBox cb1 = new JCheckBox("Option #1");
                JCheckBox cb2 = new JCheckBox("Option #2");
                JCheckBox cb3 = new JCheckBox("Option #3");

                JCheckBox cb4 = new JCheckBox("Normal #1");
                JCheckBox cb5 = new JCheckBox("Normal #2");
                JCheckBox cb6 = new JCheckBox("Normal #3");

                configure(cb1, checkBoxDefaults);
                configure(cb2, checkBoxDefaults);
                configure(cb3, checkBoxDefaults);

                cb1.setSelected(true);
                cb4.setSelected(true);
                cb3.setEnabled(false);
                cb6.setEnabled(false);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = gbc.REMAINDER;
                frame.add(cb1, gbc);
                frame.add(cb2, gbc);
                frame.add(cb3, gbc);
                frame.add(cb4, gbc);
                frame.add(cb5, gbc);
                frame.add(cb6, gbc);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

            private void configure(JCheckBox checkbox, UIDefaults uiDefaults) {
                checkbox.putClientProperty("Nimbus.Overrides", uiDefaults);
//                checkbox.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
            }
        });
    }

}