java - JPopupMenu 没有显示在屏幕上?

标签 java swing awt jmenuitem jpopupmenu

因此,对于我的学校项目,我正在创建一个类图制作器。我已经完成了 95%,我所需要的就是让 Jpopup 菜单出现。在核心中我有 3 个文件。扩展 JFrame 的 ApplicationModel、扩展 JPanel 的 ClassDiagram 和使矩形(如图中)出现的 ClassModel。渲染的核心是 Rectangle 对象,中间和底部矩形内的文本被另一个不可见的矩形包围,该矩形可右键单击。

This is what the program looks like (Minus the paint editting) 现在处理点击的文件是DiagramMouseListener,下面是它的代码。

package edu.mville.cs.classdiagram;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

public class DiagramMouseListener extends MouseAdapter
{
    ClassDiagram diagram;
    Field field;
    Method method;
    int x;
    int y;
    ClassModel elementBeingDragged;

    JPopupMenu fieldPopupMenu = new JPopupMenu();
    JPopupMenu methodPopupMenu = new JPopupMenu();

    JMenuItem editFieldNameItem;
    JMenuItem createFieldItem;
    JMenuItem deleteFieldItem;

    JMenuItem editMethodNameItem;
    JMenuItem createMethodItem;
    JMenuItem deleteMethodItem;

    public DiagramMouseListener(ClassDiagram diagram) { this.diagram = diagram; }

    public void addPopupMenu()
    {
        editFieldNameItem = new JMenuItem("Edit Field Name");
        createFieldItem = new JMenuItem("New Field");
        deleteFieldItem = new JMenuItem("Delete Field");

        editMethodNameItem = new JMenuItem("Edit Method Name");
        createMethodItem = new JMenuItem("New Method");
        deleteMethodItem = new JMenuItem("Delete Method");

        methodPopupMenu.add(editMethodNameItem);
        methodPopupMenu.add(createMethodItem);
        methodPopupMenu.add(deleteMethodItem);

        fieldPopupMenu.add(editFieldNameItem);
        fieldPopupMenu.add(createFieldItem);
        fieldPopupMenu.add(deleteFieldItem);

        editFieldNameItem.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ae)
            {

            }
        });
        /*
        createFieldItem.addActionListener(this);
        deleteFieldItem.addActionListener(this);
        editMethodNameItem.addActionListener(this);
        createMethodItem.addActionListener(this);
        deleteMethodItem.addActionListener(this);
        */
    }

    @Override
    public void mouseClicked(MouseEvent me)
    {        
        if(SwingUtilities.isLeftMouseButton(me) && me.getClickCount() == 2)
        {
            diagram.doubleClick(me.getPoint());
        }
    }

    @Override
    public void mousePressed(MouseEvent e)
    {
        x = e.getX();
        y = e.getY();

        DiagramElement elt = diagram.containsPoint(e.getPoint());
        if (elt instanceof ClassModel)
        {
            elementBeingDragged = (ClassModel) elt;
        }
    }

    @Override
    public void mouseDragged(MouseEvent e)
    {
        int dx = e.getX() - x;
        int dy = e.getY() - y;

        if (elementBeingDragged != null)
        {
            elementBeingDragged.move(dx, dy);

            diagram.repaint();
        }

        x += dx;
        y += dy;
    }

    @Override
    public void mouseReleased(MouseEvent me)
    {
        elementBeingDragged = null;

        DiagramElement de = diagram.containsPoint(me.getPoint());

        if (SwingUtilities.isRightMouseButton(me) && me.getClickCount() == 1 && de instanceof Field)
        {
            if (me.isPopupTrigger())
            {
                System.out.println("it is");
                fieldPopupMenu.show(me.getComponent(), me.getX(), me.getY());
            }
        }
        else if (SwingUtilities.isRightMouseButton(me) && me.getClickCount() == 1 && de instanceof Method)
        {
            if (me.isPopupTrigger())
            {
                System.out.println("it is");
                methodPopupMenu.show(me.getComponent(), me.getX(), me.getY());
            }
        }  
    }
}

第 118 行显示 System.out.println("it is");它成功在控制台上显示文本,这告诉我代码成功到达该部分,但当我右键单击文本时,弹出菜单永远不会显示(文本位于由 5 个像素空间分隔的不可见矩形内)。

我尝试了多种解决方案来解决这个问题。我什至查看了 oracle 教程和其他用户的示例,看看我的代码出了什么问题。但经过无数个小时的寻找,我未能解决这个问题。任何帮助,将不胜感激。另外,如果您需要更多信息,我将很乐意提供!谢谢。

最佳答案

几件事;

首先,弹出窗口坐标应该相对于您触发弹出窗口的组件,而不是屏幕坐标。发生的情况是,API 正在计算组件的屏幕位置并添加您传递的 x/y 值,这可能会将弹出窗口推离屏幕

fieldPopupMenu.show(me.getComponent(), me.getX(), me.getY());

其次,弹出窗口可以通过不同的事件在不同的系统上触发。您应该检查 mousePressedmouseReleased 甚至 mouseClicked 中的 isPopupTrigger

最后,弹出窗口可以由不同的鼠标按钮(甚至可能是其他条件)触发,因此只需检查 isPopupTrigger

此外,您可以只使用 JComponent#setComponentPopupMenu

已更新 setComponentPopupMenu 示例

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class PopupMenuTest {

    public static void main(String[] args) {
        new PopupMenuTest();
    }

    public PopupMenuTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JPopupMenu popupMenu;

        public TestPane() {
            popupMenu = new JPopupMenu();
            popupMenu.add(new JMenuItem("Open..."));
            popupMenu.add(new JMenuItem("Save..."));
            popupMenu.add(new JMenuItem("Close..."));
            popupMenu.add(new JMenuItem("Give Blood..."));
            popupMenu.add(new JMenuItem("Give Money..."));

            setComponentPopupMenu(popupMenu);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

更新了 MouseListener 示例

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class PopupMenuTest {

    public static void main(String[] args) {
        new PopupMenuTest();
    }

    public PopupMenuTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JPopupMenu popupMenu;

        public TestPane() {
            popupMenu = new JPopupMenu();
            popupMenu.add(new JMenuItem("Open..."));
            popupMenu.add(new JMenuItem("Save..."));
            popupMenu.add(new JMenuItem("Close..."));
            popupMenu.add(new JMenuItem("Give Blood..."));
            popupMenu.add(new JMenuItem("Give Money..."));

            addMouseListener(new MouseAdapter() {

                protected void doPopup(MouseEvent evt) {
                    if (evt.isPopupTrigger()) {
                        popupMenu.show(evt.getComponent(), evt.getX(), evt.getY());
                    }
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    doPopup(e);
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    doPopup(e);
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    doPopup(e);
                }

            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

关于java - JPopupMenu 没有显示在屏幕上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20598686/

相关文章:

java - 我已经使用tomcat5.0.28 开发了一个应用程序。当我尝试执行它时,它发出以下异常

java - Swing - Awt。如何在没有前一帧中的元素的情况下渲染新帧?

java - 如何使用actionPerformed()旋转ImageIcon()?

java - 无法在 struts2 中更改或添加操作

java - String.replaceAll(regex) 进行两次相同的替换

java - 类不响应来自不同类的 Int

java - 添加 JLabel 作为 JPanel 的背景

java - StyledDocument 的 setCharacterAttributes() - 摆脱不需要的行为

java - JFrame代码编译并运行,但不打开窗口

JavaME(PBP): How do I rotate text?