当前位置: 首页 > 知识库问答 >
问题:

可见时更新JPopupMenu高度

宋鸿德
2023-03-14

我的应用程序中有一个弹出菜单,我想用一个自定义的菜单替换它,这样它就能与应用程序的其他部分相匹配。从本质上说,我不想在弹出窗口中使用普通的菜单项,而是想重用应用程序中其他地方已经存在的组件,该组件允许您以“分页”的方式而不是子菜单来导航项的层次结构。因此,如果单击列表中包含子项的项,则将显示下一页,用所单击项的子项列表替换列表中的当前项。

import java.awt.BorderLayout;
import java.awt.Color;
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.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;

public class PopupSizeTestFrame extends JFrame {

    private static final int PREFFERED_WIDTH = 300;
    private static JPanel resizingPanel;
    private static JPopupMenu popupMenu;
    private static PopupSizeTestFrame frame;

    private static void resizePopupMenu() {
        // What should I do here so that the size of the popup menu is updated?

        /**
         * Calling pack() works in this example, but I cannot call pack in the
         * actual application since there is a smooth transition animation when
         * clicking on the inner panel and pack() essentially re-adds the
         * components of the popup menu (removeNotify and addNotify is called),
         * which interferes with the animation and causes the menu to flicker.
         * The flickering when clicking the inner panel can also be seen in this
         * example when uncommenting the pack() call.
         */
        //popupMenu.pack();
        // 
        // I tried combinations of the following, without success:
        //popupMenu.invalidate();
        //popupMenu.revalidate();
        //popupMenu.validate();
        //popupMenu.doLayout();

        // Repaint
        popupMenu.repaint();
    }

    public static void main(String args[]) {
        // Create popup child panel with height that changes when clicked
        resizingPanel = new JPanel(new BorderLayout());
        int initialHeight = 30;
        final JLabel label = new JLabel("Click me (" + initialHeight + "px)");
        resizingPanel.add(label);
        resizingPanel.setBackground(Color.GREEN);
        resizingPanel.setPreferredSize(new Dimension(PREFFERED_WIDTH, initialHeight));
        resizingPanel.addMouseListener(new MouseAdapter() {
            private int clickCount = 0;

            @Override
            public void mouseClicked(MouseEvent e) {
                int height = ((clickCount % 3) + 1) * 50;
                resizingPanel.setPreferredSize(new Dimension(PREFFERED_WIDTH, height));
                clickCount++;
                label.setText("Click me (" + height + "px)");
                resizePopupMenu();
            }
        });

        // Create popup
        popupMenu = new JPopupMenu();
        popupMenu.setLayout(new BorderLayout());
        popupMenu.add(new JLabel("Header"), BorderLayout.NORTH);
        popupMenu.add(resizingPanel, BorderLayout.CENTER);
        popupMenu.add(new JLabel("Footer"), BorderLayout.SOUTH);

        // Create frame
        frame = new PopupSizeTestFrame();
        frame.setLayout(new BorderLayout());
        frame.setPreferredSize(new Dimension(400, 400));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    popupMenu.show(frame, e.getX(), e.getY());
                }
            }
        });

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                frame.setVisible(true);
            }
        });
    }
}

当运行上面的示例时,您将看到,如果在单击内部面板后关闭和打开弹出菜单,则弹出菜单的大小会被更新,但当弹出菜单可见时,弹出菜单的大小不会被更新。

我可以在resizePopupMenu()中做什么来更新JPopupMenu的高度?

共有1个答案

楚意
2023-03-14

对于问题中的测试应用程序,弹出窗口始终是一个重量级组件,下面的工作(正如mKorbel所建议的)

private static void resizePopupMenu() {
    SwingUtilities.getWindowAncestor(popupMenu).pack();
}

对于实际应用程序,当弹出窗口在应用程序的边界内时,它被创建为一个轻量级组件,这就防止了它被pack()调整大小,也防止了它的大小超过应用程序的边界。

我尝试设置此属性...

JPopupMenu.setDefaultLightWeightPopupEnabled(false);
// Set owner to component on which popup is shown or any of its parents
final Component owner = ...; 
AccessController.doPrivileged(new PrivilegedAction<Void>() {
    @Override
    public Void run() {
        try {
            Field field;
            if (System.getProperty("java.version").startsWith("1.6.0")) {
                Class clazz = Class.forName("javax.swing.PopupFactory");
                field = clazz.getDeclaredField("forceHeavyWeightPopupKey");
            } else { //JDK 1.7.0, 1.8.0
                Class clazz = Class.forName("javax.swing.ClientPropertyKey");
                field = clazz.getDeclaredField("PopupFactory_FORCE_HEAVYWEIGHT_POPUP");
            }
            field.setAccessible(true);
            owner.putClientProperty(field.get(null), Boolean.TRUE);
        } catch (Exception ex) {
            Exceptions.printStackTrace(ex);
        }
        return null;
    }
});

在强制弹出菜单始终为重量级组件后,此

SwingUtilities.getWindowAncestor(popupMenu).pack();

还更新了弹出窗口的大小,甚至超出了应用程序的范围。

 类似资料:
  • 改变接收到的message的不可见时间 message被某一用户实例接收后,将在一段时间内变为不可见,以防止被反复接收 当不可见时间超时,且之间一直没有收到此message的删除请求,EMQ将认为这条message未被成功处理,且此次接收message的用户实例已变为不响应状态。因此EMQ会将message重新置为可见状态,以便此message被再次读取并成功处理 用户实例接收后message后,

  • 我有一个问题与primeface数据表。我有一个数据与一些条目和一个列与一个按钮内。如果按钮被按下,一个弹出窗口打开与另一个数据表。第二个数据表中的条目取决于行中的按钮被按下。 Bean2 问题是弹出式数据表中没有列出任何条目,尽管在db查询之后的列表中有一些条目。 有没有办法修复这个bug?提前感谢! 更新1:

  • 问题内容: 我正在尝试在通过ajax 交换内容的上实现面包屑导航。 最终看起来像这样: 这是我的页面代码: 主页和页面都很简单。每当我更新的内容时,都需要更新Panel的一个。我确定 生产线会做到这一点。但是它是空的。标签不显示任何内容。 我希望在写问题时能找到答案-这可能很明显-但我仍然无法找到答案,所以我希望这里有人发现我的错误。 问题答案: 通过Ajax播放组件的可见性时, 除了之外 ,还必

  • 介绍 (Introduction) 弹出菜单表示一个菜单,可以在组件内的指定位置动态弹出。 Class 声明 (Class Declaration) 以下是javax.swing.JPopupMenu类的声明 - public class JPopupMenu extends JComponent implements Accessible, MenuElement 类构造函数

  • 我是Netbeans和Java的新手,对jpanels上的jlabel有一个问题。我有一个jTabbedPane,里面有一个jPanel。我在JPanel上有一个jLabel。我想将jLabel的可见性设置为false,但似乎不起作用。当我运行程序时,标签仍然可见。我不明白为什么。

  • 问题内容: 更新“订单”列的最佳方法是什么? 假设我有一个ID列,其范围是0到9,而订购列的范围是0到9。 当前,它在数据库中的位置为:0 0、1、1、2、2等 我的HTML页面发布了新顺序:0 8、1 3、2 6等(这完全是随机的,由用户决定)。 进行更新的最佳方法是什么? 我可以遍历并运行每个更新。我还可以创建一个包含所有对的临时表,然后基于子查询进行更新。 但是我觉得我忘记了一些琐碎的事情,