6

在我的 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." );
}
4

7 回答 7

0

不知道如何预防。但是您可以 setVisible(false) 来防止它被显示。此外,如果用户单击禁用菜单,则不会发生任何操作。

于 2011-03-07T19:35:07.937 回答
0

当您禁用 JMenuItem 时,您应该使用 jMenuItem.removeActionListener() 方法删除与该 JMenuItem 关联的 ActionListener。如果您删除该操作将不会调用侦听器,并且弹出窗口将不会消失。我希望这将有助于实现您的目标。

于 2011-03-08T09:57:43.067 回答
0

简而言之,你可以这样做,但是你将不得不编写自己的鼠标监听器,这可能需要从 jdk 源代码中大量复制粘贴,这不是一个很好的主意,我不确定有什么许可证限制它会放在你的代码上。

我会从这个方法开始挖掘:

javax.swing.plaf.basic.BasicMenuItemUI.Handler#mouseReleased

这似乎是菜单处理机制隐藏弹出窗口的入口点。我会仔细看看

javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber#stateChanged

编辑@Burhan Valikarimwala 的开发答案,试试这个方法:从禁用的 JMenuItem 中删除所有动作侦听器并将它们存储在一些静态临时结构中(比如说 a Map<WeakReference<JMenuItem>, List<MouseListener>>),这样它就不会隐藏弹出窗口。当您再次启用菜单项时,将所有侦听器添加回来。把它变成一些 util 方法,它将是无缝的。

于 2011-03-08T15:07:07.977 回答
0

您是否尝试过这种方法:http: //download.oracle.com/javase/6/docs/api/javax/swing/JMenuItem.html#setArmed%28boolean%29

“武装菜单项,以便可以选择它”,我想如果设置为 false 就可以了。

于 2011-03-10T10:35:13.753 回答
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 并使用前一个,但它没有任何帮助。

无论如何,这个解决方案有效。享受吧,波罗

于 2011-04-05T19:33:06.550 回答
0

这已经过测试并且有效。

外观决定如何处理禁用菜单项上的鼠标事件。无论如何,您可以使用自定义拦截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);
    }
}

首先,调整代码以满足您的需求(可选)。
最后,any替换JMenuItemCustomMenuItem.

就是这样!

于 2011-04-17T11:24:37.267 回答
0

我认为在 Java7 中这已得到修复。

于 2013-11-28T14:17:04.470 回答