问题描述
此示例的单选按钮位于子菜单上,如下所示。
我想要做的是,无论何时按下“更改单选按钮”按钮,它都会更改在菜单上选择的按钮。这意味着它必须首先检索当前设置的然后选择另一个。
对于这个简单的示例,可以将单选按钮设为实例变量以使事情变得简单,但生成 JMenu 和相关子菜单和单选按钮的图像是程序内部的某个类。直接访问不是那么直接。
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().......
}
});
我可能可以从 Frame 中获取菜单栏并向下钻取数字,如果菜单栏中有大量项目、子项目甚至多个单选按钮组,代码可能会变得混乱。
是否有更直接的方法来找出菜单上的哪些单选按钮被选中以及更直接的方法来更改它们的值?
解决方法
您可以做的是将状态保存在布尔值中。您可以向单选按钮添加侦听器并在每次选择其中一个时更改布尔值
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 应用程序。此方法可确保在 Event Dispatch Thread 上创建和执行 Swing 组件。
我创建了一个 JFrame
和一个 JButton
JPanel
。我将 JFrame
和 JPanel
的创建分开。
我创建了一个应用程序模型类来保存一个布尔值,该布尔值决定是选择向前还是向后。 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));
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 创建一个类来存储所有项目,然后只传递类
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 像这样创建自己的动作监听器类
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()
}
}
现在你只需要在 main 中执行此操作:
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 中的关联单选按钮项缩放。
RadioMenu
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;
}
}