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
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'm creating a simple sticky note app. I want to make a JPopupMenu to show when ever I click on the JTextArea . Because it's a sticky note so obviously the whole app will be a textArea
Short Code:
//I've tried my best to follow SSCE
private JTextArea textArea = new JTextArea();
private JPopupMenu popup = new JPopupMenu("Popup Menu");
private JMenuItem hideBar = new JMenuItem("Hide Bar");
private JMenuItem hideTitle = new JMenuItem("Hide Item");
public mySticky(){
add(textArea); //Text Area is using the whole Frame "Sticky Note"
popup.add(hideBar); //adding MenuItem
popup.add(hideTitle); //adding MenuItem
//addMouseListener(new popupTriggerListener());
textArea.addMouseListener(new popupTriggerListener());
}
private class popupTriggerListener extends MouseAdapter{
public void MousePressed(MouseEvent e){
if(e.isPopupTrigger())
popup.show(textArea,e.getX(),e.getY()); //I've added texArea I'm not sure what to add inside.
}
public void MouseReleased(MouseEvent e){
if(e.isPopupTrigger())
popup.show(textArea,e.getX(),e.getY()); //I've added texArea I'm not sure what to add inside.
}
public void MouseClicked(MouseEvent e){
}
}
I've tried my best to follow SSCE
How can this possibly be a SSCCE given that the code doesn't even compile? Try reading the link again.
I suggest you start by read the section from the Swing tutorial on Bringing Up a Popup Menu for a working example.
hmmm I'm missing something here
You are missing the #Override statement which should preceed the method signature when you override a method. This will prevent you from making typing mistakes.
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
I've created a drop-down menu on my Swing JToolBar. But it doesn't create behave the way I want. I'm aiming for it to work like Firefox's "Smart Bookmarks" button.
It disappears when the user selects a menu item: CORRECT!
It disappears when the user presses ESC: CORRECT!
It disappears when the user clicks somewhere in the main frame outside of the menu: CORRECT!
But it doesn't disappear when the user clicks a second time on the button that shows the drop-down menu: INCORRECT... :-(
My question is how can I add this behaviour, that it does disappear when the clicks on the button that shows the menu a second time.
Here's my current code, from Java 6 on the Mac:
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
public class ScratchSpace {
public static void main(String[] arguments) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Toolbar with Popup Menu demo");
final JToolBar toolBar = new JToolBar();
toolBar.add(createMoreButton());
final JPanel panel = new JPanel(new BorderLayout());
panel.add(toolBar, BorderLayout.NORTH);
panel.setPreferredSize(new Dimension(600, 400));
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private static AbstractButton createMoreButton() {
final JToggleButton moreButton = new JToggleButton("More...");
moreButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
createAndShowMenu((JComponent) e.getSource(), moreButton);
}
}
});
moreButton.setFocusable(false);
moreButton.setHorizontalTextPosition(SwingConstants.LEADING);
return moreButton;
}
private static void createAndShowMenu(final JComponent component, final AbstractButton moreButton) {
JPopupMenu menu = new JPopupMenu();
menu.add(new JMenuItem("Black"));
menu.add(new JMenuItem("Red"));
menu.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
moreButton.setSelected(false);
}
public void popupMenuCanceled(PopupMenuEvent e) {
moreButton.setSelected(false);
}
});
menu.show(component, 0, component.getHeight());
}
}
Well, here is a potential solution that is not without it's drawbacks. Only you can decide if this is acceptable for your application. The issue is that the popup closing occurs before other mouse-handling events are fired so clicking on your More.. button again causes the popup to hide, thus resetting the buttons state to deselected BEFORE the button even gets told it was pressed.
The easy workaround is to add the following call within your main program:
UIManager.put("PopupMenu.consumeEventOnClose", Boolean.TRUE);
The result of this is that whenever a popup menu is closed because of a mouse-pressed event, that mouse event will be consumed at the time the menu is closed and won't be passed on to any other components under the mouse. If you can live with limitation, this is an easy solution.
What's happening is that when you click off the menu, it cancels the popup menu, so you deselect the button, but the next immediate event is clicking the button, and now its deselected so it shows the menu again.
I don't have the exact solution yet, but give me a little bit ...
I don't use Firefox so I don't know what the Smart Bookmarks button looks like, but maybe use a JMenu as the "button". You could try using the Border of a JButton to make it look more like a button.
Well, the listener on the button reacts only when it is pushed down, because you listen for ItemEvent.SELECTED events only. How about adding another if clause to listen for ItemEvent.DESELECTED events here:
moreButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
createAndShowMenu((JComponent) e.getSource(), moreButton);
}
}
});
You could either store a reference to the menu somewhere, or you could make the menu itself add another listener to the button. The latter solution could be more straightforward, since you already seem to send a button reference to the menu.