如何在 Java Swing 工具栏中创建“下拉”菜单?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1900293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I create a "Drop-Down" menu in a Java Swing toolbar?
提问by Steve McLeod
I've created a drop-down menu on my Swing JToolBar. But it doesn't create behave the way I want. I'm aiming for it to work like Firefox's "Smart Bookmarks" button.
我在 Swing JToolBar 上创建了一个下拉菜单。但它不会按照我想要的方式创建行为。我的目标是让它像 Firefox 的“智能书签”按钮一样工作。
It disappears when the user selects a menu item: CORRECT!
当用户选择一个菜单项时它就会消失:正确!
It disappears when the user presses ESC: CORRECT!
当用户按下 ESC 时它消失:正确!
It disappears when the user clicks somewhere in the main frame outside of the menu: CORRECT!
当用户单击菜单外主框架中的某处时,它就会消失:正确!
But it doesn't disappear when the user clicks a second time on the button that shows the drop-down menu: INCORRECT... :-(
但是当用户第二次单击显示下拉菜单的按钮时它不会消失:不正确... :-(
My question is how can I add this behaviour, that it does disappear when the clicks on the button that shows the menu a second time.
我的问题是如何添加这种行为,当第二次单击显示菜单的按钮时它会消失。
Here's my current code, from Java 6 on the Mac:
这是我当前的代码,来自 Mac 上的 Java 6:
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
public class ScratchSpace {
public static void main(String[] arguments) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Toolbar with Popup Menu demo");
final JToolBar toolBar = new JToolBar();
toolBar.add(createMoreButton());
final JPanel panel = new JPanel(new BorderLayout());
panel.add(toolBar, BorderLayout.NORTH);
panel.setPreferredSize(new Dimension(600, 400));
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private static AbstractButton createMoreButton() {
final JToggleButton moreButton = new JToggleButton("More...");
moreButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
createAndShowMenu((JComponent) e.getSource(), moreButton);
}
}
});
moreButton.setFocusable(false);
moreButton.setHorizontalTextPosition(SwingConstants.LEADING);
return moreButton;
}
private static void createAndShowMenu(final JComponent component, final AbstractButton moreButton) {
JPopupMenu menu = new JPopupMenu();
menu.add(new JMenuItem("Black"));
menu.add(new JMenuItem("Red"));
menu.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
moreButton.setSelected(false);
}
public void popupMenuCanceled(PopupMenuEvent e) {
moreButton.setSelected(false);
}
});
menu.show(component, 0, component.getHeight());
}
}
采纳答案by BryanD
Well, here is a potential solution that is not without it's drawbacks. Only you can decide if this is acceptable for your application. The issue is that the popup closing occurs before other mouse-handling events are fired so clicking on your More.. button again causes the popup to hide, thus resetting the buttons state to deselected BEFORE the button even gets told it was pressed.
好吧,这里有一个潜在的解决方案,但它并非没有缺点。只有您可以决定这对于您的应用程序是否可接受。问题是弹出窗口关闭发生在触发其他鼠标处理事件之前,因此再次单击“更多..”按钮会导致弹出窗口隐藏,从而在按钮被告知按下之前将按钮状态重置为取消选择。
The easy workaround is to add the following call within your main program:
简单的解决方法是在主程序中添加以下调用:
UIManager.put("PopupMenu.consumeEventOnClose", Boolean.TRUE);
The result of this is that whenever a popup menu is closed because of a mouse-pressed event, that mouse event will be consumed at the time the menu is closed and won't be passed on to any other components under the mouse. If you can live with limitation, this is an easy solution.
这样做的结果是,每当弹出菜单因鼠标按下事件而关闭时,该鼠标事件将在菜单关闭时被消耗,并且不会传递给鼠标下的任何其他组件。如果您可以忍受限制,这是一个简单的解决方案。
回答by Reverend Gonzo
What's happening is that when you click off the menu, it cancels the popup menu, so you deselect the button, but the next immediate event is clicking the button, and now its deselected so it shows the menu again.
发生的情况是,当您单击菜单外时,它会取消弹出菜单,因此您取消选择该按钮,但下一个直接事件是单击该按钮,现在它已取消选择,因此它再次显示菜单。
I don't have the exact solution yet, but give me a little bit ...
我还没有确切的解决方案,但请给我一点...
回答by camickr
I don't use Firefox so I don't know what the Smart Bookmarks button looks like, but maybe use a JMenu as the "button". You could try using the Border of a JButton to make it look more like a button.
我不使用 Firefox,所以我不知道智能书签按钮是什么样子,但也许使用 JMenu 作为“按钮”。您可以尝试使用 JButton 的 Border 使其看起来更像一个按钮。
回答by Joonas Pulakka
Well, the listener on the button reacts only when it is pushed down, because you listen for ItemEvent.SELECTEDevents only. How about adding another if clause to listen for ItemEvent.DESELECTEDevents here:
好吧,按钮上的侦听器只有在按下时才会做出反应,因为您ItemEvent.SELECTED只侦听事件。如何添加另一个 if 子句来监听ItemEvent.DESELECTED这里的事件:
moreButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
createAndShowMenu((JComponent) e.getSource(), moreButton);
}
}
});
You could either store a reference to the menusomewhere, oryou could make the menu itself add another listener to the button. The latter solution could be more straightforward, since you already seem to send a button reference to the menu.
你既可以存储到一个参考menu的地方,或者你可以使自己的另一个监听器添加到该按钮的菜单。后一种解决方案可能更直接,因为您似乎已经向菜单发送了一个按钮引用。

