How to prevent JMenuItem disabled from hiding the menu when clicked?

In my Java swing application, I noticed that when I click on a disabled JMenuItem in JPopupMenu, it hides this menu, but I don’t want to hide it, as if nothing was clicked. Is there any way to prevent this?

-----------------------------------> Update: added sample code:

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." ); } 
+6
java swing jpopupmenu jmenuitem
source share
7 answers

It has been tested and works.

Look and Feel decides how to handle mouse events on disabled menu items. Anyway, you can intercept unwanted events using a custom MenuItem . Just use this code (copy / paste):

 public class CustomMenuItem extends JMenuItem { public CustomMenuItem(String text) { super(text); } public CustomMenuItem() { super(); } protected void processMouseEvent(MouseEvent e) { if (isEnabled()) super.processMouseEvent(e); } } 

Customize the code first to suit your needs (optional).
Finally, replace any JMenuItem with CustomMenuItem .

What is it!

0
source share

not sure how to prevent. but you can set Visible (false) to prevent it from displaying. Also, if the user clicks on a disabled menu, there will be no action.

0
source share

When you disable JMenuItem, you must remove the ActionListener associated with this JMenuItem using jMenuItem.removeActionListener (). If u deletes that this action will not call the listener and the popup will not disappear. Hope this helps to achieve your goal.

0
source share

In short, you can do this, but you will need to write your own mouse listener, which may require a lot of copies and folders from the jdk source code, which is not a good idea, and I don’t have to say what license restrictions it will put on your code .

I would start digging out of this method:

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

which seems to be the entry point from where the menu processing engine hides the popup. I would take a closer look

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

EDIT . Developing @Burhan Valikarimwala's answer, try this apporach: remove all action listeners from the disabled JMenuItem and save them in some static temp structure (say, a Map<WeakReference<JMenuItem>, List<MouseListener>> ), so this will not hide the pop-up window . When you turn on the menu item again, add all the listeners back. Add it to some use method and it will be smooth.

0
source share

You tried this method: http://download.oracle.com/javase/6/docs/api/javax/swing/JMenuItem.html#setArmed%28boolean%29

"move the menu item so that it can be selected," which I think will do the trick if set to false.

0
source share

The only solution I could come up with for your problem of clicking on disabling JMenuItem causing it to be hidden is below:

 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()); } } } } 

Basically, hiding occurs when your release is inside the borders of JMenuItem, so we check to see if it is disabled and we again show a popup. Since by this time it has already been decided that it will be hidden. I tried to call super.mouseRelease with another MouseEvent indicating the external component and consuming the previous one, but nothing helps.

In any case, this solution works. Enjoy boro

0
source share

I think this is fixed in Java7.

0
source share

All Articles