I created a Java app in WindowBuilder for Eclipse. I built a menu and on one of the menu items I added the mouseclicked event.
JMenuItem mitemAbout = new JMenuItem("About");
mitemAbout.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
JOptionPane.showInternalMessageDialog( form, "Message", "title", JOptionPane.PLAIN_MESSAGE);
}
});
mitemHelp.add(mitemAbout);
I put a breakpoint on the JOptionPane line and when I click on the menu item in debug mode it doesn't even get to it.
Am I completely missing a step here?
Although JMenuItem components offer the addMouseListener method (inherited from java.awt.Component) MouseEvents are only processed for the MenuElements own functional use, i.e. any external MouseEvents will have no effect.
For JMenuItem components, use an ActionListener rather than a MouseListener to listen for user events:
mitemAbout.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
...
}
});
or use:
mitemAbout.setAction(myAction);
Related
I have a simple MouseAdapter that I add to a JMenu. I want the menu to show its contents when moused over, react when clicked on, and hide its contents when the mouse leaves it. Here's where I add the listener:
public final void addGuiReaction(Runnable clickReaction) {
JMenu THIS = this;
this.addMouseListener(new MouseAdapter() {
final Runnable reaction = clickReaction;
final JMenu source = THIS;
#Override
public void mouseClicked(MouseEvent arg0) {reaction.run();}
#Override
public void mouseEntered(MouseEvent arg0) {source.doClick();} // Opens the menu
#Override
public void mouseExited(MouseEvent arg0) {/* Need to "close" the menu */}
});
}
This works just fine for both the reaction and the open when moused over functionality, but I can't figure out how to close it. Tried both setSelected(false) and setPopupMenuVisible(false) but the issue with both is that the menu doesn't open again the next time I mouse over it.
Anyone knows a nice way of closing the menu?
Answering to "How to close the JMenu..."
In place of this:
/* Need to "close" the menu */
You can put this:
source.dispatchEvent(new KeyEvent(source, KeyEvent.KEY_PRESSED, 0, 0, KeyEvent.VK_ESCAPE));
Hence simulate the ESC key press which will trigger the respective Action from the ActionMap of the JMenuBar.
However this will not fully solve your problem as while the keyboard arrow keys will work, you will not be able to use the mouse to select any of the items of the JMenu as trying to enter any of them will trigger the JMenu mouseExited event. You may need to attach a proper mouse event listener to the menu items as well.
I just began using JMenu. To ease into it, I decided to use Netbeans form design tool, which has worked great for all components in this app.
Clicking a top-level menu item works great.
For one menu item, I made a submenu with 3 items, each with a mouse click listener.
Here's relevant code for one of the 3 submenus:
private JMenuItem mnuEditDicAddAllScratch;
mnuEditDicAddAllScratch = new JMenuItem();
private void mnuEditDicAddAllScratchMouseClicked(MouseEvent evt) {
new WordsToAdd(); // never happened
}
mnuEditDicAddAllScratch.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
mnuEditDicAddAllScratchMouseClicked(evt);
}
});
mnuEdit.add(mnuEditDicAddAllScratch);
It didn't work. Clicks ignored.
So I tried an Action listener:
private void mnuEditDicAddAllScratchActionPerformed(ActionEvent evt) {
new WordsToAdd(); // WORKED
}
mnuEditDicAddAllScratch.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
mnuEditDicAddAllScratchActionPerformed(evt);
}
});
And it worked.
So a question is, "Why didn't mouse click listener listen?"
Also, "If I should stay away from mouse click events, why or under what circumstances?"
(And, pre-emptive strike: I should stay away from Netbeans form designer.)
You should use the best tool for the job at hand. This means that for JMenuItems and for JButtons, you should use ActionListeners, not MouseListeners (exceptions notwithstanding). For instance if you disable a button, you want the button to not work, right? This works with ActionListeners but not with MouseListeners.
For the best information on this type of stuff, go to the source: Swing Tutorials.
mnuEditDicAddAllScratch.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
mnuEditDicAddAllScratchActionPerformed();
}
});
I made a popup menu in Netbeans and I want to make a menu item that sends me to another GUI when I press it, but I don't know how.
I have to do something like a restaurant menu and when someone presses the button from the menu to send them to a specific type of food.
I made it only to popup when I right click it.
private void formMousePressed(java.awt.event.MouseEvent evt) {
if(evt.isPopupTrigger()){
jPopupMenu1.show(evt.getComponent(),evt.getX(),evt.getY());
}
}
private void formMouseReleased(java.awt.event.MouseEvent evt) {
if(evt.isPopupTrigger()){
jPopupMenu1.show(evt.getComponent(),evt.getX(),evt.getY());
}
}
"I want to make a menu item that sends me to another GUI when I press it, but I don't know how."
I'm, not sure how the drag and drop works with GUI Builder for JPopupMenu. I tried to to drap and drop it, but it won't show the display, so I couldn't just drag and drop JMenuItems to it. So I had to hand code it.
I dragged a JPopupMenu to the frame (jPopupmenu1);
In the constructor, I added a JMenuItem to it.
I added an ActionListener to the JMenuItem
Just show instantiate the second GUI , and maybe dispose of the second, depending on your preference
public NewJFrame() {
initComponents();
JMenuItem item1 = new JMenuItem("Open GUI2");
jPopupMenu1.add(item1);
item1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
new GUI2();
}
});
}
....
private void formMousePressed(java.awt.event.MouseEvent evt) {
if (evt.isPopupTrigger()) {
jPopupMenu1.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
private void formMouseReleased(java.awt.event.MouseEvent evt) {
if (evt.isPopupTrigger()) {
jPopupMenu1.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
It works fine for me
I'm a little confused on where the action logic (what happens when a user selects a menu item from the popup) should be placed. Currently, I have it stored in a subclass of JPopupMenu, but it doesn't seem to call the event when I click on a menu item.
Subclass code:
public class MyPopupMenu extends JPopupMenu {
JMenuItem item1;
JMenuItem item2;
public MyPopupMenu() {
item1 = new JMenuItem("New Tab");
item2 = new JMenuItem("Close Tab");
add(item1);
add(item2);
}
class myListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent ev) {
System.out.println("I've been clicked!");
}
}
}
I attached this to my JTabbedPane by calling the setComponentPopupMenumethod.
myTabPane.setComponentPopupMenu(myPopupMenu);
This compiles OK. And it does show the popup menu as expected, but upon selecting one of the menu options in the popup, all is silent. No message gets displayed. Do I need to put it somewhere else?
you have to add MouseListener to JMenuItems
add proper listener to use Swing Action, ActionListener for JMenuItems, read Oracle tutorial for working code example
Add MouseListner to your menu item
myListener myListener = new myListener();
item1.addMouseListener(myListener);
item2.addMouseListener(myListener);
Seems your approach is bit wrong. Please refer How to Use Menus
The JMenuBar does not start showing JMenuItems as selected or displaying the JMenu popups until it is first clicked upon. After you click somewhere in the JMenuBar, all these items respond to mouse hovers.
I would like to bypass the initial click required and have it activated automatically upon a mouse hover. Is there a way to do this?
The way is to add a MouseListener on the JMenu and listen on events mouseEntered. In the event handlers, you just need to click on it using doClick. For example,
jMenuFile.addMouseListener(new MouseListener(){
public void mouseEntered(MouseEvent e) {
jMenuFile.doClick();
}
...
});
Once programmatically clicked on the mouse is entered, it opens the popup menu automatically. To activate an entire JMenuBar, you have to add a listener on each JMenu. For this purpose, it is better to create a listener object separately.
I have two menu items on the bar, so I did:
MouseListener ml = new MouseListener(){
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
((JMenu)e.getSource()).doClick();
}
};
jMenuFile.addMouseListener(ml);
jMenuHelp.addMouseListener(ml);
If you have so many menu items on the bar, you can just iterate it:
for (Component c: jMenuBar1.getComponents()) {
if (c instanceof JMenu){
c.addMouseListener(ml);
}
}
Roman C's initial and accepted answer will not AUTO Close the menu with child MenuItems as part of the JMenuBar.
Running a ((JMenu)e.getSource()).doClick(); on the mouseEntered simulates the click into one of the JMenu parents but can't be simply added to the mouseExited method as the MouseListener needs to be attached to the child MenuItems as well as the JMenu parents. (Which it doesn't do in the normal assignment to the MenuBar - only attaching to the parent JMenu objects).
Additionally, a problem arises due to trying to get the MouseExit listener to fire a "close" method ONLY when the mouse has left the entire Menu structure (ie the Child menu dropdowns).
Below is a fully working answer taken from my live app:
The way I solved the menu close on mouse out was to run a boolean variable "isMouseOut" in the top of the constructor to keep track, and then allocate the MouseListener in a more OO friendly way to keep track of the multiple MouseIn-MouseOut events as a user interacts with the menu. Which calls a separate menuClear method acting upon the state of the boolean "isMouseOut". The class implements MouseListener. This is how its done.
Create an ArrayList adding all the menu items to this array first. Like so:
Font menuFont = new Font("Arial", Font.PLAIN, 12);
JMenuBar menuBar = new JMenuBar();
getContentPane().add(menuBar, BorderLayout.NORTH);
// Array of MenuItems
ArrayList<JMenuItem> aMenuItms = new ArrayList<JMenuItem>();
JMenuItem mntmRefresh = new JMenuItem("Refresh");
JMenuItem mntmNew = new JMenuItem("New");
JMenuItem mntmNormal = new JMenuItem("Normal");
JMenuItem mntmMax = new JMenuItem("Max");
JMenuItem mntmStatus = new JMenuItem("Status");
JMenuItem mntmFeedback = new JMenuItem("Send Feedback");
JMenuItem mntmEtsyTWebsite = new JMenuItem("EtsyT website");
JMenuItem mntmAbout = new JMenuItem("About");
aMenuItms.add(mntmRefresh);
aMenuItms.add(mntmNew);
aMenuItms.add(mntmNormal);
aMenuItms.add(mntmMax);
aMenuItms.add(mntmStatus);
aMenuItms.add(mntmFeedback);
aMenuItms.add(mntmEtsyTWebsite);
aMenuItms.add(mntmAbout);
then iterate over the arrayList at this stage adding a MouseListener using the for() loop:
for (Component c : aMenuItms) {
if (c instanceof JMenuItem) {
c.addMouseListener(ml);
}
}
Now set JMenu parents for the MenuBar:
// Now set JMenu parents on MenuBar
final JMenu mnFile = new JMenu("File");
menuBar.add(mnFile).setFont(menuFont);
final JMenu mnView = new JMenu("View");
menuBar.add(mnView).setFont(menuFont);
final JMenu mnHelp = new JMenu("Help");
menuBar.add(mnHelp).setFont(menuFont);
Then add the dropdown menuItems children to the JMenu parents:
// Now set menuItems as children of JMenu parents
mnFile.add(mntmRefresh).setFont(menuFont);
mnFile.add(mntmNew).setFont(menuFont);
mnView.add(mntmNormal).setFont(menuFont);
mnView.add(mntmMax).setFont(menuFont);
mnHelp.add(mntmStatus).setFont(menuFont);
mnHelp.add(mntmFeedback).setFont(menuFont);
mnHelp.add(mntmEtsyTWebsite).setFont(menuFont);
mnHelp.add(mntmAbout).setFont(menuFont);
Add the mouseListeners to the JMenu parents as a separate step:
for (Component c : menuBar.getComponents()) {
if (c instanceof JMenu) {
c.addMouseListener(ml);
}
}
Now that the child menuItem elements all have their own listeners that are separate to the parent JMenu elements and the MenuBar itself - It is important to identify the object type within the MouseListener() instantiation so that you get the menu auto opening on mouseover (in this example the 3x JMenu parents) BUT ALSO avoids child exception errors and allows clean identification of mouseOUT of the menu structure without trying to monitor where the mouse position is. The MouseListener is as follows:
MouseListener ml = new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
isMouseOut = true;
timerMenuClear();
}
public void mouseEntered(MouseEvent e) {
isMouseOut = false;
Object eSource = e.getSource();
if(eSource == mnHelp || eSource == mnView || eSource == mnFile){
((JMenu) eSource).doClick();
}
}
};
The above only simulates the mouse click into the JMenu 'parents' (3x in this example) as they are the triggers for the child menu dropdowns. The timerMenuClear() method calls on the MenuSelectionManager to empty whatever selectedpath point was live at the time of real mouseOUT:
public void timerMenuClear(){
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(isMouseOut == true){
System.out.println("Timer");
MenuSelectionManager.defaultManager().clearSelectedPath();
}
}
};
//Delay timer half a second to ensure real mouseOUT
Timer timer = new Timer(1000, task);
timer.setInitialDelay(500);
timer.setRepeats(false);
timer.start();
}
It took me a little testing, monitoring what values I could access within the JVM during its development - but it Works a treat! even with nested menus :) I hope many find this full example very useful.