如何复制JCheckBox的禁用外观?

时间:2010-06-28 07:16:09

标签: java swing user-interface checkbox

采用以下示例代码。如果组件包含HTML,则Swing中存在一些错误,它不会将禁用的组件呈现为禁用。除了报告我希望同事已经处理过的问题之外,还有一些解决问题的好方法吗?

无论我采取什么解决方案,我都希望它能够成为一个全局解决方案,而不是需要被应用到应用程序中每个复选框的内容。

我尝试为绘制前后调用setForeground的复选框创建自定义UI,但事实证明,通过调用setForeground,它会触发一个事件,最终导致调用{ {1}},它调用渲染器,...

repaint()

3 个答案:

答案 0 :(得分:1)

您可以将复选框和标签分隔到自己的组件中,只需创建一个没有标签的复选框。您也可以将它们添加到自己的面板中,并覆盖面板的setEnabled()方法,只需启用/禁用复选框并更改标签的颜色即可。以此代码段为例:

final JCheckBox checkbox = new JCheckBox();
final JLabel label = new JLabel();
JPanel panel = new JPanel() {
    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        checkbox.setEnabled(enabled);
        if (enabled)
            label.setForeground(Color.BLACK);
        else
            label.setForeground(Color.GRAY);
    }
};
panel.add(checkbox);
panel.add(label);

请注意,checkbox和label必须是最终的才能在我们的面板的setEnabled()方法中使用它们。根据您将HTML插入复选框的频率,您始终可以创建自己的组件类来执行此操作。

public class HTMLCheckBox extends JPanel {
    private JCheckBox checkbox = new JCheckBox();
    private JLabel label = new JLabel();
    private Color disabledColor = Color.GRAY;
    private Color enabledColor = Color.BLACK;

    public HTMLCheckBox(String text) {
        label.setText(text);
        add(checkbox);
        add(label);
    }

    public boolean isSelected() {
        return checkbox.isSelected();
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        checkbox.setEnabled(enabled);
        if (enabled)
            label.setForeground(enabledColor);
        else
            label.setForeground(disabledColor);
    }
}

然后根据需要添加自己的构造函数和方法。例如,覆盖setBackground()以使其设置面板,复选框和标签的背景。更改标签文本的setText()方法可能也很方便。无论你想要它做什么。甚至可能是enabledColordisabledColor的设置者,允许您随意更改这些内容。

答案 1 :(得分:0)

我建议开始使用渲染器而不是那个。您可以在渲染器中使用HTML(例如JLabel),您的问题将自行消失:)

更多信息位于http://java.sun.com/docs/books/tutorial/uiswing/components/combobox.html#renderer

答案 2 :(得分:0)

我必须停止回答我自己的问题......必须与时区有关,并有时间在睡觉时考虑它。

应用程序中的其他位置......

UIManager.put("CheckBoxUI", "package.for.CustomisedWindowsCheckBoxUI");

然后这是实现,但这仍然非常hacky并且它使用实用程序方法来生成HTML颜色字符串,这对于在此处发布来说不太好。

请注意,这仅适用于Windows L& F.金属L& F也见证了有问题,但解决方案是相同的,只是子类BasicCheckBoxUI而已。

import java.awt.Graphics;

import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;

import com.sun.java.swing.plaf.windows.WindowsCheckBoxUI;

import com.blah.util.ColourUtils;

/**
 * Customisation of Windows check box UI to fix bugs.
 */
public class CustomisedWindowsCheckBoxUI extends WindowsCheckBoxUI {
    /**
     * Factory method called from Swing.
     *
     * @param b the check box.
     * @return the UI.
     */
    public static ComponentUI createUI(JComponent b) {
        // TODO: Sun have an AppContext they use to store these once per app.
        //  Might be more sociable to use something like that.
        return new CustomisedWindowsCheckBoxUI();
    }

    @Override
    public void paint(Graphics g, JComponent c) {
        AbstractButton b = (AbstractButton) c;

        // Works around a bug in BasicButtonUI where a disabled button with HTML markup in the text will
        // not appear to be disabled.

        // TODO: Find a way to fix this globally for HTML rendering.  It seems odd that it isn't working.
        // I can see the code in BasicHTML.createHTMLView which uses the foreground colour, which is
        // obviously why setForeground() works as a workaround.

        if (b.getForeground() instanceof ColorUIResource) {
            View view = (View) c.getClientProperty(BasicHTML.propertyKey);
            if (view != null) {
                // Ensure that we don't update the renderer if the value hasn't changed.
                String cachedHtmlFor = (String) c.getClientProperty("cachedHtmlFor");
                String key = String.format("%s:%s", c.isEnabled(), b.getText());
                if (!key.equals(cachedHtmlFor)) {
                    c.putClientProperty("cachedHtmlFor", key);
                    if (c.isEnabled()) {
                        BasicHTML.updateRenderer(c, b.getText());
                    } else {
                        BasicHTML.updateRenderer(c, String.format("<html><div style='color: %s'>%s",
                                                                  ColourUtils.toHtmlColour(b.getBackground().darker()),
                                                                  b.getText()));
                    }
                }
            }
        }

        super.paint(g, c);
    }
}