【问题标题】:removeEvent ItemListener (removeItemListener) from within itemStateChanged doesn't work (StackOverfowError)itemStateChanged 中的 removeEvent ItemListener (removeItemListener) 不起作用 (StackOverfowError)
【发布时间】:2018-03-05 18:03:38
【问题描述】:

我有以下代码,我不能使用setEnabled(false),因为我需要设置背景色和前景色。

public class RadioButton extends JRadioButton implements ItemListener {
    public RadioButton(String text)
    {
        super(text);

        addItemListener(this);
    }

    public void itemStateChanged(ItemEvent e) {
        synchronized (this) {
            removeItemListener(this);
            if (e.getStateChange() == ItemEvent.SELECTED) {
                System.out.println("item is selected true [changed]");
                setSelected(false);
            } else if (e.getStateChange() == ItemEvent.DESELECTED) {
                System.out.println("item is selected false [changed]");
                setSelected(true);
            }
            addItemListener(this);
        }
    }
}

这应该是一个单选按钮,不能更改。但是,如果我尝试测试代码,它会给我一个无限循环打印

item 被选中 true [已更改]

一次...

...然后总是

项目被选中 false [已更改]

直到有一个Java StackOverflowError

这怎么可能?禁用 ItemListener 是否不起作用?

如果可以的话,请告诉我如何将其打包到 lamda 函数中。在尝试将其放入 lamda 函数时,我收到了 illegal self reference-error。

如果标题不正确,请纠正我。

【问题讨论】:

  • 删除可能效果很好,但你也可以在最后添加它
  • @XtremeBaumer 是有意的。因为我调用 setSelected(...) 之前 我再次添加了ItemListener
  • 一种更简单的解决方案是将ButtonModel 替换为不改变isSelected 状态的解决方案
  • 我的问题是,为什么?为什么需要一个不能选择但不能禁用的按钮?我问的原因是,作为用户,如果我看到一个在视觉上难以处理但不会改变状态的按钮,我会很生气 - 我认为按钮或程序有问题
  • @MadProgrammer 我有一个程序可以询问考试问题并评估它们。我更改了评估单选按钮和复选框的背景颜色和前景颜色。从上下文中可以清楚地看出,它们并不是要由用户检查,而是代表正确的选择。正如我在问题中解释的那样,如果我使用 setEnabled(false),我无法设置背景色和前景色(灰色调也令人不安)。

标签: java swing events radio-button disabled-control


【解决方案1】:

正如MadProgrammer 指出的那样,禁用AbstractButton(又名RadioButtonCheckbox)可以通过将ButtonModel 设置为始终返回恒定值的自定义值来归档。

主类:

radioButtonOrCheckbox.setModel(new ButtonCustomModel(true));

ButtonCustomModel:

public class ButtonModel implements javax.swing.ButtonModel {
    protected boolean state;

    public ButtonModel(boolean state)
    {
        this.state = state;
    }

    @Override
    public boolean isSelected() {
        return state;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    // other methods of ButtonModel-interface
    [...]
}

【讨论】:

    【解决方案2】:

    我不能使用 setEnabled(false),因为我需要设置背景色和前景色

    这可能只是个人的事情,但我有一个明显的不喜欢或不符合既定规范和用户期望的 UI。

    因此,当一个按钮不应该被交互时,它应该被禁用。这是用户立即理解的约定。

    我更改了评估单选按钮和复选框的背景色和前景色。

    好的,所以你想以某种方式装饰按钮,这很公平

    从上下文中可以清楚地看出,它们不应该由用户检查

    也许对你来说,我可能会疯狂地点击它,但我就是那种用户;)

    好的,因此只需支付一点UIManager 的默认值,就可以更好地控制某些元素的呈现方式,例如...

    UIManager.put("RadioButton.disabledText", Color.BLUE);
    JRadioButton rb = new JRadioButton("Test");
    rb.setOpaque(true);
    rb.setBackground(Color.RED);
    rb.setForeground(Color.BLUE);
    rb.setEnabled(false);
    
    add(rb);
    
    UIManager.put("CheckBox.disabledText", Color.RED);
    JCheckBox cb = new JCheckBox("Test");
    cb.setOpaque(true);
    cb.setBackground(Color.BLUE);
    cb.setForeground(Color.RED);
    cb.setEnabled(false);
    add(cb);
    

    现在,这只是一个快速破解。

    对我来说,我可能会考虑做一些不同的事情来突出正确答案,可能会淡化或删除其他问题或使用LineBorder 突出正确答案或使用JLabel 和漂亮的大绿色勾号或红十字,就像我脑海中的一些简单想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多