簡體   English   中英

如何防止被禁用的JMenuItem在被點擊時隱藏菜單?

[英]How to prevent a disabled JMenuItem from hiding the menu when being clicked?

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

我認為在Java7中這已得到修復。

不知道如何預防。 但你可以setVisible(false)來防止它被顯示。 此外,如果用戶單擊禁用菜單,則不會執行任何操作。

禁用JMenuItem時,應使用jMenuItem.removeActionListener()方法刪除與該JMenuItem關聯的ActionListener。 如果你刪除那個動作將不會調用監聽器,彈出窗口將不會消失。 我希望這有助於實現您的目標。

簡而言之,你可以這樣做,但你必須編寫自己的鼠標監聽器,這可能需要從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方法,它將是無縫的。

你試過這個方法了嗎: http//download.oracle.com/javase/6/docs/api/javax/swing/JMenuItem.html#setArmed%28boolean%29

“設置菜單項以便可以選擇它”,如果設置為false,我想這會成功。

我能提出的唯一解決方案,因為你點擊禁用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並使用前一個,但它沒有任何幫助。

無論如何這個解決方案有效 享受,博羅

這已經過測試和運作。

外觀和感覺決定如何處理禁用菜單項上的鼠標事件。 無論如何,您可以使用自定義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);
    }
}

首先,根據您的需求調整代碼(可選)。
最后, CustomMenuItem 替換任何JMenuItem

而已!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM