Add actions to JPopupMenu options - java

I have a class that extends JPanel and implements MouseListener. In this class, if the panel is clicked the following two functions are executed:
#Override
public void mouseClicked(MouseEvent e) {
displayExitPopup();
}
private void displayExitPopup() {
JPopupMenu exitPopup = new JPopupMenu();
exitPopup.add("Exit Game");
exitPopup.add("Cancel");
exitPopup.show(this, this.getWidth(), this.getHeight());
}
This all works fine and the popup displays the 2 options as it should.
Now I am trying to perform actions when either of the two options in the popup menu are clicked - System.exit(0) if Exit Game is clicked, and the popup menu to close if Cancel is clicked. How can this be done?

If you take a look at the JavaDocs for JPopupMenu#add(String), you will find that it's a convenience method which returns a JMenuItem, you should then be able to add an ActionListener to it
Take a look at Bringing up a PopupMenu for more details
Having said that, I would instead, encourage you to make use the Action API which will allow you to create self contained units of work, which also provide the information needed to create the JMenuItem used by the JPopupMenu
Have a look at How to Use Actions for more details
You should also be using JComponent#setComponentPopupMenu instead of trying to use a MouseListener, as different platforms have different triggers for a popup menu and it's complicated and ugly real quick

When adding a item to JPopupMenu, you get a JMenuItem. On this object, you can call addActionListener to add a action listener, like you have with a JTextField or a JButton.
exitPopup.add("Cancel").addActionListener(e-> {
// do something
});

Related

ItemListener vs ChangeListener vs ActionListener

I've seen many Java Swing programs that use ActionListener, ChangeListener, or ItemListener. What are the differences between these and when should I use each one?
ActionListener
They are used with buttons or menu. So that whenever you click them it notifies the ActionEvent which in turn invokes the actionPreformed(ActionEvent e) function to perform the specified task.
ItemListeners
These are used with checkboxes, radio buttons, combo boxes kinds of stuff.
See what happens when you use ActionListener with combo box instead of item listener in this link https://coderanch.com/t/331788/java/add-listener-combo-drop-list.
ChangeListener
This is used with components like sliders, color choosers and spinners where you want the action to be performed according to the change in that component (https://docs.oracle.com/javase/tutorial/uiswing/events/changelistener.html). Focus on the word "change". Then you might think it should work with buttons too. You can see for yourself on this website http://www.java2s.com/Tutorial/Java/0240__Swing/AddchangelistenertoButtonmodel.htm
For a JMenuItem, instead of a listener, you should use an Action (which is a more capable form of ActionListener):
Action saveAction = new AbstractAction("Save") {
#Override
public void actionPerformed(ActionEvent event) {
saveDocument();
}
};
saveAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
saveAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control S"));
saveMenuItem = new JMenuItem(saveAction);
For JCheckBoxMenuItems and JRadioButtonMenuItems, just as with regular JMenuItems, the Action’s actionPerformed method is called when the user activates the menu item. You can check the new state from within your Action:
Action showStatusAction = new AbstractAction("Show Status") {
#Override
public void actionPerformed(ActionEvent event) {
boolean selected = (Boolean) getValue(SELECTED_KEY);
statusBar.setVisible(selected);
}
};
showStatusAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_W);
showStatusAction.putValue(Action.SELECTED_KEY, true);
showStatusMenuItem = new JCheckBoxMenuItem(showStatusAction);
Note that Action.SELECTED_KEY only works if you set it to true or false before you install the Action. From the documentation:
Components that honor this property only use the value if it is non-null. For example, if you set an Action that has a null value for SELECTED_KEY on a JToggleButton, the JToggleButton will not update its selected state in any way. Similarly, any time the JToggleButton's selected state changes it will only set the value back on the Action if the Action has a non-null value for SELECTED_KEY.
If you insist on using listeners directly, ItemListener indicates selection state, so it can be used to monitor the state of JCheckBoxMenuItems and JRadioButtonMenuItems. For all other JMenuItems, use ActionListener.
The above actually applies to all descendants of AbstractButton as well as JMenuItem and its descendant classes:
For JButtons, use an Action.
For JToggleButtons, JCheckBoxes, and JRadioButtons, use an Action and check its SELECTED_KEY value.
If you aren’t willing to use Actions, use ActionListener for JButtons, and use ItemListener for JToggleButtons, JCheckBoxes, and JRadioButtons.
My understanding is that there is no reason to use a ChangeListener with a standard JMenuItem or button, as a ChangeEvent is mainly intended to indicate to renderers that the component needs to be repainted.

Forcing a JPopupMenu to disable hover effects on its owner JFrame?

When i right click on a JTable in a JFrame I show a JPopupMenu. If I left this JPopupMenu shown as it is and moved with the mouse to the JTable I can still hover on its rows.
This is not the default behavior of Windows applications. In normal case if a popup menu appears in a program it blocks any hover actions on the popup owner window.
Can i do the same thing in Java ?
One way to approach this problem is to set an instance variable in one of your GUI elements to flag whether or not to enable hover events. I have shown below how this may work, but it's not in its complete form, you will also need to re-enable hover when the JPopupMenu is dismissed, and also check the state of the ENABLE_HOVER field before firing hover effects.
public MyTable extends JTable {
private boolean ENABLE_HOVER = true;
public MyTable() {
...
this.addMouseListener(new MouseListener(){
...
public void mouseClicked(MouseEvent e) {
if (isRightClick(e)) {
setHoverEnabled(false);
showJPopupMenu();
}
}
});
}
protected void setHoverEnabled(final boolean hover) {
this.ENABLE_HOVER = hover;
}
}
Another method which may be better suited to disabling multitudes of however enabled elements is to intercept the events at the glass pane. An example of how this might work is shown here. Be warned though if your interface is already built it may require significant re-jigging of your component classes.
You will need to intercept all events at the glass pane, if hover is enabled (no popup menu shown) you would pass the event to the appropriate component. Otherwise if hover is disabled and the MouseEvent occurred over the JPopupMenu is passed only to the JPopupMenu.

How can i display new GUI based on menu click

I am learning java and building one project to test basics.
I have one menu item FILE and then sub menu item like
1)Front
2)Admin
3)Booking
I have separate gui made in separate files but i want that they should be visible in one area , with click on submenus
I am using swing , JmenuBar . Also the other guis are using Jframe
I have separate gui made in separate files but i want that they should be visible in one area
Most applications should only ever have a single JFrame, which indeed is your requirement since you want the separate GUI to be visible in the same area.
Therefore your other GUI, should not extend JFrame but instead should extend JPanel. Then you can just use a CardLayout on your real GUI to swap the panels in/out depending on which panel is selected from your menu. All these basic are covered in the Swing tutorial. I guess you would start with the section on:
How to Use Card Layout
How to Use Menus
Other people have already talked about ActionListeners and stuff, so that's half of the problem. The other half is how to actually deal with the multiple windows. I would probably not use one JFrame per different GUI, given that the spirit of the JFrame suggests you should only have one instance of it per application. Instead, I would look at using either JDialog or JInternalFrame. I'm not sure what you mean by
...should be visible in one area...
but JInternalFrame will allow you to implement something like a multiple document interface, where all the sub-GUIs would be contained within the frame of the main UI. JDialog would be give you independent windows like JFrame does.
If with "they should be visible in one area" you mean modal, then you should change all your JFrames to JDialogs and leave only the JFrame that contains your main-menu.
To do this, you need an ActionListener for each of the menu items. Then have each listener pass the instance of the JFrame you want to a method that controls where you want to position the window and show it.
//Make menu items
JMenuItem font = new JMenuItem();
font.addActionListener(new ActionListener() {
showWindow(new FontFrame());
});
JMenuItem admin = new JMenuItem();
admin.addActionListener(new ActionListener() {
showWindow(new AdminFrame());
});
...
//define frame handling method
void showWindow(JFrame f) {
...
f.setVistible(true);
}

Swing make a JButton not focussable

I want to make a Java swing button 'not-focussable'.
The button should not receive focus at all, but should be able to receive mouse clicks.
I thought the following options, but these either dont solve my problem completely, or dont seem elegant. Are there any other/better/suggested options?
Move the focus to the next component immediately when the button receives focus (but then what do I do if the button is the only component on the UI other than labels?)
Implement another non-focusable component as a button (a label with mouse events, borders...) (this does not look very elegant to me)
Create a anonymous button implementation that overides the keyboard events so that it does not respond to keyboard events (this does not solve the focus problem, but is somwhat ok for me, since the root of the problem is to avoid accidental keyboard clicks. I will do this only if there are no options at all, but even then prefer option 2)
All Swing components have a setFocusable method to do this:
JButton button = ...
button.setFocusable(false);
Did you try to call the setFocusable() method inherited from java.awt.Component ?
Resources :
Javadoc - Component.isFocusable()
Oracle.com - Focus tutorial
You can implement your own FocusTraversalPolicy (or extend e.g. ContainerOrderFocusTraversalPolicy) with an accept method that just doesn't like your button.
JFrame frame = new JFrame();
... /* create other components */
frame.setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy() {
public boolean accept(Component c) {
return super.accept(c) && c!=iDontLikeYouButton;
}
});

JWindow alway on top not getting focus events

I have a jwindow(set to be always on top) that you can click to get a pop menu. If the user right clicks the window it shows the pop menu but then if the user clicks any other window(such as firefox) pop menu does not disappear.
I tried to fix it by adding FocusListener on the jwindow, i implemented FocusListener and override
public void focusGained(FocusEvent e) {
System.out.println("gain" );
}
public void focusLost(FocusEvent e) {
System.out.println("lost" );
}
but there event never get called. i also tried the following,
addWindowFocusListener(new WindowAdapter() {
public void windowGainedFocus(WindowEvent e) {
System.out.println("gain 2" );
}
});
this event also not called.
All this jwindows has is a single JLabel with a picture on it.
From memory JWindow's do not receive focus/window events.
You are suppose to call setFocusableWindowState(true) on a JWindow to allow it to be focusable. But that "still" is not enough. The JWindow must also have focusable Components and I'm still not able to get it to work.
Using JFrame setUndecorated() seems the best choice.
To be focusable, a JWindow needs to be created with a parent Frame, like new JWindow(parentFrame). Do that and I think you should find it will automatically get the focus when you set it to visible.
Not really sure what you are trying to do. If you are trying to hide the popup manually then you should probably use a WindowListener and handle the windowDeactivated event.
If you really want to display a popup menu, you should be using JPopupMenu, not implementing it yourself.

Categories