如何动态地 get/set JRadionButtonMenuItem?

How to get/set JRadionButtonMenuItem dynamically?

此示例的单选按钮位于子菜单上,如此处所示。

我想做的是,只要按下“更改单选按钮”按钮,它就会更改菜单上 select 编辑的按钮。这意味着它必须首先检索当前设置的那个,然后 select 另一个。

对于这个简单的示例,可以将单选按钮设为实例变量以使事情变得简单,但是图像 JMenu 和相关联的子菜单和单选按钮的生成是 class程序。直接访问不是那么直接。

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

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

public class RadioButtonsOnMenu 
{
    public static void main(final String args[]) 
    {
        JFrame frame = new JFrame("MenuSample Example");
        JButton jButton = new JButton("Change Radio Button");
        jButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent arg0) {
                System.out.println("Changing Radion Button");
                //How to change the JButton on the menu?
                //frame.getMenuBar().......
            }
        });

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel jPanel = new JPanel();
        jPanel.add(jButton);
        
        frame.add(jPanel);
        frame.setJMenuBar(buildMenu());
        frame.setSize(350, 250);
        frame.setVisible(true);
    }
    
    public static JMenuBar buildMenu()
    {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic(KeyEvent.VK_F);
        menuBar.add(fileMenu);

        JMenuItem newMenuItem = new JMenuItem("New", KeyEvent.VK_N);
        fileMenu.add(newMenuItem);

        JMenu findOptionsMenu = new JMenu("Options");
        findOptionsMenu.setMnemonic(KeyEvent.VK_O);
        fileMenu.add(findOptionsMenu);

        ButtonGroup directionGroup = new ButtonGroup();
        
        JRadioButtonMenuItem forwardMenuItem = new JRadioButtonMenuItem("Forward", true);
        forwardMenuItem.setMnemonic(KeyEvent.VK_F);
        findOptionsMenu.add(forwardMenuItem);
        directionGroup.add(forwardMenuItem);

        JRadioButtonMenuItem backwardMenuItem = new JRadioButtonMenuItem("Backward");
        backwardMenuItem.setMnemonic(KeyEvent.VK_B);
        findOptionsMenu.add(backwardMenuItem);
        directionGroup.add(backwardMenuItem);
        
        return menuBar;
    }
}

不清楚如何最好地访问 JButton 操作中的子菜单和关联的单选按钮设置。

        jButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent arg0) {
                System.out.println("Changing Radion Button");
                //How to change the JButton on the menu?
                //frame.getMenuBar().......
            }
        });

我可能会从框架中获取菜单栏并深入研究代码,如果菜单栏有许多项目、子项目甚至多个单选按钮组,代码会变得混乱。

是否有更直接的方法来找出菜单上的哪些单选按钮 selected 以及更直接的方法来更改它们的值?

您可以做的是将状态保存为布尔值。您可以向单选按钮添加侦听器,并在每次选择其中一个按钮时更改布尔值

boolean isForward = true;

所以当更改为向后时,您将值设置为 false。这样你就不需要每次都获取单选按钮的状态。 在您的按钮动作监听器中,您可以执行以下操作:

jButton.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent arg0) {
        System.out.println("Changing Radion Button");

            forwardRadioButton.setState(!isForward);
            backwardRadioButton.setState(isForward);
            iSForward = !isForward;
     }
});

“诀窍”是创建一个应用程序模型来保存菜单单选按钮的值。

这是我创建的 GUI。

我通过调用 SwingUtilities invokeLater 方法启动了 Swing 应用程序。此方法确保 Swing 组件在 Event Dispatch Thread.

上创建和执行

我创建了一个 JFrame 和一个 JButton JPanel。我分开创建了 JFrameJPanel.

我创建了一个应用程序模型 class 来保存一个布尔值,该布尔值确定是选择前进还是后退。 JButton ActionListener 切换布尔值的状态。 updateRadioButtonMenu 方法更新单选按钮菜单项的选定状态。

这是完整的可运行代码。

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

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.SwingUtilities;

public class RadioButtonsOnMenu implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new RadioButtonsOnMenu());
    }
    
    private ApplicationModel model;
    
    private JRadioButtonMenuItem backwardMenuItem;
    private JRadioButtonMenuItem forwardMenuItem;
    
    public RadioButtonsOnMenu() {
        this.model = new ApplicationModel();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("MenuSample Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenuBar());

        frame.add(createButtonPanel());
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic(KeyEvent.VK_F);
        menuBar.add(fileMenu);

        JMenuItem newMenuItem = new JMenuItem("New", KeyEvent.VK_N);
        fileMenu.add(newMenuItem);

        JMenu findOptionsMenu = new JMenu("Options");
        findOptionsMenu.setMnemonic(KeyEvent.VK_O);
        fileMenu.add(findOptionsMenu);

        ButtonGroup directionGroup = new ButtonGroup();

        forwardMenuItem = new JRadioButtonMenuItem("Forward", model.isForward());
        forwardMenuItem.setMnemonic(KeyEvent.VK_F);
        findOptionsMenu.add(forwardMenuItem);
        directionGroup.add(forwardMenuItem);

        backwardMenuItem = new JRadioButtonMenuItem("Backward", !model.isForward());
        backwardMenuItem.setMnemonic(KeyEvent.VK_B);
        findOptionsMenu.add(backwardMenuItem);
        directionGroup.add(backwardMenuItem);

        return menuBar;
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));
        
        JButton button = new JButton("Change Radio Button");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                model.setForward(!model.isForward());
                updateRadioButtonMenu();
            }
        });
        panel.add(button);
        
        return panel;
    }
    
    public void updateRadioButtonMenu() {
        forwardMenuItem.setSelected(model.isForward());
        backwardMenuItem.setSelected(!model.isForward());
    }
    
    public class ApplicationModel {
        
        private boolean isForward;
        
        public ApplicationModel() {
            this.isForward = true;
        }

        public boolean isForward() {
            return isForward;
        }

        public void setForward(boolean isForward) {
            this.isForward = isForward;
        }
        
    }

}

我会说你需要做这两件事:

由于您似乎有很多物品,所以最好将它们存放在其他地方

1 创建一个 class 来存储所有项目,然后只传递 class

public class myItemHolder{
    //declare all the items here instead of at the main
    JButton jButton = new JButton("Change Radio Button");
    ButtonGroup directionGroup = new ButtonGroup();
    JRadioButtonMenuItem forwardMenuItem = new JRadioButtonMenuItem("Forward", true);
    JRadioButtonMenuItem backwardMenuItem = new JRadioButtonMenuItem("Backward");
    
    myListener(myItemHolder items){
        directionGroup.add(forwardMenuItem);
    }
    public ButtonGroup getButtons() {
        return directionGroup;
    }
    public JButton getClick() {
        return jButton;
    }
}

2 创建您自己的动作侦听器 class 像这样

public class myListener implements ActionListener{
    myItemHolders items;
    myListener(myItemHolder items){
        this.items=items; 
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //get the radiobutton like so and do what you want with it
        items.getButtons()
    }
}

现在您只需要在主要部分执行此操作:

public class RadioButtonsOnMenu 
{
    public static void main(final String args[]) 
    {
        myItemHolder items = new myItemHolder();
        items.getClick.addActionListener(new myListener(items));
    }
}

在那里您可以轻松访问所有内容:)
这完全取决于你在哪里声明你的东西。
或者,如果您只想发送 ButtonGroup,您可以通过稍微更改结构来实现,这样 actionlistener 只请求 ButtonGroup 并给它 items.getButtons() 而不是 items.

这是使用枚举状态跟踪的另一种可行方法。我使用 Enum 和 Map 来跟踪应该激活的单选按钮。这让它可以根据需要在同一个 JMenu 中为关联的单选按钮项目缩放。

收音机菜单

package tools;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;

import javax.swing.JMenu;
import javax.swing.JRadioButtonMenuItem;

public class RadioMenu<E extends Enum<E>> extends JMenu {
  private static final long serialVersionUID = 1L;
  
  private E currentState;
  private JRadioButtonMenuItem selectedRadioButton;
  
  private HashMap<E, JRadioButtonMenuItem> stateMap;
  
  public RadioMenu() {
    stateMap = new HashMap<E, JRadioButtonMenuItem>();
  }
  
  public RadioMenu(String name) {
    super(name);
    stateMap = new HashMap<E, JRadioButtonMenuItem>();
  }
  
  public void addRadioButton(E associatedState, JRadioButtonMenuItem radioButton) {
    //Set default to first added button
    if(stateMap.isEmpty()) {
      currentState = associatedState;
      radioButton.setSelected(true);
      selectedRadioButton = radioButton;
    }
    
    add(radioButton);
    stateMap.put(associatedState, radioButton);
    radioButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        setState(associatedState);
      }
    });
  }
  
  public void generateButtonsFromEnum(Class<E> enumType) {
    for(E enumValue : enumType.getEnumConstants()) {
      addRadioButton(enumValue, new JRadioButtonMenuItem(enumValue.toString()));
    }
  }
  
  public E getState() {
    return currentState;
  }
  
  public void setState(E newState) {
    currentState = newState;
    selectedRadioButton.setSelected(false);
    
    selectedRadioButton = stateMap.get(newState);
    selectedRadioButton.setSelected(true);
  }
}

RadioMenuTest

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import tools.RadioMenu;

public class RadioMenuTest implements Runnable {

  public enum RadioOptions {
    Forward, Backward, Left, Right
  }
  
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new RadioMenuTest());
  }
  
  private RadioMenu<RadioOptions> optionsMenu;
  
  @Override
  public void run() {
    JFrame frame = new JFrame("RadioMenu Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    frame.setJMenuBar(createMenuBar());
    frame.getContentPane().add(createButtonPanel());
    
    frame.pack();
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
  }

  private JMenuBar createMenuBar() {
    JMenuBar menuBar = new JMenuBar();
    JMenu fileMenu = new JMenu("File");
    menuBar.add(fileMenu);
    
    optionsMenu = new RadioMenu<RadioOptions>("Options");
    optionsMenu.generateButtonsFromEnum(RadioOptions.class);
    
    fileMenu.add(optionsMenu);
    
    return menuBar;
  }
  
  private JPanel createButtonPanel() {
    JPanel panel = new JPanel(new FlowLayout());
    
    JButton setBackwardButton = new JButton("Set To Backward");
    setBackwardButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        optionsMenu.setState(RadioOptions.Backward);
      }
    });
    panel.add(setBackwardButton);
    
    JButton setRightButton = new JButton("Set To Right");
    setRightButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        optionsMenu.setState(RadioOptions.Right);
      }
    });
    panel.add(setRightButton);
    
    return panel;
  }
}