I have the following JMenu:
So, i added the same mouseclicked event in each menu option, so when i click one of them, in the evt, i can get the text. On the event i have the following code:
private void menuMouseClicked(java.awt.event.MouseEvent evt) {
System.out.println(evt.getSource ());
}
Having this, each time i press a option, i get the output:
.....javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],paintBorder=false,paintFocus=false,pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Add]
So the thing that i want, is from the evt, get the Text that says in the case of the first option "Add". How can i do this?
Cast it to the JMenuItem and call getText()
private void menuMouseClicked(java.awt.event.MouseEvent evt) {
JMenuItem menuItem = (JMenuItem) evt.getSource();
System.out.println(menuItem.getText());
}
You may want to also look into JMenuItem#addActionListener. You can add an ActionListener to a specific JMenuItem and then use the same logic:
someMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
JMenuItem menuItem = (JMenuItem) evt.getSource();
System.out.println(menuItem.getText());
}
});
Related
I know how to create Java Swing submenus using JMenu. When we hover the mouse over a JMenu object, it displays a JPopupMenu showing the submenu items, like this:
Submenu using JMenu
My problem is that in my application, determining which menu elements will have a submenu is expensive. I don't want to have to determine in advance whether a particular menu element should be a JMenu or just a JMenuItem. I want to make every element a JMenuItem and display a submenu for it only if the user requests it by, e.g., hovering the mouse over a menu item. Like this:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Menu2 extends JFrame
{
public Menu2()
{
super("Menu2");
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu mItems = new JMenu("Items");
menuBar.add(mItems);
mItems.add(new JMI("A"));
mItems.add(new JMI("B"));
mItems.add(new JMI("C"));
JLabel stuff = new JLabel("Other stuff");
stuff.setPreferredSize(new Dimension(200,200));
getContentPane().add(stuff);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private class JMI extends JMenuItem
implements MouseListener
{
public JPopupMenu childrenPopup = null;
public JMI(String label)
{
super(label);
addMouseListener(this);
}
// MouseListener
public void mouseClicked(MouseEvent ev) {}
public void mouseEntered(MouseEvent ev)
{
// Show a submenu for item "B" only.
// In real life we'd want a Timer to delay showing the submenu
// until we are sure the user is hovering the mouse.
// For simplicity I've omitted it.
if (getText().equals("B")) {
if (childrenPopup == null) {
childrenPopup = new JPopupMenu();
// Expensive processing to determine submenu elements...
childrenPopup.add("D");
childrenPopup.add("E");
}
// Display the submenu
childrenPopup.show(this,getWidth(),0);
}
}
public void mouseExited(MouseEvent ev) {}
public void mousePressed(MouseEvent ev) {}
public void mouseReleased(MouseEvent ev) {}
}
public static void main(String[] args)
throws Exception
{
new Menu2().setVisible(true);
}
}
The only problem is that when my manually created JPopupMenu is displayed, the rest of the menu gets closed. The resulting display does not look like the earlier one, but rather like this:
Submenu displayed manually
Note that I did not click on the "B" menu item, only moved the mouse into it. The menu did not close due to a mouse click.
How can I do what JMenu does -- display a JPopupMenu without closing the rest of the menu?
The approach I've tentatively decided upon is to extend JMenu instead
of JMenuItem and use this type for all of my menu elements. But I
won't populate these elements (the expensive step) until the user
requests it by hovering the mouse.
To avoid cluttering up the menu with the arrow icons that JMenu
normally displays (potentially misleading in this case), I use a technique described by Stackoverflow's MadProgrammer to instantiate an arrowless JMenu in a static factory method. Since I
restore the arrow icon property after creating the arrowless JMenu,
normal JMenu instances created elsewhere will still show the arrow.
Some menu elements will need to execute actions and close the menu,
like a JMenuItem does. A JMenu doesn't normally respond to mouse
clicks, so I execute click actions in my MouseListener.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Menu3 extends JFrame
{
public Menu3()
{
super("Menu3");
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu mItems = new JMenu("Items");
menuBar.add(mItems);
mItems.add(JM.create("A"));
mItems.add(JM.create("B"));
mItems.add(JM.create("C"));
JLabel stuff = new JLabel("Other stuff");
stuff.setPreferredSize(new Dimension(200,200));
getContentPane().add(stuff);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private static class JM extends JMenu
implements MouseListener
{
private static final String ARROW_ICON_KEY = "Menu.arrowIcon";
private boolean populated = false; // Submenu already populated?
protected JM(String label)
{
super(label);
addMouseListener(this);
}
// This static factory method returns a JM without an arrow icon.
public static JM create(String label)
{
UIDefaults uiDefaults = UIManager.getLookAndFeelDefaults();
Object savedArrowIcon = uiDefaults.get(ARROW_ICON_KEY);
uiDefaults.put(ARROW_ICON_KEY,null);
JM newJM = new JM(label);
uiDefaults.put(ARROW_ICON_KEY,savedArrowIcon);
return newJM;
}
// MouseListener
public void mouseClicked(MouseEvent ev)
{
// Since some menu elements need to execute actions and a JMenu
// doesn't normally respond to mouse clicks, we execute click
// actions here. In real life we'll probably fire some event
// for which an EventListener can listen. For illustrative
// purposes we'll just write out a trace message.
System.err.println("Executing "+getText());
MenuSelectionManager.defaultManager().clearSelectedPath();
}
public void mouseEntered(MouseEvent ev)
{
// In real life we'd want a Timer to delay showing the submenu
// until we are sure the user is "hovering" the mouse.
// For simplicity I've omitted it.
// Populate this submenu only once
if (!populated) {
// For purposes of example, show a submenu for item "B" only.
if (getText().equals("B")) {
// Expensive processing...
add(create("D"));
add(create("E"));
}
populated = true;
}
}
public void mouseExited(MouseEvent ev) {}
public void mousePressed(MouseEvent ev) {}
public void mouseReleased(MouseEvent ev) {}
}
public static void main(String[] args)
throws Exception
{
new Menu3().setVisible(true);
}
}
The result works the way I want:
Menu3 with open menu
I am trying to make my application minimize on taskbar and restore when I double click on the trayIcon. I also have a popup menu that has an item which restores the window when clicked.
trayIcon = new TrayIcon(image, "Anything", popup);
trayIcon.addActionListener(actionListener);
trayIcon.addMouseListener(mouseListener);
sysTray.add(trayIcon);
And here is the code of the actionListener and mouseListener:
private ActionListener actionListener = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getActionCommand().equals("Restore"))
{ // RIGHT CLICK -> RESTORE
// Do something
}
}
};
private MouseListener mouseListener = new MouseListener()
{
#Override
public void mouseClicked(MouseEvent e)
{
if (javax.swing.SwingUtilities.isLeftMouseButton(e) && e.getClickCount()>1)
{ // DOUBLE LEFT MOUSE CLICK
// Do something
}
}
// Rest of the code
}
The Restore option of the popup menu works fine, however when I am double-clicking on the trayIcon at the System Tray I get a Null Pointer Exception at line if(e.getActionCommand().equals("Restore"))
How can I eliminate this and if possible merge both listeners into one?
N.B. This answer is made from a conversation with the OP in the comments, and some of the solutions came from the OP
The TrayIcon does not populate the ActionCommand field when firing the event, hence the code dies with an NPE.
Since the tray icon only calls its ActionListener only when double clicked or in an analagous action (via keyboard), you can create a RestoreListener that does not check that condition at all, and is only used with the tray icon and the "Restore" menu item.
private ActionListener restoreListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Do the actual restoration
}
};
And actually adding it to the items...
trayIcon = new TrayIcon(image, "Anything", popup);
trayIcon.addActionListener(restoreListener);
MenuItem restoreMenuItem = new MenuItem(...);
restoreMenuItem.addActionListener(restoreListener);
This seems to behave slightly differently from a MouseListener that it does not put the window on top, this can be remedied by calling toTop() on it.
I am a beginner in both Java and Processing. I am trying to create a right click popup menu that will be displayed inside a processing jPanel. Part of the code I m using is displayed bellow, belongs to the class that extends PAplet. Initially, popup menu is displayed properly when right mouse buttonis pressed, but after using some other elements of the GUI, it doesnt appear on the screen anymore.
How to fix this? Shall I create the popup menu inside steup() method? Or elsewhere?
Thanks.
private JPopupMenu menu = new JPopupMenu();
private JMenuItem edgeFrom = new JMenuItem("Edge From");
private JMenuItem edgeTo = new JMenuItem("Edge To");
#Override
public void setup() {
size(desiredheight,desiredwidth);
background(255);
PopupActionHandler handler = new PopupActionHandler();
edgeFrom.addActionListener(handler);
edgeTo.addActionListener(handler);
menu.add(edgeFrom);
menu.add(edgeTo);
addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent evt) {
if (evt.isPopupTrigger()) {
menu.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
});
}
Use the below reference link for JPopupMenu
http://www.java2s.com/Code/Java/Swing-JFC/AsimpleexampleofJPopupMenu.htm
Let's say I have a JMenuItem with a text inside "Exit", and a JButton with the text "Exit",
the command which JButton will use is System.exit(0), of course using Action Listener, Ok i Know, I can put the same codes when clicking on the JMenuItem, but isn't there a way, that when I click on the JMenuItem, the JButton is clicked so then the following commands are executed (JButton commands)?
What you can do is create an Action object, and use that for both your JButton and your JMenuItem.
Action exit = new AbstractAction() {
private static final long serialVersionUID = -2581717261367873054L;
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
};
exit.putValue(Action.NAME, "Exit");
exit.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_X);
JButton exitButton = new JButton(exit);
JMenuItem exitItem = new JMenuItem(exit);
A good way to do this is to set the same ActionListener to both components. Like this:
JButton button = new JButton ("Exit");
JMenuItem item = new JMenuItem ("Exit");
ActionListener exitaction = new ActionListener ()
{
public void actionPerformed (ActionEvent e)
{
System.exit (0);
}
};
button.addActionListener (exitaction);
item.addActionListener (exitaction);
However, I would recommend against using System.exit (0). The better way of closing the program (which I assume is basically a JFrame) is by setting
frame.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)
(where frame is the window of the program)
and calling frame.dispose () in the ActionListener.
I consider the best way to do this is to register the same ActionListener instance in the event listeners of both JMenuItem and JButton, it's like using the old Command design pattern.
I would not recommend trying to trick the events 'engine' like making the JMenuItem fire the event related to the pressing of the JButton, since that is not what's happening but what you seem to want is to reuse both actions to 2 distinct events.
You can try to save the button as a class field
private JButton button;
and insert in the click event handler of the menu item the code
button.doClick();
but the solution of SoboLAN is more elegant.
menuBar = new JMenuBar();
// File Menu
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
// File->New
JMenuItem newMenuItem = new JMenuItem("New");
frame.setJMenuBar(menuBar);
newMenuItem.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
btnExample.setText("Clicked");
btnExample.doClick();
//---------->SOME HOW TO EXECUTE btnExample<---------//
}
});
fileMenu.add(newMenuItem);
final JButton btnExample = new JButton("SD");
frame.getContentPane().add(btnExample, "cell 4 0,growx,aligny top");
btnExample.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
spinnerForVar.setValue(4);//default value for spinner
spinnerForFunc.setValue(4);//default value for spinner
...
}
});
Hello! I hope someone can help me. Here it is the problem: I have Menu item "New" and have button btnExample. I want the following: When i click on "File->New" it executes btnExample. My code is able only to change the button title and show visual affect of clicking. But how can I actually execute it?
I have only one advice - don't do that. Don't bind GUI components in this way.
If you want two components to execute the same operation, simply pack this operation in a method and call the method from both components.
Also, use ActionListener - are you sure the user is going to press it using mouse and not keyboard? what if you add shortcuts to those buttons/components?
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
//My button to click on it
jButton1ActionPerformed(evt);//this is the call for the other button to execut it
}
You should not be using a MouseListener for this.
You should be using Actions. Then you can add the Action to both the JButton and the JMemuItem.
Read the section from the Swing tutorial on How to Use Actions.
Amazing, I found my solution in your codes!
btnExample.doClick();
This did the job for me