【问题标题】:Prevent JPopupMenu from being covered by task bar防止JPopupMenu被任务栏覆盖
【发布时间】:2018-11-18 16:19:12
【问题描述】:

如何让我的JPopupMenu 出现在任务栏上方?换句话说,我如何强制它遵守屏幕限制,使其不被覆盖?以 Android Studio 的弹出菜单为例:

正常位置:

当我将窗口拖到底部任务栏附近时,弹出“适应”并出现在其上方:

现在我的测试用例: 正常位置:

在任务栏附近(您可以看到,与 Android Studio 不同的是,部分弹出窗口消失在任务栏下方):

测试用例代码:

Test.java

public class Test extends javax.swing.JFrame {

    public Test() {
        initComponents();
    }

    public void initUI() {

    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        btnMenu = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        btnMenu.setText("Click for Menu");
        btnMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnMenuActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(291, Short.MAX_VALUE)
                .addComponent(btnMenu)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(266, Short.MAX_VALUE)
                .addComponent(btnMenu)
                .addContainerGap())
        );

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>                        

    private void btnMenuActionPerformed(java.awt.event.ActionEvent evt) {                                        
        JPopupMenu menu = new JPopupMenu();
        menu.add(new PopBody());
        menu.show(this, btnMenu.getLocation().x - 95, btnMenu.getLocation().y + 60);
    }                                       

    public static void main(String args[]) {
        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 | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
        }
        java.awt.EventQueue.invokeLater(() -> new Test().setVisible(true));
    }

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

PopBody.java

public class PopBody extends javax.swing.JPanel {

    public PopBody() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        lblBody = new javax.swing.JLabel();
        btnOK = new javax.swing.JButton();

        lblBody.setText("Panel body");

        btnOK.setText("OK");
        btnOK.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnOKActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(77, 77, 77)
                .addComponent(lblBody)
                .addContainerGap(92, Short.MAX_VALUE))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(btnOK)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(73, 73, 73)
                .addComponent(lblBody)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 56, Short.MAX_VALUE)
                .addComponent(btnOK)
                .addContainerGap())
        );
    }// </editor-fold>                        

    private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {                                      

    }                                     


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

【问题讨论】:

  • 制作 JPopupMenu heavyweight.
  • @VGR 会实现什么?
  • 几乎所有 Swing 组件默认都是轻量级的,这意味着它们不是原生屏幕分配;相反,Swing 将它们绘制在窗口内。重量级组件使用原生矩形区域,因此它可以与其他原生元素重叠。权衡是重量级组件使用了更多的系统资源,尽管这可能不像 20 年前那么令人担忧。
  • 我刚刚在 JPopup 上调用了menu.setLightWeightPopupEnabled(false);,它的行为方式相同。

标签: java swing jpopupmenu


【解决方案1】:

我自己偶然发现了这个问题并想出了这个解决方案。

private void btnMenuActionPerformed(ActionEvent evt) {
    JPopupMenu popup = new JPopupMenu();
    popup.add(new PopBody());
    popup.pack();

    int popUpHeight = popup.getPreferredSize().height;
    //determines the max available size of the screen
    Rectangle windowBounds = GraphicsEnvironment.
        getLocalGraphicsEnvironment().getMaximumWindowBounds();
    Point invokerPosition = ((Component)evt.getSource()).getLocationOnScreen();

    if (invokerPosition.y + popUpHeight > windowBounds.height) {
        //get the negative margin and use it as the y-offset
        popup.show(this, 0, windowBounds.height - (invokerPosition.y + popUpHeight));
    }
    else {
        popup.show(this, 0, 0);
    }
}

不过,我不确定您的硬编码偏移量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-27
    • 1970-01-01
    • 2018-05-13
    • 2019-07-14
    • 2017-12-19
    • 2021-02-08
    • 2020-07-23
    • 1970-01-01
    相关资源
    最近更新 更多