JPopupMenu не отображается на экране?

Поэтому для своего школьного проекта я создаю средство для создания диаграмм классов. Я закончил с этим на 95%, и все, что мне нужно, это сделать так, чтобы появилось меню Jpopup. В основном у меня есть 3 файла. ApplicationModel, которая расширяет JFrame, ClassDiagram, которая расширяет JPanel, и ClassModel, которая заставляет появляться прямоугольники (на рисунке). Ядром рендеринга являются объекты Rectangle, а текст внутри среднего и нижнего прямоугольников окружен другим невидимым прямоугольником, который можно щелкнуть правой кнопкой мыши.

Вот как выглядит программа (без редактирования краски) Теперь о файле, который обрабатывает щелчок - это 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 пикселями).

Я пробовал несколько решений этой проблемы. Я даже просмотрел учебные пособия по оракулу и примеры других пользователей, чтобы понять, что не так с моим кодом. Но после бесчисленных часов поиска мне не удалось решить проблему. Любая помощь будет оценена по достоинству. Также, если вам нужна дополнительная информация, я буду рад предоставить! Спасибо.


person Community    schedule 15.12.2013    source источник
comment
Пожалуйста, не забудьте добавить '?' на вопросы! Некоторые люди выполняют поиск на странице по запросу '?' и если в «вопросе» их нет, перейдите непосредственно к следующему (фактическому) вопросу в строке.   -  person Andrew Thompson    schedule 15.12.2013


Ответы (1)


Несколько вещей;

Во-первых, координаты всплывающего окна должны относиться к компоненту, на котором вы запускаете всплывающее окно, а не к координатам экрана. Что происходит, так это то, что API вычисляет местоположение компонента на экране и добавляет значения x/y, которые вы передаете, что, возможно, выталкивает всплывающее окно с экрана.

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

Во-вторых, всплывающие окна могут вызываться в разных системах разными событиями. Вы должны проверять isPopupTrigger в mousePressed, mouseReleased и даже mouseClicked.

Наконец, всплывающие окна могут вызываться разными кнопками мыши (и даже, возможно, другими условиями), поэтому нужно только проверить 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);
        }

    }

}
person MadProgrammer    schedule 15.12.2013
comment
Дело в том, что я только что изменил это на то, что у меня есть для целей тестирования. Извините, я забыл изменить его обратно. Однако это все еще не работает (обратите внимание, что у меня также есть метод PopupMenu для отображения в me.getX() и me.getY()) - person ; 15.12.2013
comment
Проверьте положение мыши и видимость компонента. - person MadProgrammer; 16.12.2013
comment
Можете ли вы показать мне пример использования JComponent#setComponentPopupMenu? Кроме того, координаты показывают, что положение мыши находится в правильном месте. - person ; 16.12.2013