Java 如何使JMenu在JMenuBar中具有按钮行为
我试图让JMenu像JButton一样工作,但我遇到了一些问题,希望这里有人能帮上忙 我已经在JMenu项中添加了一个MenuListener,但我无法让弹出菜单/焦点离开,以使我能够正确地反复单击JMenu以触发此功能,我希望有人能告诉我我做错了什么。谢谢Java 如何使JMenu在JMenuBar中具有按钮行为,java,swing,jmenubar,jmenu,Java,Swing,Jmenubar,Jmenu,我试图让JMenu像JButton一样工作,但我遇到了一些问题,希望这里有人能帮上忙 我已经在JMenu项中添加了一个MenuListener,但我无法让弹出菜单/焦点离开,以使我能够正确地反复单击JMenu以触发此功能,我希望有人能告诉我我做错了什么。谢谢 public void menuSelected(MenuEvent e) { ... // do stuff here code JMenu source = (JMenu)
public void menuSelected(MenuEvent e)
{
... // do stuff here code
JMenu source = (JMenu)e.getSource();
source.setSelected(false);
source.setPopupMenuVisible(false);
}
这个代码示例在eclipse中运行,再次关心您是如何使用它的
public class MyMenuFrame extends JFrame {
public MyMenuFrame() throws HeadlessException {
super("My Frame");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(400, 300);
Container pane = this.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(new JLabel("Hi there"), BorderLayout.PAGE_START);
this.setVisible(true);
JMenuBar menubar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.addMenuListener(new MenuListener() {
@Override
public void menuSelected(MenuEvent e) {
System.out.println("a");
}
@Override
public void menuDeselected(MenuEvent e) {
System.out.println("a");
}
@Override
public void menuCanceled(MenuEvent e) {
System.out.println("a");
}
});
menubar.add(menu);
this.setJMenuBar(menubar );
}
public static void main(String[] args) {
new MyMenuFrame();
}
}
不完全确定你在问什么 但是
JMenuBar
继承自Container
——如果您更愿意向其添加JButton
,而不是JMenu
,则只需调用-
JMenuBar menuBar = ....
JButton myButton = ....
menuBar.add(myButton);
很难确定你想在这里做什么。但我认为您没有正确使用JMenu JMenu是表示菜单的对象。它与菜单栏(JMenuBar)和菜单项(JMenuItem)分开。JMenuBar通常包含多个JMenus(文件、编辑等),而这些JMenus又包含多个JMenuItems(新建、打开、关闭)。JMenuItems是单击的项,在菜单中“起到按钮的作用” 要使菜单项像按钮一样工作,只需将其添加到菜单中即可。例如:
JMenu fileMenu = new JMenu("File");
JMenuItem newChoice = new JMenuItem("New");
newChoice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
newHasBeenSelected();
}
});
fileMenu.add(newChoice);
如果您试图创建一个弹出菜单,那么您需要使用jpopmpmenu而不是JMenu,并且不需要JMenuBar。以下是菜单上的Java教程:
下面是、和的Java文档
如果您编辑您的问题并对您正在做的事情进行更详细的解释,我可能会提供更具体的帮助。我知道这是一个老话题,但我想我可能有一个解决方案。我在我的一个应用程序中偶然发现了这个问题,并找到了解决办法。尝试使用JMenuItem而不是JMenu。当您将其连接到JMenuBar时,它将具有与JMenu相同的L&F。您唯一需要做的就是设置新“按钮”的大小,因为布局管理器(即使尚未设置)将根据其自身的规则调整此组件的大小: 这样做的方法可以在这个链接下找到(如果你觉得不舒服点击这个链接,谷歌的“设置大小不起作用”-它将是前十名的结果)。如果没有正确设置大小,新的“按钮”将填满JMenuBar的剩余空间 请尝试以下代码:
menuItem.setMinimumSize(someMenu.getSize());
menuItem.setPreferredSize(someMenu.getSize());
menuItem.setMaximumSize(someMenu.getSize());
menuItem.setActionCommand("ActionText");
setActionCommand()方法将设置一个动作命令,这样当您单击新的“按钮”时,这将是动作事件参数传递给动作执行方法的动作命令,以便您可以轻松识别它:
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
希望这有帮助 好的,我决定进一步研究这个问题,下面是reslut,它看起来像JButton,但看起来像jmenubar上的jmenu。代码如下。(注意,仅仅将actionListener添加到JMenu无法正常工作,这就是mouselistener的原因。将actionListener添加到菜单按钮就像普通按钮一样,只要不向菜单按钮添加任何菜单项(技术上可以),它将在JMenuBar上显示为JMenu,但其行为就像按钮一样
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.lang.reflect.Method;
import java.util.EventListener;
import javax.swing.ImageIcon;
import javax.swing.JMenu;
public class MenuButton extends JMenu {
private boolean startedIn = false;
private ActionListener action;
public MenuButton(String title) {
super(title);
removeListeners(this);
this.addMouseListener(new MenuButtonListener());
}
public MenuButton(ImageIcon icon) {
super();
removeListeners(this);
this.addMouseListener(new MenuButtonListener());
this.setIcon(icon);
}
public void addActionListener(ActionListener a) {
action = a;
}
//we need to remove all the listeners already associated with a JMenu. If we do
//not do this, then it will not behave as expected because some mouseclicks are eaten
//by these listeners. There is no easy way to do that, the following method is a
//workaroundprovided in the java bug database.
static private void removeListeners(Component comp) {
Method[] methods = comp.getClass().getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
String name = method.getName();
if (name.startsWith("remove") && name.endsWith("Listener")) {
Class[] params = method.getParameterTypes();
if (params.length == 1) {
EventListener[] listeners = null;
try {
listeners = comp.getListeners(params[0]);
} catch (Exception e) {
// It is possible that someone could create a listener
// that doesn't extend from EventListener. If so, ignore
// it
System.out.println("Listener " + params[0]
+ " does not extend EventListener");
continue;
}
for (int j = 0; j < listeners.length; j++) {
try {
method.invoke(comp, new Object[] { listeners[j] });
// System.out.println("removed Listener " + name +
// " for comp " + comp + "\n");
} catch (Exception e) {
System.out
.println("Cannot invoke removeListener method "
+ e);
// Continue on. The reason for removing all
// listeners is to
// make sure that we don't have a listener holding
// on to something
// which will keep it from being garbage collected.
// We want to
// continue freeing listeners to make sure we can
// free as much
// memory has possible
}
}
} else {
// The only Listener method that I know of that has more
// than
// one argument is removePropertyChangeListener. If it is
// something other than that, flag it and move on.
if (!name.equals("removePropertyChangeListener"))
System.out.println(" Wrong number of Args " + name);
}
}
}
}
public class MenuButtonListener extends MouseAdapter {
boolean within = false;
boolean pressed = false;
public void mousePressed(MouseEvent e) {
MenuButton.this.setSelected(true);
pressed = true;
//System.out.println("pressed");
}
public void mouseReleased(MouseEvent e) {
//System.out.println("released");
MenuButton.this.setSelected(false);
if (action != null && within && pressed) {
action.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED, null));
MenuButton.this.setSelected(false);
}
pressed = false;
}
@Override
public void mouseEntered(MouseEvent e) {
within = true;
}
@Override
public void mouseExited(MouseEvent e) {
within = false;
}
}
}
导入java.awt.Component;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
导入java.lang.reflect.Method;
导入java.util.EventListener;
导入javax.swing.ImageIcon;
导入javax.swing.JMenu;
公共类菜单按钮扩展了JMenu{
private boolean startedIn=false;
私人行动听者行动;
公共菜单按钮(字符串标题){
超级(标题);
RemovelListeners(这个);
这个.addMouseListener(新的MenuButtonListener());
}
公共菜单按钮(图像图标){
超级();
RemovelListeners(这个);
这个.addMouseListener(新的MenuButtonListener());
这个.setIcon(图标);
}
public void addActionListener(ActionListener a){
行动=a;
}
//我们需要删除所有已经与JMenu关联的侦听器
//如果不这样做,那么它的行为就不会像预期的那样,因为会吃掉一些鼠标
//没有简单的方法可以做到这一点,下面的方法是
//java bug数据库中提供了解决方法。
静态私有void removeListeners(组件组件组件){
方法[]方法=comp.getClass().getMethods();
for(int i=0;i