【问题标题】:Coordinating two `ButtonGroup`协调两个`ButtonGroup`
【发布时间】:2012-03-15 00:02:11
【问题描述】:

菜单中有一组 3 个JRadioButtonMenuItem,工具栏中有 3 个JToggleButton。每一个都绑定了3个Action,这样当我禁用一个动作时,对应的item和button都会被禁用。

当我点击一个菜单项时,我希望相应的工具栏按钮也会被选中,但似乎“未点击”组有自己奇怪的方式来响应这些事件(使用我没有的模式尝试识别)。

这里是菜单组代码(简化):

ButtonGroup menuGrp = new ButtonGroup();

JRadioButtonMenuItem itemA = new JRadioButtonMenuItem(actionA);
JRadioButtonMenuItem itemB = new JRadioButtonMenuItem(actionB);
JRadioButtonMenuItem itemC = new JRadioButtonMenuItem(actionC);

menuGrp.add(itemA);
menuGrp.add(itemB);
menuGrp.add(itemC);

itemA.setSelected(true);

这里工具栏组代码:

ButtonGroup toolbarGrp = new ButtonGroup();

JToggleButton buttonA = new JToggleButton(actionA);
JToggleButton buttonB = new JToggleButton(actionB);
JToggleButton buttonC = new JToggleButton(actionC);

toolbarGrp.add(buttonA);
toolbarGrp.add(buttonB);
toolbarGrp.add(buttonB);

buttonA.setSelected(true);

【问题讨论】:

  • 您将 buttonB 添加到 toolbarGrp 两次。这只是一个错字还是你在代码中有它?

标签: java swing buttongroup


【解决方案1】:

我不知道你到底是怎么做的,但这段代码对我有用:

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToggleButton;


public class Button
{
    public static void main(String[] args){
        JFrame frame = new JFrame();
        JMenuBar bar = new JMenuBar();
        JMenu menu = new JMenu("Foo");

        ButtonGroup menuGrp = new ButtonGroup();
        JRadioButtonMenuItem itemA = new JRadioButtonMenuItem();
        JRadioButtonMenuItem itemB = new JRadioButtonMenuItem();
        JRadioButtonMenuItem itemC = new JRadioButtonMenuItem();
        menuGrp.add(itemA);
        menuGrp.add(itemB);
        menuGrp.add(itemC);
        menu.add(itemA);
        menu.add(itemB);
        menu.add(itemC);
        itemA.setSelected(true);

        bar.add(menu);
        frame.setJMenuBar(bar);

        JPanel content = new JPanel();

        ButtonGroup toolbarGrp = new ButtonGroup();
        JToggleButton buttonA = new JToggleButton();
        JToggleButton buttonB = new JToggleButton();
        JToggleButton buttonC = new JToggleButton();
        toolbarGrp.add(buttonA);
        toolbarGrp.add(buttonB);
        toolbarGrp.add(buttonC);
        buttonA.setSelected(true);

        content.add(buttonA);
        content.add(buttonB);
        content.add(buttonC);

        itemA.setAction(new MyAction(buttonA));
        itemB.setAction(new MyAction(buttonB));
        itemC.setAction(new MyAction(buttonC));
        buttonA.setAction(new MyAction(itemA));
        buttonB.setAction(new MyAction(itemB));
        buttonC.setAction(new MyAction(itemC));
        frame.setContentPane(content);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }

    static class MyAction extends AbstractAction
    {
        AbstractButton button;

        public MyAction(AbstractButton button){
            this.button = button;
        }

        @Override public void actionPerformed(ActionEvent e){
            button.setSelected(true);
        }   


    }
}

【讨论】:

  • 实际上,我正在为每个对应的对(itemA buttonA -> actionA,...)共享动作,根据Javadocs,他们应该共享动作的状态,而无需手动选择。我试图修改您的代码以反映我的代码:启用状态确实是共享的(就像在我的代码中一样),但现在一组只是忽略了另一组的选择。而且我不明白为什么在我的代码中最后这件事有效(尽管部分有效)。
  • 不管怎样,你让我走上了正确的道路。我最终通过在每个actionPerformed() 中调用putValue(Action.SELECTED_KEY, true) 来解决,这就像手动选择操作而不是组件一样。谢谢。
【解决方案2】:

您可以通过在它们之间共享按钮模型来链接任意两个(或更多)按钮的状态,在这种情况下:

itemA.setModel(buttonA.getModel());
itemB.setModel(buttonB.getModel());
itemC.setModel(buttonC.getModel());

这样您就可以避免拨打putValue(Action.SELECTED_KEY, true)。不确定这是否真的是一种改进,但我确实更喜欢它。

【讨论】:

    【解决方案3】:

    记录在案(多年后),这是由于 Java 6 中所做的更改。您可以查看 JDK-6397556 进行一些讨论,但简短的版本是因为完全绑定 stateful 按钮到 Actions 需要按钮将该状态(选择与未选择)推回 Action,他们不想破坏未预料到的现有程序。

    因此,如果您要从动作构造一个切换按钮,并且希望按钮的初始选定状态跟随动作的选定状态,则必须通过将Action.SELECTED_KEY 设置为非空来选择加入在创建按钮之前的布尔值:

    Action action = .....;
    action.putValue (Action.SELECTED_KEY, Boolean.TRUE);
    JCheckBox checkbox = new JCheckBox(action);
    

    显然,传递Boolean.FALSE 以将它们完全绑定在一起,初始状态为“未选中”。 (如果您的代码已经在其他布尔变量中确定了初始选择状态,那么只需执行 Boolean.valueOf(initiallySelectedOrNot) 即可,或者您可以依赖自动装箱到 DTRT。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-10
      相关资源
      最近更新 更多