是否可以在运行时更改组件样式?

时间:2013-07-18 11:56:40

标签: java swing styles look-and-feel nimbus

我使用swing + nimbus来设计我的组件。我想用“Nimbus.Overrides”在运行时更改组件的样式。

private void SetExceptionState() {
    //password.setBackground(new Color(200,0,0,120));
    UIDefaults overrides = new UIDefaults();
    overrides.put("PasswordField.background", Color.red);
    password.putClientProperty("Nimbus.Overrides", overrides);
    password.revalidate();
    password.updateUI();
}

private void ResetExceptionState() {
    //password.setBackground(Color.white);
    UIDefaults overrides = new UIDefaults();
    overrides.put("PasswordField.background", Color.white);
    password.putClientProperty("Nimbus.Overrides", overrides);
}

我第一次设置覆盖时,可以说使用SetExceptionState()方法。我得到一个红色背景。我第二次使用这个没有任何反应。看起来,覆盖只被评估一次。

我想要的是引入密码字段的新状态并将其样式区分开来。有没有可能这样做?

致以最诚挚的问候,

伊格德拉修

1 个答案:

答案 0 :(得分:6)

是的,Nimbus实际上可以监听“Nimbus.Overrides”的更改 - 只是:如果它们是!instanceof UIResource,它不会卸载某些属性。至少是背景,前景,字体的情况(可能也是其他人)

在你的上下文中,你最初安装了一个RED的非资源,有效地告诉laf不再触摸它 - 它符合:-)

我能使其工作的唯一方法是在设置新覆盖之前使背景为空,如:

private void setExceptionState(JComponent password) {
    password.setBackground(null);
    UIDefaults overrides = new UIDefaults();
    overrides.put("PasswordField.background", Color.RED);
    password.putClientProperty("Nimbus.Overrides", overrides);
}

private void resetExceptionState(JComponent password) {
    password.setBackground(null);
    UIDefaults overrides = new UIDefaults();
    overrides.put("PasswordField.background", Color.WHITE);
    password.putClientProperty("Nimbus.Overrides", overrides);
}

<强>更新

实际上,上述内容并未回答真正的问题:

  

引入密码字段的新状态并将其设置为不同

Nimbus确实允许添加自定义状态(虽然结果有些不可预测,因为经常与Synth的那个不受欢迎的最小孩子一起;-)要走的路是

  • 实施自定义状态
  • 使用ui-defaults
  • 注册additonal状态
  • 根据需要附加该州的属性

所有这些配置必须在安装LAF之后完成之前第一个JPasswordField实例化,如果LAF最有可能(没有测试)冒充问题在运行时切换。

protected void installCustomPasswordFieldState() {
    // implement a custom state
    State<JPasswordField> state = new State<JPasswordField>("Invalid") {

        @Override
        protected boolean isInState(JPasswordField c) {
            Object invalid = c.getClientProperty("Invalid");
            return Boolean.TRUE.equals(invalid);
        }

    };
    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
    // register available states 
    // note: couldn't find a way to grab the already available states
    // so this is guesswork
    defaults.put("PasswordField.States", "Enabled, Focused, Invalid");
    // install the custom state
    defaults.put("PasswordField.Invalid", state);
    // install the properties for the custom state
    // note: background has no effect
    defaults.put("PasswordField[Invalid].background", 
            Color.RED); 
    javax.swing.Painter<JComponent> p = new javax.swing.Painter<JComponent>() {

        @Override
        public void paint(Graphics2D g, JComponent object, int width, int height) {
            g.setColor(Color.RED);
            // this is crude - overpainting the complete area, do better!
            g.fillRect(0, 0, width, height);
        }

    };
    // using a painter has an effect 
    defaults.put("PasswordField[Invalid].backgroundPainter", p);
}

// example usage, toggling
// a new property (for simplicity implemented as clientProperty
// to toggle the invalid state
Action reset = new AbstractAction("reset") {
    @Override
    public void actionPerformed(ActionEvent e) {
        boolean isInvalid = Boolean.TRUE.equals(field.getClientProperty("Invalid")); 
        if (isInvalid) {
            field.putClientProperty("Invalid", null); 
        } else {
            field.putClientProperty("Invalid", Boolean.TRUE); 
        }
        field.repaint();
    }
};