Как заставить JMenu иметь поведение кнопки в JMenuBar
Вопрос
Я пытался заставить JMenu вести себя как JButton, но у меня возникли некоторые проблемы, и, надеюсь, кто-нибудь здесь сможет помочь!
Я добавил MenuListener к элементу JMenu с этим, но я не могу отключить всплывающее меню / фокус, чтобы я мог правильно щелкнуть JMenu несколько раз, чтобы запустить эту функцию, и я надеялся, что кто-нибудь сможет сказать мне, что я делаю неправильно.Спасибо.
public void menuSelected(MenuEvent e)
{
... // do stuff here code
JMenu source = (JMenu)e.getSource();
source.setSelected(false);
source.setPopupMenuVisible(false);
}
Решение
Не совсем уверен, о чем вы просите...
Но JMenuBar
наследуется от Container
- если вы предпочитаете добавить JButton
к нему, чем к JMenu
вы можете просто позвонить -
JMenuBar menuBar = ....
JButton myButton = ....
menuBar.add(myButton);
Другие советы
Этот пример кода выполняется в 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();
}
}
Я знаю, что это старая тема, но я думаю, что у меня может быть решение.Я наткнулся на эту проблему в одном из своих приложений и нашел обходной путь.Попробуйте использовать JMenuItem вместо JMenu.Он будет иметь те же L & F, что и JMenu, когда вы присоедините его к JMenuBar.Единственное, что вам нужно сделать, это установить размер вашей новой "кнопки", поскольку ваш менеджер компоновки (даже если вы ее не установили) изменит размер этого компонента на основе своих собственных правил:
http://www.javaworld.com/javaworld/jw-09-2000/jw-0922-javatraps.html
Способ сделать это находится по этой ссылке (если вам неудобно переходить по ссылке, найдите в Google "setsize не работает" - это будет в первой десятке результатов).Если вы неправильно настроите размер, ваша новая "кнопка" заполнит оставшееся пространство вашей 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());
}
Надеюсь, это поможет!
Очень трудно определить, что вы пытаетесь здесь сделать.Но я не думаю, что вы правильно используете JMenu.
JMenu - это объект, представляющий меню.Он отделен от строки меню (JMenuBar) и от пункта меню (JMenuItem).JMenuBar обычно содержит несколько JMenus (File, Edit и т.д.), Которые, в свою очередь, содержат несколько JMenuItems (New, Open, Close).JMenuItems - это то, на что нажимается и что "действует как кнопка" в меню.
Чтобы заставить пункт меню действовать как кнопка, просто добавьте его в меню.Например:
JMenu fileMenu = new JMenu("File");
JMenuItem newChoice = new JMenuItem("New");
newChoice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
newHasBeenSelected();
}
});
fileMenu.add(newChoice);
Если вы пытаетесь создать всплывающее меню, вам нужно использовать JPopupMenu вместо JMenu, и вам не нужна строка JMenuBar.Вот учебные пособия по Java по меню: http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html
И вот документы Java для JМенуБар, JMenu ( Меню ), JPopupMenu, и JMenuItem ( Меню ).
Если вы отредактируете свой вопрос и дадите более подробное объяснение того, что вы делаете, я, возможно, смогу оказать более конкретную помощь.
Хорошо, я решил исследовать это немного подробнее, и следующим является reslut, который, похоже, действует точно так же, как JButton, но выглядит как jmenu в jmenubar.Код ниже.(обратите внимание, что простое добавление ActionListener в JMenu не сработало правильно, что является причиной mouselistener.Вы добавляете ActionListener в menubutton точно так же, как обычную кнопку, и до тех пор, пока вы не добавите никаких элементов menuitems в menubutton (что технически вы могли бы), он будет отображаться как JMenu на панели JMenuBar, но вести себя как кнопка.
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;
}
}
}