1

我有 JFrame 和一个按钮,它在点击事件时打开一个 JPopupMenu。这个 JPopupMenu 有一个 JPanel,里面有一个按钮。这个按钮应该处理 JPopupMenu。只要 JFrame 未最大化,它就会执行此操作。但是,当 JFrame 最大化时,它会关闭 Jframe 本身。

任何有关解决此问题的帮助或指示将不胜感激。

(我正在使用 netbeans 来开发它。)

//Demo.Java

public class Demo extends javax.swing.JFrame {
    public JPopupMenu menu1;

    public Demo() {
        initComponents();
        menu1 = new JPopupMenu();
        menu1.add(new MyJPanel());    
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jButton1.setText("Open JPopupMenu");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(53, 53, 53)
                .addComponent(jButton1)
                .addContainerGap(224, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(85, 85, 85)
                .addComponent(jButton1)
                .addContainerGap(192, Short.MAX_VALUE))
        );

        pack();
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        menu1.show(jButton1,0,0);
    }                                        

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Demo().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    // End of variables declaration                   
}

下面是 MyJpanel 的代码。

// MyJPanel.java
package demo;

import java.awt.Window;
import javax.swing.SwingUtilities;

public class MyJPanel extends javax.swing.JPanel {
    public MyJPanel() {
        initComponents();
    }
    @SuppressWarnings("unchecked")
    private void initComponents() {

        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jPanel2 = new javax.swing.JPanel();

        jButton1.setText("Close jPopupMenu");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(82, 82, 82)
                .addComponent(jButton1)
                .addContainerGap(192, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(122, 122, 122)
                .addComponent(jButton1)
                .addContainerGap(127, Short.MAX_VALUE))
        );

        jButton1.getAccessibleContext().setAccessibleName("closeParent");

        jTabbedPane1.addTab("tab1", jPanel1);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 395, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 272, Short.MAX_VALUE)
        );

        jTabbedPane1.addTab("tab2", jPanel2);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane1)
        );
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        Window w = SwingUtilities.getWindowAncestor(MyJPanel.this);
        w.dispose();
    }                                        

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JTabbedPane jTabbedPane1;
    // End of variables declaration                   


}
4

2 回答 2

2

我假设,你的意思是:

当 JFrame 最大化时,它会关闭JPopupMenu本身

菜单的状态分别JPopupMenu与其祖先 ( JFrame) 或整个窗口系统紧密绑定。它将在焦点丢失、鼠标/按键按下...几乎在任何窗口中的任何状态更改或输入事件时被隐藏,就像人们从普通的弹出菜单中所期望的一样。解决此问题将迫使您重新打开菜单(捕获事件很难甚至不可能)。但是,这会导致闪烁。请注意,aJPopupMenu可以依赖底层平台窗口系统的固定基本机制,因此无法通过 AWT/Swing 更改其行为。

我最近想要类似的东西;JTable使用.切换 a 的多列的可见性JPopupMenu。但是后来,随着黑客的过度使用,我决定使用JDialog带有a 的模式JList,包含条目。JList向 a (或 a )添加悬停效果JTable是一种可移植且可重用的效果,这比上面提到的任何 hack 问题要少得多:Change JList item background color on hover

编辑:

SwingUtilities.getWindowAncestor(MyJPanel.this)

由于 JPopupMenu 不是 a WindowgetWindowAncestor()因此找不到JpopupMenu应该完全关闭的,如下所示:

public class MyJPanel extends javax.swing.JPanel {
    //...

    /**
     * Try to find and hide the first enclosing JPopupMenu by traversing the
     * parent components
     */
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        for (Component parent = this.getParent(); parent != null; parent = parent.getParent())
            if (parent instanceof JPopupMenu) {
                ((JPopupMenu) parent).setVisible(false);
                break;
            }
    }

    //...
}
于 2013-10-13T11:02:31.317 回答
1

这个按钮应该处理 JPopupMenu。只要 JFrame 未最大化,它就会执行此操作。但是,当 JFrame 最大化时,它会关闭 Jframe 本身。

当您使用弹出窗口并且弹出窗口超出框架边界时,弹出窗口将放置在 JWindow 中,因为 Swing 组件必须在窗口中绘制。这就是为什么它在使用默认帧大小时起作用的原因。

但是,如果弹出窗口完全包含在框架的边界中,则可以将弹出窗口添加到框架并绘制。您可以通过将框架稍大一点(不需要最大化)来轻松演示这一点,您会看到不同之处。

该解决方案基本上是 Sam 已经建议的,除了您不需要编写自己的代码。只需使用:

JPopupMenu popup = (JPopupMenu)SwingUtilities.getAncestorOfClass(JPopupMenu.class, (Component)e.getSource();

if (popup != null)
    popup.setVisible(false);
于 2013-10-13T17:58:00.547 回答