1

我不确定问题出在我的代码还是 Java 1.7 上。

在下面的代码中(主要基于 Java Popup Demo),弹出窗口将在鼠标右键单击时出现。鼠标悬停时弹出菜单项将突出显示,单击 JmenuItem 使弹出菜单消失;但是,单击时不会触发 JMenuItem 的 actionEvent(应在 JTextArea 中报告)。

其他掘金:如果我键入 JMenuItem 的助记符(此处为“a”),则触发 actionEvent(该事件在 JTextArea 中报告)。

如果我没有附加自定义 Popup(Factory),则鼠标单击会按预期触发 actionEvent。

我正在使用 OSX 10.7.5

此问题发生在:

    java版本“1.7.0_07”
    Java(TM) SE 运行时环境 (build 1.7.0_07-b10)
    Java HotSpot(TM) 64 位服务器 VM(内部版本 23.3-b01,混合模式)

此代码在以下情况下表现良好:

    java版本“1.6.0_33”
    Java(TM) SE 运行时环境 (build 1.6.0_33-b03-424-11M3720)
    Java HotSpot(TM) 64 位服务器 VM(内部版本 20.8-b03-424,混合模式)

非常感谢任何帮助/想法!独立的代码示例如下。

谢谢

安德鲁

import java.awt.*;
import java.awt.event.*;
import javax.swing.*; 

public class PopupMenuDemo implements ActionListener  {
    JTextArea output;
    JScrollPane scrollPane;
    String newline = "\n";

    public Container createContentPane() {
        JPanel contentPane = new JPanel(new BorderLayout());
        contentPane.setOpaque(true);
        output = new JTextArea(5, 30);
        output.setEditable(false);
        scrollPane = new JScrollPane(output);
        contentPane.add(scrollPane, BorderLayout.CENTER); 
        return contentPane;
    }

    public void createPopupMenu() {
        JMenuItem menuItem;
        JPopupMenu popup = new JPopupMenu();
        menuItem = new JMenuItem("A popup menu item", 'a');
        menuItem.addActionListener(this);
        popup.add(menuItem);
        MouseListener popupListener = new PopupListener(popup);
        output.addMouseListener(popupListener);
    }

    public void actionPerformed(ActionEvent e) {
        JMenuItem source = (JMenuItem)(e.getSource());
        String s = "Action event detected."
        + newline
        + "    Event source: " + source.getText()
        + " (an instance of " + source.getClass().getName() + ")";
        output.append(s + newline);
        output.setCaretPosition(output.getDocument().getLength());
    }

    private void createAndShowGUI() {
        JFrame frame = new JFrame("PopupMenuDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    PopupFactory.setSharedInstance(new MyPopupFactory());
        PopupMenuDemo demo = new PopupMenuDemo();
        frame.setContentPane(demo.createContentPane());

        demo.createPopupMenu();

        frame.setSize(450, 260);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new PopupMenuDemo().createAndShowGUI();
        }
        });
    }

    class PopupListener extends MouseAdapter {
        JPopupMenu popup;

        PopupListener(JPopupMenu popupMenu) {
            popup = popupMenu;
        }

        public void mousePressed(MouseEvent e) {
            maybeShowPopup(e);
        }

        public void mouseReleased(MouseEvent e) {
            maybeShowPopup(e);
        }

        private void maybeShowPopup(MouseEvent e) {
            if (e.isPopupTrigger()) {
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        }
    }

    class MyPopupFactory extends PopupFactory {
    public Popup getPopup(Component owner, Component contents, int x, int y) throws IllegalArgumentException {
        return new MyPopup(owner, contents, x, y);
    }
    }

    class MyPopup extends Popup {
    private JWindow popupWindow;

    MyPopup(Component owner, Component contents, int ownerX, int ownerY) {
        popupWindow = new JWindow();
        popupWindow.setLocation(ownerX, ownerY);
        popupWindow.getContentPane().add(contents, BorderLayout.CENTER);
        contents.invalidate();
    }

    public void show() {
        popupWindow.setVisible(true);
        popupWindow.pack();
    }

    public void hide() {
        popupWindow.setVisible(false);
        popupWindow.removeAll();
        popupWindow.dispose();
    }
    }
}
4

2 回答 2

1

问题在于构造函数的使用new JWindow(),这使得新窗口与所有者组件无关。因此,单击弹出窗口的处理方式与单击 UI 中任何不相关部分的处理方式相同,从而取消弹出窗口。

您必须使用类似new JWindow(SwingUtilities.getWindowAncestor(owner))的方法使弹出窗口成为所有者窗口的子窗口。

于 2021-06-08T09:13:30.970 回答
0

首先,我会放弃使用 aMouseListener来监控弹出触发器,你最好使用它JComponent#setComponentPopupMenu并省去你自己的麻烦。

其次,我不知道您为什么要提供自己的弹出工厂,但这会给您带来问题。如果您注释掉该popupWindow.dispose行,它将起作用。至于为什么,我不能告诉你,可能 IDE 正在运行,所以我无法调试代码:P

于 2012-10-14T02:51:07.977 回答