I want to create a Toolbar in my application. If you click a button on that toolbar, it will pop up a menu, just like in Eclipse's toolbar. I don't know how to do this in Swing. Can someone help me please? I've tried Google but found nothing.
This is way harder in Swing than it needs to be. So instead of pointing you to tutorials I've created a fully working example.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class ToolbarDemo {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(600, 400));
final JToolBar toolBar = new JToolBar();
//Create the popup menu.
final JPopupMenu popup = new JPopupMenu();
popup.add(new JMenuItem(new AbstractAction("Option 1") {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "Option 1 selected");
}
}));
popup.add(new JMenuItem(new AbstractAction("Option 2") {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "Option 2 selected");
}
}));
final JButton button = new JButton("Options");
button.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
});
toolBar.add(button);
frame.getContentPane().add(toolBar, BorderLayout.NORTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
I don't see why this is harder than it needs to be or why you should use a MouseListener. The solution by Steve McLeod works, but where the menu appears depends on where the mouse was clicked. Why not just use an ActionListener as normally used for a JButton. It seems neither harder nor less hard.
final JPopupMenu menu = new JPopupMenu();
menu.add(...whatever...);
final JButton button = new JButton();
button.setText("My Menu");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
menu.show(button, button.getBounds().x, button.getBounds().y
+ button.getBounds().height);
}
});
This positions the menu about the same as a menu in a JMenuBar for me, and the position is consistent. You could place it differently by modifying the x and y in menu.show().
Here is a simple and nice class
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class MenuButton extends JToggleButton {
JPopupMenu popup;
public MenuButton(String name, JPopupMenu menu) {
super(name);
this.popup = menu;
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ev) {
JToggleButton b = MenuButton.this;
if (b.isSelected()) {
popup.show(b, 0, b.getBounds().height);
} else {
popup.setVisible(false);
}
}
});
popup.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
MenuButton.this.setSelected(false);
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {}
});
}
}
I think it's the same as in AWT.
You should put an ActionCommand on that button and when it's executed show the pop-up menu according to the mouse coordinates.
See the section Bringing Up a Popup Menu, in How to Use Menus.
I'm not sure I understand you correctly but if you want to know how to make toolbars in Swing check this
Java Tutorials: How to Use Tool Bars and this
Java Tutorials: How to Use Actions
Above, Adam Goode asked,
Does your solution have the behavior where if you click the button again with the menu up, it pops up the menu again, instead of dismissing it?
This turned out to be a testing task. I finally solved it with an invokeLater to re-vanish the popup in that particular case. My solution also allows the client to tailor the button and the popup menu.
/**
* A button that will popup a menu.
* The button itself is a JLabel and can be adjusted with all
* label attributes. The popup menu is returned by getPopup;
* menu items must be added to it.
* <p>
* Clicks outside the menu will dismiss it.
*/
public class MenuButton extends JLabel
implements MouseListener, PopupMenuListener {
JPopupMenu popMenu;
#SuppressWarnings("")
public MenuButton() {
super();
popMenu = new JPopupMenu();
addMouseListener(this);
popMenu.addPopupMenuListener(this);
}
public JPopupMenu getPopup() { return popMenu; }
#Override
public void mousePressed(MouseEvent e) {
if ( ! popMenu.isShowing()) {
popMenu.show(this, 0, getBounds().height);
}
}
#Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(()->{
if (popMenu.isShowing()) {
// if shpwing, it was hidden and reshown
// by a mouse down in the 'this' button
popMenu.setVisible(false);
}
});
}
#Override public void mouseClicked(MouseEvent e) { }
#Override public void mouseReleased(MouseEvent e) { }
#Override public void mouseEntered(MouseEvent e) { }
#Override public void mouseExited(MouseEvent e) { }
#Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
#Override public void popupMenuCanceled(PopupMenuEvent e) { }
} // end MenuButton
Sample invocation
MenuButton button = new MenuButton();
JPopupMenu menu = button.getPopup();
menu.add("Browse Sample");
menu.add("Save As ...");
Icon hamburger = IOUtils.loadIconResource(
IndexGofer.class, "images/hamburgerMenu.png");
(IOUtils is on page http://physpics.com/Java/tools/
You should use your own tool to load an icon.)
button.setIcon(hamburger);
button.setOpaque(false);
Related
This is my first question and I'm realy sorry for my English. I don't want to navigation in JComboBox's dropdown list show the selected item in the "JComboBox's main field" (sorry, don't know how to call it, see the images).
This is what happen when I navigate in list:
But I want something like this:
and when I press Enter or clicked on item, it appear in the main field.
Here is my code:
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.*;
public class ComboTest {
JFrame frame;
JPanel panel;
String[] choices = new String[]{
"Java",
"Python",
"C++",
"PHP",
"Perl"
};
JComboBox<String> comboBox = new JComboBox<>(choices);
JTextComponent textComponent;
public static void main(String[] args){
new ComboTest();
}
public ComboTest() {
frame = new JFrame();
panel = new JPanel();
textComponent = (JTextComponent) comboBox.getEditor().getEditorComponent();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 150);
frame.setResizable(false);
panel.setLayout(new FlowLayout());
comboBox.setEditable(true);
comboBox.setSelectedItem(null);
panel.add(comboBox);
frame.add(panel);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Try this code block
comboBox.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
//when Popupmenu is visible, remove the combobox editor text
comboBox.getEditor().setItem(null);
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
Thanks to zilk. Your answer helped me to solve this. The listener addPopupMenuListener doesn't work for me. But when I changed the addPopupMenuListener to addItemListener, everything worked fine.
comboBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(final ItemEvent itemEvent) {
comboBox.getEditor().setItem(null);
comboBox.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
if(e.getKeyCode() == KeyEvent.VK_ENTER)
{
comboBox.getEditor().setItem(itemEvent.getItem());
}
}
});
}
});
I have a problem with the focus listener implemented by CustomTextField class. The focus listener is only called when another Swing component is getting the focus. But If I move the JFrame istelf by dragging it with the mouse, the focusLost() method is never called (in other words, it doesn´t seem that the focus is shifting from CustomTextField to JFrame).
EDIT: The solution of my question is below:
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
public class ScrollFocus extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ScrollFocus();
}
});
}
public ScrollFocus() {
this.setLayout(new BorderLayout());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Vector<String> values = new Vector<>();
values.add("a");
values.add("b");
values.add("c");
values.add("d");
values.add("e");
JComboBox<String> comboBox = new JComboBox<>(values);
JScrollPane scrollPane = new JScrollPane(comboBox);
this.add(scrollPane, BorderLayout.NORTH);
CustomTextField customTextField = new CustomTextField();
this.add(customTextField, BorderLayout.CENTER);
JButton button = new JButton("press");
final JPopupMenu menu = new JPopupMenu("Menu");
menu.add(new JMenuItem("Test"));
button.setComponentPopupMenu(menu);
this.add(button, BorderLayout.SOUTH);
pack();
setVisible(true);
}
class CustomTextField extends JTextField implements FocusListener {
private CustomPopup customPopup = new CustomPopup();
public CustomTextField() {
this.addFocusListener(this);
this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "VK_UP");
this.getActionMap().put("VK_UP", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
setPopupSize();
customPopup.show(CustomTextField.this, CustomTextField.this.getX(), CustomTextField.this.getY() + CustomTextField.this.getHeight());
customPopup.setSelectedIndex(0);
}
});
this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "VK_DOWN");
this.getActionMap().put("VK_DOWN", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
setPopupSize();
customPopup.show(CustomTextField.this, CustomTextField.this.getX(), CustomTextField.this.getY() + CustomTextField.this.getHeight());
customPopup.setSelectedIndex(0);
}
});
}
public void setPopupSize() {
customPopup.setPopupSize(new Dimension(this.getWidth(), 110));
}
#Override
public void focusGained(FocusEvent e) {
}
#Override
public void focusLost(FocusEvent e) {
}
class CustomPopup extends JPopupMenu {
String[] values = new String[]{"Value1", "Value2", "Value3", "Value4", "Value5", "Value6", "Value7",
"Value8","Value9", "Value10", "Value11", "Value12", "Value13", "Value14", "Value15", "Value16",};
JList<String> list = new JList<>(values);
JScrollPane scrollPane = new JScrollPane(list);
public int index = 0;
public CustomPopup() {
this.setLayout(new GridLayout(0,1));
this.add(scrollPane);
this.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){
if(customPopup.index > 0)
customPopup.setSelectedIndex(--customPopup.index);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN){
if(customPopup.index < customPopup.getListSize()-1)
customPopup.setSelectedIndex(++customPopup.index);
}
}
});
this.addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
index=0;
}
});
pack();
}
public void setSelectedIndex(int index) {
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
requestFocus();
}
public int getListSize() {
return values.length;
}
}
}
}
//customPopup.setVisible(true);
customPopup.show((JComponent)e.getSource(), 0, 20);
You should be using the show(...) method to show the popup. This must add some listeners to the popup so you will no longer need the FocusListener on the text field.
However, now this is a different problem. The text field loses focus so the Action never get invoked. That would be ok, but the JList never gains focus so it doesn't respond to the up/down keys unless you click on the list box first. I'm not sure what the problem is here.
Maybe you can try to make the popup, scrollpane and list all non-focusable so that focus remains on the text field?
'Focus', which is admittedly a slightly ambiguous term, generally applies to a component, not to an entire window. We think of the "window with focus", but I think what we really mean is "the current window, the one which contains the focus." I would not expect focus_lost to be called if I moved the window (aka JFrame) itself.
Another way to think of it; if I had a text field, clicked in it, and typed a letter or two, I would see those letters in that text field. If I then moved the window slightly and typed another letter or two, I would still expect those letters to appear in that field. It still has focus, and never lost it.
I need to display a swing popup with my custom component. The popup should stay visible, until I hide it myself, but shouldn't get focus.
I have a code written by some other developer that does it in the following way:
popupMenu = new JPopupMenu();
popupMenu.add(myCustomComponent, BorderLayout.CENTER);
popupMenu.setFocusable(false);
popupMenu.setVisible(true);
popupMenu.show(parentComponent, x, y);
This seems to work, but has a bug - when the popup is visible, first mouse click outside the component is consumed by the popup. So I need to click twice to set focus to another component.
How can I fix it? Or what is correct way to make the popup?
UPDATE
At last I've managed to reproduce my problem in short code fragment. Thanks to Guillaume Polet for giving me a starting point.
Here's the code:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class TestJPopup {
protected void initUI() {
JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextField textField = new JTextField("Some text field");
frame.add(textField, BorderLayout.WEST);
final JButton buttonToHit = new JButton("Hit me");
buttonToHit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
}
});
frame.add(buttonToHit);
frame.setSize(200, 100);
frame.setVisible(true);
final JPopupMenu popup = new JPopupMenu();
popup.add(new JLabel("<html>Hey!<br>I'm the popup window!</html>"),
BorderLayout.NORTH);
popup.setFocusable(false);
popup.setVisible(true);
popup.show(textField, 60, 60);
// I want to activate popup when user clicks in the text field
textField.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (popup != null) {
popup.show(textField, 60, 60);
}
}
});
}
public static void main(String[] args) throws Exception {
Class lnfClass = Class.forName("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", true,
Thread.currentThread().getContextClassLoader());
LookAndFeel feel = (LookAndFeel) lnfClass.newInstance();
UIManager.setLookAndFeel(feel);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestJPopup().initUI();
}
});
}
}
Two critical moments:
Windows look and feel used (with default not reproducible)
Mouse listener attached to text field in main frame
Not an answer, but just an example SSCCE in which I can't currently reproduce the behaviour you described. Maybe start from this code, try to reproduce the error and the edit your post with modified non-working code.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestJPopup {
protected void initUI() {
JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel leftLabel = new JLabel("Left");
frame.add(leftLabel, BorderLayout.WEST);
final JButton buttonToHit = new JButton("Hit me");
buttonToHit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
}
});
frame.add(buttonToHit);
frame.setSize(500, 400);
frame.setVisible(true);
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(new JLabel("<html>A Custom<br>component<br>made to<br> simulate <br>your custom component</html>"),
BorderLayout.NORTH);
JTextField textfield = new JTextField(30);
popupMenu.add(textfield);
popupMenu.setFocusable(false);
popupMenu.setVisible(true);
popupMenu.show(leftLabel, 20, 20);
// Let's force the focus to be in a component in the popupMenu
textfield.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestJPopup().initUI();
}
});
}
}
Not a solution, but:
Looks like a bug to me, even a plain componentPopup exhibits the same mis-behaviour (in winLAF and Nimbus, not in Metal):
JTextField field = new JTextField("some popup owner");
JPopupMenu menu = new JPopupMenu();
menu.add("dummy");
field.setComponentPopupMenu(menu);
Action action = new AbstractAction("hit me!") {
#Override
public void actionPerformed(ActionEvent e) {
LOG.info("got hit!");
}
};
JComponent content = new JPanel();
content.add(new JButton(action));
content.add(field);
for quick research and/or for future readers,
this issue is reproducible and presented for,
a) JPopup
b) JMenu
tested on jdk1.6.0_25 and jdk1.7.0_04,
same issue on WinXp and Win7,
for Look and Feel to SystemLookAndFeel / WindowsLookAndFeel,
Here's a possible workaround with JWindow instead of JPopupMenu, that was proposed by mKorbel in comments:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestJPopup {
protected void initUI() {
final JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextField textField = new JTextField("Some text field");
frame.add(textField, BorderLayout.WEST);
final JButton buttonToHit = new JButton("Hit me");
buttonToHit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
}
});
frame.add(buttonToHit);
frame.setSize(200, 70);
frame.setVisible(true);
final JWindow popup = new JWindow();
popup.getContentPane().add(new JLabel("<html>Hey!<br>I'm the popup window!</html>"),
BorderLayout.NORTH);
popup.setLocation(frame.getLocation().x + 60, frame.getLocation().y + 60);
popup.pack();
popup.setFocusable(false);
popup.setVisible(true);
// I want to activate popup when user clicks in the text field
textField.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
if (popup != null) {
popup.setVisible(true);
popup.setLocation(frame.getLocation().x + 60, frame.getLocation().y + 60);
popup.toFront();
}
}
});
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
if (popup != null) {
popup.setVisible(false);
}
}
});
}
public static void main(String[] args) throws Exception {
Class lnfClass = Class.forName("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", true,
Thread.currentThread().getContextClassLoader());
LookAndFeel feel = (LookAndFeel) lnfClass.newInstance();
UIManager.setLookAndFeel(feel);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestJPopup().initUI();
}
});
}
}
Here is the magic line that fixes the problem:
UIManager.put("PopupMenu.consumeEventOnClose", Boolean.FALSE);
I found this after looking into the source code for the BasicPopupMenuUI class. Apparently this behaviour is a deliberate design choice according to the following comments in the code, but it sure feels like a bug to me.
// Ask UIManager about should we consume event that closes
// popup. This made to match native apps behaviour.
By the way, it happens in Java 5 and 6 too.
In my Java swing application i have noticed that when i click on a disabled JMenuItem in a JPopupMenu it hides the menu, but i i do not want to hide it, as if nothing is clicked. Is there a way to prevent this ?
-----------------------------------> Update: Added Code sample :
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." );
}
This has been tested and works.
The Look & Feel decides how to handle the mouse events on disabled menu items. Anyway, you can intercept the undesired events by using a custom MenuItem. Simply use that 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);
}
}
First, adapt the code to suit your needs (optional).
Finally, replace any JMenuItem with a CustomMenuItem.
That's it!
not sure how to prevent. but you can setVisible(false) to prevent it being displayed. Also if a user clicks on the disable menu no action will take place.
When you are disabling JMenuItem, you should remove the ActionListener associated with that JMenuItem by using
jMenuItem.removeActionListener() method.
If u remove that that action will not call the listener and popup will not be disappeared.
I hope this will help to achieve your target.
did you gave a try at this method:
http://download.oracle.com/javase/6/docs/api/javax/swing/JMenuItem.html#setArmed%28boolean%29
"arm the menu item so it can be selected", which I guess would do the trick if set to false.
In short, you can do this, but you will have to write your own mouse listener, which may require a lot of copy&paste from the jdk source code, which is not a very good idea, and I'm not sure about what license restrictions it will put on your code.
I would start digging from this method:
javax.swing.plaf.basic.BasicMenuItemUI.Handler#mouseReleased
which seems to be the entry point from where the menu handling mechanism hides the popup. I would take a closer look at
javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber#stateChanged
EDIT Developing answer by #Burhan Valikarimwala, try this apporach: remove all action listeners from the disabled JMenuItem and store them in some static temp structure (let's say a Map<WeakReference<JMenuItem>, List<MouseListener>>), this way it will not hide the popup. When you make the menu item enabled again, add all the listeners back. Make it into some util method and it will be seamless.
The only solution I could come up with, for your problem of a click on disable JMenuItem causing it to hide 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 the hiding happens when your release is inside the bounds of the JMenuItem, therefore we are checking if it is disabled then we show popup again. As by this time it is already decided that it will be hidden. I was trying calling super.mouseRelease with a different MouseEvent pointing outside component and consuming the previous one but it helps nothing.
Anyway this solution works.
Enjoy, Boro
I think in Java7 this has been fixed.
I have a bunch of JLabels and i would like to trap mouse click events. at the moment i am having to use:
public void mouseClicked(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mouseEntered(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
}
public void mouseReleased(MouseEvent arg0) {
System.out.println("Welcome to Java Programming!");
}
I was wondering if there is a tidier way of doing this instead of having a bunch of events I do not wish trap?
EDIT:
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent event) {
System.out.println(event.getComponent());
}
}
the above works but netBeans says add #override anotation. what does this mean?
EDIT: ok got it. fixed and solved.
Use MouseAdapter()
An abstract adapter class for receiving mouse events. The methods in this class are empty. This class exists as convenience for creating listener objects.
So you need to implement only the method you like such as following example:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass extends JPanel {
public MainClass() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
System.out.println(me);
}
});
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new MainClass());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
One could use a MouseAdapter class, which implements the MouseListener interface, so one does not need to implement all the methods.
However, by overriding the methods of interest, one can get the desired behavior. For example, if one overrides the mouseClicked method, then one can define some behavior for the mouse click event.
For example (untested code):
JLabel label = new JLabel("Hello");
label.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
System.out.println("Clicked!");
}
});
In the code above, the JLabel will print "Clicked!" to the console upon being clicked on.
You can extend MouseAdapter instead, and just override the events you're really interested in.
You can inherit from java.awt.event.MouseAdapter and only override the methods for the event(s) you are interested in.
some example of mouse event clicked,
in the same way you can use mousePressed or other mouse events
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Work1 extends JFrame{
private JPanel panelNew;
public Work1(){
super("Work 1");
// create Panel
panelNew = new JPanel();
panelNew.setLayout(null);
panelNew.setBackground(Color.cyan );
add(panelNew);
// create Button
JButton btn = new JButton("click me");
// position and size of a button
btn.setBounds(100, 50, 150, 30);
panelNew.add(btn);
// add event to button
btn.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
// change text of button after click
if (btn.getText() == "abraCadabra"){
btn.setText("click me again") ;
}
else btn.setText("abraCadabra");
}
});
}
public static void main(String[] args){
Work1 go1 = new Work1();
go1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go1.setSize(320,200);
go1.setVisible(true);
}
}