【问题标题】:Adding a checkbox group to a java menu将复选框组添加到 java 菜单
【发布时间】:2015-05-04 09:43:12
【问题描述】:

我试图在我的菜单中添加一个复选框组,但不断收到“找不到符号”错误。

    MenuBar mb = new MenuBar();
    Menu file = new Menu("File");
    Menu colorM = new Menu("Color");
    MenuItem quitM = new MenuItem("Quit", new MenuShortcut(KeyEvent.VK_Q));
    CheckboxGroup cbg = new CheckboxGroup();
    Checkbox cb1 = new Checkbox("Black",cbg,true);
    Checkbox cb2 = new Checkbox("Red",cbg,false);
    Checkbox cb3 = new Checkbox("Blue",cbg,false);
    Checkbox cb4 = new Checkbox("Green",cbg,false);

然后在我的初始化中我有

    chatF.setMenuBar(mb);
    mb.add(file);
    mb.add(colorM);
    file.add(quitM);
    colorM.add(cbg);

我尝试添加一个 MenuItem 并将 cbg 放在那里,但同样的问题

【问题讨论】:

  • 如果我注释掉 colorM.add(cbg) 行,一切都会编译并完美运行。目前我在程序中的唯一代码是设置 UI 以及添加和删除侦听器,所以我认为不需要设置按钮、标签等的代码。

标签: java checkbox awt jmenu


【解决方案1】:

CheckboxGroup 不是Component(或者,更具体地说,MenuItem),因此您不能将其添加到菜单中。相反,您可以创建一个CheckboxMenuItem,但我认为CheckboxGroup 仅适用于Checkbox 的实例,因此您必须编写自己的代码来强制执行单选。

如果 Swing 是一个选项,您可以改用 JRadioButtonMenuItemButtonGroup

package com.example.checkboxmenu;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;

public class CheckboxMenu extends JFrame {

    public CheckboxMenu() {
        JMenuBar mb = new JMenuBar();
        JMenu file = new JMenu("File"); //$NON-NLS-1$
        JMenu colorM = new JMenu("Color");
        JMenuItem quitM = new JMenuItem("Quit", KeyEvent.VK_Q);

        JRadioButtonMenuItem cb1 = new JRadioButtonMenuItem("Black", true);
        JRadioButtonMenuItem cb2 = new JRadioButtonMenuItem("Red", true);
        JRadioButtonMenuItem cb3 = new JRadioButtonMenuItem("Blue", true);
        JRadioButtonMenuItem cb4 = new JRadioButtonMenuItem("Green", true);

        ButtonGroup group = new ButtonGroup();
        group.add(cb1);
        group.add(cb2);
        group.add(cb3);
        group.add(cb4);

        setJMenuBar(mb);
        mb.add(file);
        mb.add(colorM);
        file.add(quitM);
        colorM.add(cb1);
        colorM.add(cb2);
        colorM.add(cb3);
        colorM.add(cb4);

        quitM.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(400,300);
        setVisible(true);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        new CheckboxMenu();
    }

}

【讨论】:

  • 不幸的是,在这种情况下我不能使用摇摆。当我声明复选框时,我将它们添加到同一行中的组中。我不确定哪种类型的菜单会接受复选框组
  • 我认为您必须自己为 CheckboxMenuItem 实现 CheckboxGroup 的功能。它应该相当简单,但是您必须使用侦听器来更新其他复选框的状态。
【解决方案2】:

您不能将CheckboxGroup 添加到菜单...您只能添加MenuItem 实例。可以加个CheckboxMenuItem,不过这个也看不懂CheckboxGroup

因此您需要将CheckBoxs 更改为CheckboxMenuItems,将它们单独添加到菜单中,滚动您自己的CheckboxMenuItemGroup 类并使用它将CheckboxMenuItems 绑定在一起。

类似下面的东西应该可以工作:

public class CheckboxMenuItemGroup implements ItemListener {

    private Set<CheckboxMenuItem>   items = new HashSet<CheckboxMenuItem>();

    public void add(CheckboxMenuItem cbmi) {
        cbmi.addItemListener(this);
        cbmi.setState(false);
        items.add(cbmi);
    }

    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            String itemAffected = (String) e.getItem();
            for (CheckboxMenuItem item : items) {
                // Use this line to allow user to toggle the selected item off
                if (!item.getLabel().equals(itemAffected)) item.setState(false);
                // Use this line to force one of the items to always be selected
                // item.setState(item.getLabel().equals(itemAffected));
            }
        }
    }

    public void selectItem(CheckboxMenuItem itemToSelect) {
        for (CheckboxMenuItem item : items) {
            item.setState(item == itemToSelect);
        }
    }

    public CheckboxMenuItem getSelectedItem() {
        for (CheckboxMenuItem item : items) {
            if (item.getState()) return item;
        }
        return null;
    }
}

这应该有效,因为当代码调用item.setState() 时不会调用ItemListeners,只有当用户单击菜单中的项目时。只需确保您只使用 CheckboxMenuItemGroup.selectItem() 调用设置项目的状态,否则您最终可能会选择多个项目。

那么你只需要像这样构建你的菜单:

public static void main(String[] args) {

    final Frame f = new Frame("Test CheckboxMenuItemGroup");
    MenuBar mb = new MenuBar();
    Menu menu = new Menu("Menu");
    CheckboxMenuItem cb1 = new CheckboxMenuItem("Black");
    CheckboxMenuItem cb2 = new CheckboxMenuItem("Red");
    CheckboxMenuItem cb3 = new CheckboxMenuItem("Blue");
    CheckboxMenuItem cb4 = new CheckboxMenuItem("Green");

    CheckboxMenuItemGroup mig = new CheckboxMenuItemGroup();
    mig.add(cb1);
    mig.add(cb2);
    mig.add(cb3);
    mig.add(cb4);
    mig.selectItem(cb1);

    menu.add(cb1);
    menu.add(cb2);
    menu.add(cb3);
    menu.add(cb4);

    f.setMenuBar(mb);

    f.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    });
    f.setSize(300, 200);
    f.setVisible(true);
}

【讨论】:

  • 您能否为我解释一下,或者您有其他网站可以参考吗?
  • 首先,您只能将MenuItems 添加到Menu 或MenuItem 的子类中,例如MenuPopupMenu(在这种情况下没有意义)和@ 987654338@ 这正是您想要的。但您也希望您的CheckboxMenuItems 具有排他性。您无法将它们添加到CheckboxGroup,因此您必须创建一个与CheckboxGroup 类似但针对CheckboxMenuItems 的类,并将您的四个CheckboxMenuItems 附加到它。最后,您需要将您的CheckboxMenuItems 单独添加到您的Menu
  • 我猜你目前不使用 IDE。如果您这样做是可行的,我强烈建议您安装 NetBeans 或 Eclipse 之类的,因为它可以在您尝试使用无效参数调用方法时警告您并建议适当的替代方案,甚至在您尝试编译之前代码。
  • @JulianWright 我正在尝试将您的示例用于使用 Java 7 的 OSX 上的 Dock 菜单,因为这只适用于本机 awt 菜单。使用 selectItem() 可以很好地设置默认选定项目,但 itemStateChanged() 不起作用,因为没有任何项目等于从 ItemEvent 返回的项目,尽管查看它们应该执行的代码。你的例子真的适合你吗?
  • 我没有尝试过,但你是对的 - 看起来 ItemEvent.getItem() 并没有按照盒子上说的那样做。我已经用我实际编译和测试过的答案更新了答案。
【解决方案3】:

使用 swing 代替 awt。

JMenuBar menuBar = new JMenuBar();
JMenu color = new JMenu("Color");

JCheckBoxMenuItem cb1 = new JCheckBoxMenuItem("Black");
JCheckBoxMenuItem cb2 = new JCheckBoxMenuItem("Red");
JCheckBoxMenuItem cb3 = new JCheckBoxMenuItem("Blue");
JCheckBoxMenuItem cb4 = new JCheckBoxMenuItem("Green");

ButtonGroup group = new ButtonGroup();
group.add(cb1);
group.add(cb2);
group.add(cb3);
group.add(cb4);

menuBar.add(cb1);
menuBar.add(cb2);
menuBar.add(cb3);
menuBar.add(cb4);

setJMenuBar(menuBar); // Set the JMenuBar of the JFrame

您可以将任何AbstractButton 添加到ButtonGroup

【讨论】:

    【解决方案4】:

    在 OSX Java 7 (1.7.0_40) 上,Julian 的回答不太有效,因为 ItemEvent 返回的对象实际上是一个字符串而不是 CheckBoxItem,这听起来像是 OSX 中的一个错误,但通过修改 itemStateChanged 方法使其工作

    import java.awt.*;
    import java.awt.event.ItemEvent;
    import java.awt.event.ItemListener;
    import java.util.HashSet;
    import java.util.Set;
    
    public class CheckboxMenuItemGroup implements ItemListener
    {
    
        private Set<CheckboxMenuItem> items = new HashSet<CheckboxMenuItem>();
    
        public void add(CheckboxMenuItem cbmi) {
            cbmi.addItemListener(this);
            cbmi.setState(false);
            items.add(cbmi);
        }
    
        @Override
        public void itemStateChanged(ItemEvent e) {
            if (e.getStateChange() == ItemEvent.SELECTED) {
    
                String itemAffected = (String)e.getItem();
                for (CheckboxMenuItem item : items) {
                    if (item.getLabel() != itemAffected) item.setState(false);
                }
            }
        }
    
        public void selectItem(CheckboxMenuItem itemToSelect) {
            for (CheckboxMenuItem item : items) {
                item.setState(item == itemToSelect);
            }
        }
    
        public CheckboxMenuItem getSelectedItem() {
            for (CheckboxMenuItem item : items) {
                if (item.getState()) return item;
            }
            return null;
        }
    }
    

    【讨论】:

    • 非常正确 - 我自己没有编译它,现在我已经对其进行了测试,它在 Linux 中的 JDK 1.7.0_45 下的行为方式似乎相同。我更新了我的代码以反映这一点,并将示例充实为我实际编译和测试的内容!您可能希望在 itemStateChanged() 代码中使用 equals() 进行字符串比较,而不是 !=。
    猜你喜欢
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 2012-01-16
    • 1970-01-01
    • 2017-02-07
    相关资源
    最近更新 更多