gpt4 book ai didi

java - 可见时更新 JPopupMenu 高度

转载 作者:行者123 更新时间:2023-11-30 11:13:52 27 4
gpt4 key购买 nike

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

使用“分页”组件的优点是它可以很好地适应应用程序的其余部分(它已经在其他非弹出窗口的地方使用)并且在页面之间导航时有一些漂亮的动画效果.

我遇到的问题是,当显示不同的页面时,分页组件的首选高度会发生变化(列表中的项目数量会发生变化),我希望弹出菜单的高度能够更新,以便它完全适合分页组件, 但到目前为止,我尝试在弹出菜单可见时更新它的高度都失败了。

下面是一个演示问题的示例应用程序:

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 的高度?

最佳答案

对于问题中的测试应用程序,弹出窗口始终是一个重量级组件,并且以下组件有效(如 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;
}
});

强制弹出菜单始终是重量级组件后this

SwingUtilities.getWindowAncestor(popupMenu).pack();

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

关于java - 可见时更新 JPopupMenu 高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26214246/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com