0

I am pretty new to Swing, any help appreciated. I have the following situation: A "Main" Class where I define my main JPanel and default Label text. A "GUILabel" Class (extends JLabel) where I define the look of the Text Labels. A "popupmenu" Class (extends JPopupMenu) where I define the content of the popupmenu.

Target: When I right-click on a panel the popupMenu should appear (this already works). When I choose a menu item of this popupMenu, the text of the label I clicked on should change.

I guess its currently not working (I am sorry this code isn't complete - this is my 5th attempt), because I create the popup menu Once in the Main Class. Then I am adding this popup menu to each Label. So I guess thats why getInvoker() returns null in the popup menu class.

But do I really have to create a new popupmenu for each JLabel? Cant this single menu just handle all Components assigned to?

Main Frame:

package popupshit;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.border.BevelBorder;

public class Model implements ActionListener {

   public static void main(String[] args) {
      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setLayout(new GridLayout(0, 3));
      frame.setVisible(true);

      GUIPopupMenu popup = new GUIPopupMenu(9);

      JLabel label1 = new GUILabel();
      label1.setComponentPopupMenu(popup);

      JLabel label2 = new GUILabel();
      label2.setComponentPopupMenu(popup);

      JLabel label3 = new GUILabel();
      label3.setComponentPopupMenu(popup);

      frame.add(label1);
      frame.add(label2);
      frame.add(label3);

      frame.pack();
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      ((JLabel) e.getSource()).setText("" + e.getActionCommand());
    }

}

PopupMenu:

package popupshit;

import java.awt.event.ActionListener;

import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

public class GUIPopupMenu extends JPopupMenu {

   public GUIPopupMenu(int numbers) {

      for (int i = 1; i < numbers; i++) {
         JMenuItem popMenuItem = new JMenuItem("" + i);
         popMenuItem.addActionListener ((ActionListener) this.getInvoker());
         System.out.println(this.getParent());
         this.add(new JMenuItem("" + i));
      }
      this.addSeparator();
      this.add(new JMenuItem("remove"));
   }
}

GUILabel:

    package popupshit;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.border.BevelBorder;

import javax.swing.border.BevelBorder;

public class GUILabel extends JLabel implements ActionListener {

   public GUILabel() {
      this.setBorder(new BevelBorder(BevelBorder.LOWERED));
      this.setVisible(true);
      this.setPreferredSize(new Dimension(50, 50));
      this.setText("0");
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      this.setText((String) e.getActionCommand());
      JOptionPane.showMessageDialog(null, "worked!" );
   }
}
user3238620
  • 33
  • 1
  • 5

2 Answers2

1

invoker is null because until the popup menu is a actually invoked, it has no invoker.

Instead, add a simple ActionListener to the menu item which, when invoked, uses the invoker property to determine which should occur.

My personal preference would be to create a new instance of the popup menu for each component separately, passing a reference of the component in question or some other controller as required...but that's me...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

Add an ActionListener to the menu item something like:

@Override
public void actionPerformed(ActionEvent e)
{
    Component c = (Component)e.getSource();
    JPopupMenu popup = (JPopupMenu)c.getParent();
    JLabel label = (JLabel)popup.getInvoker();
    ...
}

Don't extend JPopupMenu just to add a few menu items to the popup.

camickr
  • 321,443
  • 19
  • 166
  • 288