Giving JMenuItem's name to it's ActionListener
Why aren't you calling setActionCommand
on the menuitem. Instead of using setName
, if you call setActionCommand
, you should get what you expect when you call getActionCommand
Also, its label, not lable.
Adding an ActionListener to JMenuItem
What it looks to me is you have
JMenuBar menuBar = new JMenuBar();
JMenu file = new JMenu("File");
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.exit(0);
}
});
JMenu headMenu = new JMenu("Heads");
outside of any method definition and there is no way to call that code.
Try this:
public class Main extends JFrame{
//initialize integer height/width values along with declaring
//Swing component variables
private final int W = 500,
H = 500;
private JMenu file, headMenu, bgMenu;
private JMenuBar menuBar;
private JMenuItem exitItem;
//constructor
public Main(){
setTitle("Move the Head");
setSize(W, H);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
initializeElements();
}
//Initializes the elements, this part is missing from your code above.
public void initializeElements(){
menuBar = new JMenuBar();
file = new JMenu("File");
exitItem = new JMenuItem("Exit");
exitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.exit(0);
}
});
headMenu = new JMenu("Heads");
bgMenu = new JMenu("Backgrounds");
}
public static void main( String[] args ) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Main f = new Main();
f.setVisible(true);
}
});
}
}
The ActionListener of the JMenuItem is not working
Remove the getParent
Method from PopUpMenu
public class PopUpMenu extends JPopupMenu {
private Container parent;
public PopUpMenu(MenuItem[] menuItems) {
super();
for (MenuItem item : menuItems) {
add(item);
}
}
public void setParent(Container parent) {
this.parent = parent;
parent.addMouseListener(new PopUpListener(this));
}
}
This method will override the getParent
defined in java.awt.Component.getParent()
. I guess this leads to the unexpected behavior.
EDIT
I'm overriding that method on purpose. But I still tried to remove it to see if that would fix the problem. Unfortunately, it did not.
You can override the method but you must ensure the Component.getParent
method's contract.
The PopUpMenu
is not a child of the container parent
. I mean that if the PopUpMenu
returns the container parent
the container should also know that the PopUpMenu
is it's child. E.g. Container.getCompnents()
should contain the PopUpMenu
. That's the contract.
But it will not help inyour situation since what don't really want to create a component parent/child relationship. You just want to hold a reference to some Object that you want to invoke some method.invoke(container);
.
This example is based on your code with the fix I suggessted above. I've put everything in one compilation unit to provide a MVCE:
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = createFrame();
MenuItem menuItem1 = new MenuItem("getForeground", "Foreground Color");
MenuItem menuItem2 = new MenuItem("getBackground", "Background Color");
PopUpMenu popUpMenu = new PopUpMenu(new MenuItem[] { menuItem1, menuItem2 });
popUpMenu.setParent(frame);
frame.setVisible(true);
}
private static JFrame createFrame() {
JFrame frame = new JFrame();
frame.setSize(1000, 800);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
return frame;
}
}
class PopUpMenu extends JPopupMenu {
private Container parent;
public PopUpMenu(MenuItem[] menuItems) {
super();
for (MenuItem item : menuItems) {
add(item);
}
}
public Container getParentComponent() {
// another name because I don't want to override getParent()
// Try to rename this method to getParent to see
// that it will not work
return parent;
}
public void setParent(Container parent) {
this.parent = parent;
parent.addMouseListener(new PopUpListener(this));
}
}
class MenuItemListener extends IListener {
protected void action(ActionEvent event) {
Object source = event.getSource();
if (source instanceof MenuItem) {
MenuItem item = (MenuItem) source;
Container parent = item.getParent();
if (parent instanceof PopUpMenu) {
PopUpMenu menu = (PopUpMenu) parent;
Container container = menu.getParentComponent();
try {
String name = item.getMethodName();
Method method = container.getClass().getMethod(name);
Object invoke = method.invoke(container);
JOptionPane.showMessageDialog(container, invoke);
} catch (Exception e) {
}
}
}
}
}
abstract class IListener implements ActionListener {
private boolean keyboardSensitive;
public IListener() {
setKeyboardSensitive(false);
}
@Override
public void actionPerformed(ActionEvent event) {
if ((event.getModifiers() != 0) || isKeyboardSensitive()) {
action(event);
}
}
protected abstract void action(ActionEvent event);
public boolean isKeyboardSensitive() {
return keyboardSensitive;
}
public void setKeyboardSensitive(boolean keyboardSensitive) {
this.keyboardSensitive = keyboardSensitive;
}
}
class MenuItem extends JMenuItem {
private String methodName;
public MenuItem(String methodName, String text) {
super(text);
setMethodName(methodName);
setFocusable(true);
addActionListener(new MenuItemListener());
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
}
class PopUpListener extends MouseAdapter {
private PopUpMenu menu;
public PopUpListener(PopUpMenu menu) {
setMenu(menu);
}
@Override
public void mousePressed(MouseEvent event) {
if (event.isPopupTrigger()) {
menu.show(event.getComponent(), event.getX(), event.getY());
}
}
public void mouseReleased(MouseEvent event) {
if (event.isPopupTrigger()) {
menu.show(event.getComponent(), event.getX(), event.getY());
}
}
public PopUpMenu getMenu() {
return menu;
}
public void setMenu(PopUpMenu menu) {
this.menu = menu;
}
}
Here is a refactored version of the same logic that doesn't need a lot of specialized (extended) classes like PopUPMenu
or MenuItem
.
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.reflect.*;
import java.text.MessageFormat;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = createFrame();
JMenuItem foregroundMenuItem = createMenuItem(frame, "getForeground", "Foreground Color");
JMenuItem backgroundMenuItem = createMenuItem(frame, "getBackground", "Background Color");
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(foregroundMenuItem);
popupMenu.add(backgroundMenuItem);
PopUpListener popUpListener = new PopUpListener(popupMenu);
frame.addMouseListener(popUpListener);
frame.setVisible(true);
}
private static JMenuItem createMenuItem(Object invocationTarget, String methodName, String actionName) {
MethodInvocationAction methodInvocationAction = new MethodInvocationAction(invocationTarget, methodName);
methodInvocationAction.putValue(Action.NAME, actionName);
JMenuItem menuItem = new JMenuItem(methodInvocationAction);
return menuItem;
}
private static JFrame createFrame() {
JFrame frame = new JFrame();
frame.setSize(1000, 800);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
return frame;
}
}
class MethodInvocationAction extends AbstractAction {
private Object targetObj;
private Method targetMethod;
private boolean keyboardSensitive;
public MethodInvocationAction(Object targetObj, String methodName) {
this.targetObj = targetObj;
try {
targetMethod = targetObj.getClass().getMethod(methodName);
} catch (NoSuchMethodException | SecurityException e) {
String msg = MessageFormat.format("{0} does not have a method named {1}", targetObj, methodName);
throw new RuntimeException(msg, e);
}
}
public boolean isKeyboardSensitive() {
return keyboardSensitive;
}
public void setKeyboardSensitive(boolean keyboardSensitive) {
this.keyboardSensitive = keyboardSensitive;
}
@Override
public void actionPerformed(ActionEvent event) {
if ((event.getModifiers() != 0) || isKeyboardSensitive()) {
performAction(event);
}
}
public void performAction(ActionEvent e) {
try {
Object invoke = targetMethod.invoke(targetObj);
JOptionPane.showMessageDialog(null, invoke);
} catch (Exception exception) {
showException(exception);
}
}
private void showException(Exception e1) {
StringWriter exceptionStackTraceWriter = new StringWriter();
e1.printStackTrace(new PrintWriter(exceptionStackTraceWriter));
String exceptionStackTrace = exceptionStackTraceWriter.toString();
JTextArea exceptionStackTraceTextComponent = new JTextArea();
exceptionStackTraceTextComponent.setText(exceptionStackTrace);
JScrollPane scrollPane = new JScrollPane(exceptionStackTraceTextComponent);
scrollPane.setPreferredSize(new Dimension(800, 600));
JOptionPane.showMessageDialog(null, scrollPane, e1.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE);
}
}
class PopUpListener extends MouseAdapter {
private JPopupMenu menu;
public PopUpListener(JPopupMenu menu) {
this.menu = menu;
}
public void mousePressed(MouseEvent event) {
handlePopupEvent(event);
}
public void mouseReleased(MouseEvent event) {
handlePopupEvent(event);
}
private void handlePopupEvent(MouseEvent event){
if (event.isPopupTrigger()) {
menu.show(event.getComponent(), event.getX(), event.getY());
}
}
}
Update JMenu display names
If I understand what exactly you want (a snapshot could have been useful), then you should use menu.setText("player1")
setName(string)
is not for display, see here.
How to create JButtons using JMenuItem and ActionListener
Implement a method to add a JButton in the ProgramDisplay class, e.g.
void addButton(String name, String employeeID, String rateOfPay, String hoursWorked) {
add(new JButton(name + ":" + employeeID + ", " + rateOfPay + " - " + hoursWorked); }
pass the ProgramDisplay instance as final parameter to the NewListener, e. g.
private class NewListener extends JFrame implements ActionListener {
final ProgramDisplay pd;
NewListener(ProgramDisplay pd) {
this.pd = pd;
}
.....
and call the addButton method from within your ActionPerformed method:
Apply.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
name = nameField.getText();
employeeID = IDField.getText();
rateOfPay = payRateField.getText();
hoursWorked = hoursField.getText();
setVisible(false);
NewListener.this.pd.addButton(name, employeeID, rateOfPay, hoursWorked);
}
});
How to change a menuItem tool tip from its own action listener?
not sure what happened, there must be another issue in your code, but everything could be .... only speculations, my SSCCE
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class ActionExample {
private boolean testCondition = false;
private JMenuItem DeleteTask = new JMenuItem("Delete Task");
public ActionExample() {
Action sample = new SampleAction();
DeleteTask.setMnemonic(KeyEvent.VK_D);
DeleteTask.setToolTipText("Delete a Task");
DeleteTask.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (testCondition) {
testCondition = false;
DeleteTask.setToolTipText("Changed Tool Tip");
} else {
testCondition = true;
DeleteTask.setToolTipText("Delete a Task");
}
}
});
JMenu menu = new JMenu("Menu");
menu.setMnemonic(KeyEvent.VK_M);
menu.add(sample);
menu.add(DeleteTask);
menu.addMenuListener(new SampleMenuListener());
JToolBar tb = new JToolBar();
tb.add(sample);
JTextField field = new JTextField(10);
field.setAction(sample);
JFrame f = new JFrame("ActionExample");
JMenuBar mb = new JMenuBar();
mb.add(menu);
f.setJMenuBar(mb);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(tb, BorderLayout.NORTH);
f.getContentPane().add(field, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ActionExample actionExample = new ActionExample();
}
});
}
}
class SampleMenuListener implements MenuListener {
@Override
public void menuSelected(MenuEvent e) {
System.out.println("menuSelected");
}
@Override
public void menuDeselected(MenuEvent e) {
System.out.println("menuDeselected");
}
@Override
public void menuCanceled(MenuEvent e) {
System.out.println("menuCanceled");
}
}
class SampleAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public SampleAction() {
super("Sample");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt S"));
putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_S));
putValue(SHORT_DESCRIPTION, "Just a sample action");
}
@Override
public void actionPerformed(ActionEvent evt) {
System.out.println("sample...");
}
}
Related Topics
How to Get Eclipse to Use a Different Compiler Version for Java
What Is Difference Between Collection.Stream().Foreach() and Collection.Foreach()
Javafx - Border Radius <-> Background Color
Android Studio - No Jvm Installation Found
Java.Lang.Runtimeexception: Takepicture Failed
Android: Textview Automatically Truncate and Replace Last 3 Char of String
How to Properly Use Backwards Compatible Vector Drawable with the Latest Android Support Library
Create a Bitmap/Drawable from File Path
Android - Prevent White Screen at Startup
Listening for Input Without Focus in Java
When Should We Use Observer and Observable
How to Use Jsp/Jstl to Generate Dynamic CSS/JavaScript Files
How to Disable Sslv3 in Android for Httpsurlconnection
Android: Switch Camera When Button Clicked