在我的Java swing应用程序中,我注意到当我在JPopupMenu中单击禁用的JMenuItem时,它会隐藏菜单,但我不想隐藏它,就像没有点击任何内容一样。有办法防止这种情况吗?
-----------------------------------> 更新:添加了代码示例:
JMenuItem saveMenuItem = new JMenuItem();
saveMenuItem.setEnabled(false);
saveMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveMenuItemActionPerformed();
}
});
add(saveMenuItem);
private void saveMenuItemActionPerformed() {
System.out.println( "Save clicked." );
}
答案 0 :(得分:0)
不确定如何预防。但你可以setVisible(false)来防止它被显示。此外,如果用户单击禁用菜单,则不会执行任何操作。
答案 1 :(得分:0)
当您禁用JMenuItem时,应该通过使用删除与该JMenuItem关联的ActionListener jMenuItem.removeActionListener()方法。 如果你删除那个动作将不会调用监听器,弹出窗口将不会消失。 我希望这有助于实现目标。
答案 2 :(得分:0)
简而言之,你可以这样做,但你必须编写自己的鼠标监听器,这可能需要大量的复制和粘贴来自jdk源代码,这不是一个好主意,我不是确定它将对您的代码赋予哪些许可限制。
我会从这种方法开始挖掘:
javax.swing.plaf.basic.BasicMenuItemUI.Handler#mouseReleased
这似乎是菜单处理机制隐藏弹出窗口的入口点。我会仔细看看
javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber#stateChanged
编辑通过@Burhan Valikarimwala开发答案,尝试此apporach:从禁用的JMenuItem中删除所有动作侦听器并将它们存储在某个静态临时结构中(假设为Map<WeakReference<JMenuItem>, List<MouseListener>>
),这它不会隐藏弹出窗口的方式。再次启用菜单项时,请添加所有侦听器。将它变成一些util方法,它将是无缝的。
答案 3 :(得分:0)
你试过这个方法了吗: http://download.oracle.com/javase/6/docs/api/javax/swing/JMenuItem.html#setArmed%28boolean%29
“设置菜单项,以便可以选择”,如果设置为false,我想这会成功。
答案 4 :(得分:0)
我能提出的唯一解决方案,因为您点击禁用JMenuItem导致其隐藏的问题如下:
import java.awt.Color;
import java.awt.Dimension;
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 javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
public class PopupMenuDisableNoCloseTest extends JPanel implements ActionListener
{
public static void main(String[] args)
{
PopupMenuDisableNoCloseTest p = new PopupMenuDisableNoCloseTest();
p.setPreferredSize(new Dimension(200, 300));
p.setBackground(Color.GREEN);
JPanel contentPane = new JPanel();
contentPane.add(p);
final JFrame f = new JFrame();
final JPopupMenu popup = new JPopupMenu();
final JMenuItem menuItem1 = new JMenuItem("A popup menu item");
menuItem1.addActionListener(p);
menuItem1.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e)
{
System.out.println(" menuItem1 mousePressed e.getPoint()=" + e.getPoint());
}
@Override
public void mouseReleased(MouseEvent e)
{
System.out.println(" menuItem1 mouseReleased e.getPoint()=" + e.getPoint());
if(!menuItem1.isEnabled())
popup.setVisible(true);
}
});
menuItem1.setEnabled(false);
popup.add(menuItem1);
JMenuItem menuItem2 = new JMenuItem("Another popup menu item");
menuItem2.addActionListener(p);
popup.add(menuItem2);
MouseListener popupListener = new PopupListener(popup);
f.addMouseListener(popupListener);
f.setContentPane(contentPane);
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e)
{
JMenuItem source = (JMenuItem) (e.getSource());
String s = "Action event detected. Event source: " + source.getText();
System.out.println("s=" + s);
}
static class PopupListener extends MouseAdapter
{
JPopupMenu popup;
PopupListener(JPopupMenu popupMenu)
{
popup = popupMenu;
}
@Override
public void mousePressed(MouseEvent e)
{
maybeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e)
{
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e)
{
if(e.isPopupTrigger())
{
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
}
基本上,当你的发布在JMenuItem的边界内时发生隐藏,因此我们检查它是否被禁用然后我们再次显示弹出窗口。到目前为止,已经确定它将被隐藏。我试图用一个不同的MouseEvent调用super.mouseRelease来指向组件外部并使用前一个但它没有任何帮助。
无论如何这个解决方案有效。 享受,博罗
答案 5 :(得分:0)
这已经过测试并且有效。
The Look&amp;感觉决定如何处理禁用菜单项上的鼠标事件。无论如何,您可以使用自定义MenuItem
拦截不受欢迎的事件。只需使用该代码(复制/粘贴):
public class CustomMenuItem extends JMenuItem {
public CustomMenuItem(String text) {
super(text);
}
public CustomMenuItem() {
super();
}
protected void processMouseEvent(MouseEvent e) {
if (isEnabled()) super.processMouseEvent(e);
}
}
首先,根据您的需要调整代码(可选)
最后,使用JMenuItem
替换任何CustomMenuItem
。
就是这样!
答案 6 :(得分:0)
我认为在Java7中这已得到修复。