【问题标题】:Java/Swing/Mac OSX: Converting JMenu to JPopupMenu using ScreenMenuBarJava/Swing/Mac OSX:使用 ScreenMenuBar 将 JMenu 转换为 JPopupMenu
【发布时间】:2012-07-26 15:57:36
【问题描述】:

我有一个应用程序,它有一个带有菜单栏的主 GUI,以及另一个全屏框架,这使得主 GUI 的某些部分以全屏独占模式显示。当我处于全屏模式时,我想将菜单栏中的下拉菜单绑定为 jpopupmenu。

Swing 在 JMenu 中提供了 getPopupMenu() 函数。乍一看,这个功能似乎工作正常。我可以将鼠标悬停在菜单项上并移动到并查看子菜单。将鼠标悬停在子菜单上确实会强调子菜单,将鼠标悬停在普通菜单项(或单选按钮菜单项或复选框菜单项)上不会强调该项目。但是,我实际上无法单击菜单项。不过,键盘快捷键确实可以正常工作。这个问题与这个论坛上的问题基本相同(但问题没有解决):

http://www.java-forums.org/new-java/16463-jmenu-jpopupmenu.html

如果我在菜单栏被初始化并在主 GUI 中使用/显示之后添加一个 JMenuItem(因此在切换到全屏框架时),菜单项实际上是可点击的。该菜单项反过来也可以在主 GUI 的菜单栏中单击。初始化 jMenu 后直接执行 getPopupMenu() 不会改变任何内容。不使用全屏独占模式也不会改变任何问题。

编辑

我似乎遗漏了一些重要信息:我正在 Mac OSX 上测试应用程序并使用: System.setProperty("apple.laf.useScreenMenuBar", "true");

要使菜单栏使用本机菜单栏。如果我禁用它,弹出菜单将按预期工作。这似乎是 mac java API 中的一个错误?这是他们的某种克服方式吗?

我很抱歉忘记提及这一点,我不知道这会影响任何事情(尽管这似乎很明显)。

【问题讨论】:

    标签: java macos swing jmenu jpopupmenu


    【解决方案1】:

    好的,我可能遗漏了一些东西,但我很快就将它破解了,没有任何问题

    public class PopupFrame extends javax.swing.JFrame {
    
        /**
         * Creates new form PopupFrame
         */
        public PopupFrame() {
            initComponents();
        }
    
        /**
         * This method is called from within the constructor to initialize the form.
         * WARNING: Do NOT modify this code. The content of this method is always
         * regenerated by the Form Editor.
         */
        @SuppressWarnings("unchecked")
        // <editor-fold defaultstate="collapsed" desc="Generated Code">
        private void initComponents() {
    
            jMenuBar1 = new javax.swing.JMenuBar();
            mnuFile = new javax.swing.JMenu();
            jMenuItem1 = new javax.swing.JMenuItem();
            jMenuItem2 = new javax.swing.JMenuItem();
            jMenuItem3 = new javax.swing.JMenuItem();
            jMenuItem4 = new javax.swing.JMenuItem();
            jMenuItem5 = new javax.swing.JMenuItem();
    
            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
            addMouseListener(new java.awt.event.MouseAdapter() {
                public void mousePressed(java.awt.event.MouseEvent evt) {
                    doMouseClicked(evt);
                }
                public void mouseReleased(java.awt.event.MouseEvent evt) {
                    doMouseClicked(evt);
                }
                public void mouseClicked(java.awt.event.MouseEvent evt) {
                    doMouseClicked(evt);
                }
            });
    
            mnuFile.setText("File");
    
            jMenuItem1.setText("New");
            jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    doActionPerformed(evt);
                }
            });
            mnuFile.add(jMenuItem1);
    
            jMenuItem2.setText("Open");
            jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    doActionPerformed(evt);
                }
            });
            mnuFile.add(jMenuItem2);
    
            jMenuItem3.setText("Save");
            jMenuItem3.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    doActionPerformed(evt);
                }
            });
            mnuFile.add(jMenuItem3);
    
            jMenuItem4.setText("Close");
            jMenuItem4.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    doActionPerformed(evt);
                }
            });
            mnuFile.add(jMenuItem4);
    
            jMenuItem5.setText("Exit");
            jMenuItem5.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    doActionPerformed(evt);
                }
            });
            mnuFile.add(jMenuItem5);
    
            jMenuBar1.add(mnuFile);
    
            setJMenuBar(jMenuBar1);
    
            org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(0, 400, Short.MAX_VALUE)
            );
            layout.setVerticalGroup(
                layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(0, 278, Short.MAX_VALUE)
            );
    
            pack();
        }// </editor-fold>
    
        private void doActionPerformed(java.awt.event.ActionEvent evt) {
    
            JMenuItem mi = (JMenuItem) evt.getSource();
    
            JOptionPane.showMessageDialog(this, "Clicked " + mi.getText());
    
        }
    
        private void doMouseClicked(java.awt.event.MouseEvent evt) {
    
            if (evt.isPopupTrigger()) {
    
                JPopupMenu popupMenu = mnuFile.getPopupMenu();
                popupMenu.show(this, evt.getX(), evt.getY());
    
            }
    
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String args[]) {
            /*
             * Set the Nimbus look and feel
             */
            //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
            /*
             * If Nimbus (introduced in Java SE 6) is not available, stay with the
             * default look and feel. For details see
             * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
             */
            try {
                for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        javax.swing.UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(PopupFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (InstantiationException ex) {
                java.util.logging.Logger.getLogger(PopupFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                java.util.logging.Logger.getLogger(PopupFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (javax.swing.UnsupportedLookAndFeelException ex) {
                java.util.logging.Logger.getLogger(PopupFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            //</editor-fold>
    
            /*
             * Create and display the form
             */
            java.awt.EventQueue.invokeLater(new Runnable() {
    
                public void run() {
                    new PopupFrame().setVisible(true);
                }
            });
        }
        // Variables declaration - do not modify
        private javax.swing.JMenuBar jMenuBar1;
        private javax.swing.JMenuItem jMenuItem1;
        private javax.swing.JMenuItem jMenuItem2;
        private javax.swing.JMenuItem jMenuItem3;
        private javax.swing.JMenuItem jMenuItem4;
        private javax.swing.JMenuItem jMenuItem5;
        private javax.swing.JMenu mnuFile;
        // End of variables declaration
    }
    

    抱歉,我不得不在我 3 个月大的孩子小睡时把它放在一起,所以它又快又丑:P

    更新

    经过一番尝试,似乎当我们自己调用弹出窗口时,我正在更改弹出窗口的父引用(invoker),这意味着当JMenu 试图显示弹出窗口时,上下文都是错误的.

    我将doActionPerformed 方法更新为如下所示:

    JOptionPane.showMessageDialog(this, "Clicked " + mi.getText());
    JPopupMenu popupMenu = mnuFile.getPopupMenu();
    popupMenu.setInvoker(mnuFile);
    

    基本上,休息弹出窗口的客户端引用。

    【讨论】:

    • 这似乎有效。可能问题是用来显示popupmenu的frame和menubar所在的frame不一样。编辑: - 单击鼠标右键(因此弹出菜单显示)后,文件菜单将不再显示,这有点奇怪。
    • +1 好例子;类似结果见here
    • 通常,我更喜欢解决这个问题的方法是有一个单独的弹出菜单。我将使用Action 类创建所有菜单项,从而使我能够集中公共代码,同时在设计中提供更大的灵活性。例如,您可以从上下文的角度构建弹出窗口。
    • @user23127 哇,你是对的。手动打开弹出窗口后,它不再与菜单项一起出现,真棒:P
    • 小家伙起来了,下次午睡时我会做一个多帧测试
    猜你喜欢
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 2011-05-25
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    相关资源
    最近更新 更多