在JButton之间共享状态

时间:2010-02-02 19:37:57

标签: java swing jbutton

我想创建两个或多个共享状态的JButton,即当鼠标按钮被按下JButton时,两者都呈现为郁闷(也称为“武装”),或者如果它们是复选框,同时选中/取消选中等等。

对于用户来说,它必须看起来好像两个按钮都是相同的按钮,出现在层次结构中的多个位置(实际上Swing不允许这样做。)

我可以通过创建单个ButtonModel并为两个按钮分配相同的模型来获得一半。这会同步其武装/已检查/选定状态等。

然而,按钮之间共享的一个显着效果是焦点 - 单击一个按钮使该按钮成为焦点(由按钮内的矩形表示)并将其从另一个按钮中移除按钮。当 按钮确实有焦点时,我想将两个按钮渲染为好像它们一样聚焦。

有干净的方法吗?

理想情况下,我希望它独立于所选择的外观。

修改:我发现了共享ButtonModel的另一个问题。当其中一个按钮失去焦点时,它会将模型的armedpressed属性设置为false。在处理mousePressed之后发生这种情况,因此如果您在第一个按钮具有焦点时按下第二个按钮,则在您再次按下它之前它不会进入按下状态。

3 个答案:

答案 0 :(得分:3)

通过对两个按钮使用相同的ButtonModel,您做了一个非常好的举动。

现在您的焦点问题。答案是否定的。没有L&F不可知的方式。 您必须覆盖BasicButtonUI(或您正在使用的ButtonUI)并覆盖焦点绘制逻辑。

答案 1 :(得分:3)

这就是我的所作所为:

  • 使用新课程JButton
  • 扩展SharedFocusButton
  • SharedFocusButton会覆盖hasFocusgetModelpaintBorder
  • JButton.paintBorder(Graphics)ButtonUI.update(Component, Graphics)正在运行时,暂时更改hasFocus的行为,以便在组中的任何按钮具有焦点时返回true。同时暂时更改getModel的行为以返回代理ButtonModel(有时会返回共享ButtonModel
  • 代理ButtonModel的行为与默认的共享ButtonModel相同,只是它拒绝将armedpressed属性'值更改为false,同时处理focusLost事件。
  • 处理focusGainedfocusLost,强制组中的所有按钮自行重绘(这不会自动发生,因为每个按钮都有自己的UI处理焦点事件。)

剩余问题:
应该修改焦点遍历,以便 Tab 键永远不会将焦点从一个按钮转移到同一组中的另一个按钮。

答案 2 :(得分:1)

我假设你已经整理了文字,听众等。

转到BasicButtonUI的paint方法,我们可以看到它在进行某些绘制之前实际检查按钮是否具有焦点。因此,除非您可以同时拥有两个聚焦组件,否则我能想到的唯一方法是使用其他按钮的UI进行绘制。

两个按钮都需要是FocusButton,并且需要相互调用setButton。除了其他方面,我没有费心去添加任何空检查。

public class FocusButton extends JButton {
    private JButton btn;

    public FocusButton() {
        addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
                // Other button seems to repaint when focus is gained anyway
            }

            public void focusLost(FocusEvent e) {
                btn.repaint();
            }
        });
    }

    public void setButton(JButton btn) {
        this.btn = btn;
    }

    public void paint(Graphics g) {
        if (!btn.hasFocus()) {
            super.paint(g);
        } else {
            btn.paint(g);
        }
    }
}

编辑:如果您的按钮尺寸不同,这种方法效果不佳,如果它们应该有不同的文字,显然根本不起作用。