0

I have a JFrame containing a JTabbedPane containing a JPanel in a Tab. In this JPanel, I want a JPopupMenu to show at Mouse Position when clicking the right mouse button. To do this, I use the show(invoker, x, y) method. My Problem: The JPopupMenu has a very strange behaviour; sometimes it displays without containing everything (just a grey box) and sometimes it displays in the top left corner of the Panel, behaving completely as expected.

Code:

import javax.swing.JFrame;
import javax.swing.JTabbedPane;

class Testframe extends JFrame {
    public static JFrame frame;

    private static final long serialVersionUID = 1L;    

    public Testframe(String string) {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setTitle(string);
        setSize(200,200);
        setVisible(true);
    }

    public static void main(String[] args) {
        frame = new Testframe("Title");
        JTabbedPane tabpane = new JTabbedPane(JTabbedPane.TOP);
        tabpane.addTab("title", new TestPanel());
        frame.add(tabpane);
        tabpane.setVisible(true);
    }
}

import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;


public class TestPanel extends JPanel implements MouseListener {
    private static final long serialVersionUID = 1L;

    JPopupMenu activeDropdown;

    TestPanel() {
        setBackground(Color.GREEN);
        setVisible(true);
        addMouseListener(this);
    }

    private void dropdown(MouseEvent e) {
        activeDropdown = new JPopupMenu();
        JMenuItem item = new JMenuItem("Eintrag 0");
        activeDropdown.add(item);
        activeDropdown.show(Testframe.frame, e.getX(), e.getY());
        this.add(activeDropdown);
    }

    @Override
    public void mouseClicked(MouseEvent e) {

        if(SwingUtilities.isRightMouseButton(e)) {
            if (activeDropdown != null)
                this.remove(activeDropdown);
            dropdown(e);
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) {}

}

If I try to put the JTabbedPane into a separate Class, the JPopupMenu appears anywhere (seems to be a fixed position) on the screen, completely independent from the window position.

0x6C38
  • 6,796
  • 4
  • 35
  • 47

2 Answers2

1

Change your dropdown method as below. That should work as expected.

 private void dropdown(MouseEvent e) {
    activeDropdown = new JPopupMenu();
    JMenuItem item = new JMenuItem("Eintrag 0");
    activeDropdown.add(item);

    this.add(activeDropdown);
    activeDropdown.show(this, e.getX(), e.getY());
 }

However, I don't understand why you are removing the existing JPopMenu and adding a new one on every right-mouse click.

Mubin
  • 4,192
  • 3
  • 26
  • 45
  • Wow, thanks, it works just fine. However, the Menu seems to have a little offset in position from the mouse click position, is there a way to fix that without manually reverting the offset by some pixels? – SimplyMe Jun 16 '13 at 15:09
  • By the way, I want to populate the menu dependent from the mouse position, that's why I need a new Menu on any right click. – SimplyMe Jun 16 '13 at 15:11
  • I ran the program and didn't see any offset in the position from mouse click position. Also, if you want to modify the items in `JPopMenu` then you don't have to drop and recreate it. Instead use `remove` and `add` methods on `activeDropdown`. That should suffice. Also, don't forget to accept any answer that resolves your problem on SO :-) – Mubin Jun 16 '13 at 15:14
  • Hm, yeah, I didn't thought about it that way yet ... Sounds more efficient and comfortable, indeed. – SimplyMe Jun 16 '13 at 15:19
  • The offset didn't appear in my real Project, it only happens in the test code, so there's no need to fix it ... :D – SimplyMe Jun 16 '13 at 15:20
1

You can simply use JComponent.setComponentPopupMenu to handle righ-click popup-menus. This is much simpler and will handle all the wiring code for you.

Small example with your code:

import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;

public class TestPanel extends JPanel {
    private static final long serialVersionUID = 1L;

    JPopupMenu activeDropdown;

    TestPanel() {
        setBackground(Color.GREEN);
        activeDropdown = new JPopupMenu();
        JMenuItem item = new JMenuItem("Eintrag 0");
        activeDropdown.add(item);
        setComponentPopupMenu(activeDropdown);
    }

    protected void initUI() {
        JFrame frame = new JFrame("Title");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTabbedPane tabpane = new JTabbedPane(JTabbedPane.TOP);
        tabpane.addTab("title", this);
        frame.add(tabpane);
        frame.setSize(200, 200);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestPanel().initUI();
            }
        });
    }
}

NB: Avoid using static variables!

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117