4

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

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

通过创建一个ButtonModel按钮并将相同的模型分配给两个按钮,我可以达到一半。这会同步他们的武装/检查/选择状态等。

但是,以这种方式在按钮之间没有共享的一个显着效果是焦点 - 单击一个按钮使该按钮获得焦点(由按钮内的矩形表示)并将其从另一个按钮中移除。我想渲染两个按钮,就好像它们在任何一个按钮真正具有焦点时都具有焦点一样。

有没有一种干净的方法可以做到这一点?

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

编辑:我发现共享ButtonModel. 当其中一个按钮失去焦点时,它会将模型的armedpressed属性设置为false。这发生处理之后mousePressed,因此如果您在第一个按钮获得焦点时按下第二个按钮,它不会进入按下状态,直到您再次按下它。

4

3 回答 3

3

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

现在解决您关于焦点的问题。答案是否定的。没有L&F不可知论的方法。您必须覆盖BasicButtonUI(或ButtonUI您正在使用的任何一个)并覆盖焦点绘制逻辑。

于 2010-02-03T04:01:09.970 回答
3

这是我所做的:

  • 扩展JButton一个新的类SharedFocusButton
  • SharedFocusButton覆盖hasFocus,getModelpaintBorder.
  • 当要么JButton.paintBorder(Graphics)ButtonUI.update(Component, Graphics)正在运行时,临时更改 的行为,hasFocus以便true在组中的任何按钮具有焦点时返回。还临时更改getModel返回代理的行为ButtonModel(在其他时候它返回 shared ButtonModel
  • 代理的ButtonModel行为类似于默认值 shared ,只是它在处理事件ButtonModel时拒绝更改armedorpressed属性的值。falsefocusLost
  • 处理focusGainedfocusLost,强制组中的所有按钮重绘自己(这不会自动发生,因为每个按钮都有自己的 UI 处理焦点事件。)

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

于 2010-02-03T12:48:09.400 回答
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);
        }
    }
}

编辑:如果您的按钮大小不同,这不会很好用,如果它们应该有不同的文本,显然根本不起作用。

于 2010-02-03T03:58:03.660 回答