以下内容:
public class TestCode {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
System.err.println("Showing popup");
// Create a popup menu and fill it with some component
JPopupMenu basicPopupMenu = new JPopupMenu();
JTextArea textArea = new JTextArea();
textArea.setLineWrap(true);
basicPopupMenu.add(textArea);
// This is not necessary for the crash, just to verify the pref size is not null at this point
System.out.println("Popup pref size is : " + basicPopupMenu.getPreferredSize());
System.out.println("Text area pref size is : " + textArea.getPreferredSize());
basicPopupMenu.show(null, 0, 0);
// This is not necessary for the crash, just to verify the minimum size is not null at this point
System.out.println("Min size is : " + basicPopupMenu.getMinimumSize());
System.out.println("Text area min size is : " + textArea.getMinimumSize());
// If I uncomment the next line, then the crash does not occur
// textArea.getPreferredSize()
try {
basicPopupMenu.getPreferredSize();
}
catch (Exception e) {
System.err.println("getPreferredSize() exception!");
e.printStackTrace();
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Test finished");
}
}
系统崩溃:
Showing popup
Popup pref size is : java.awt.Dimension[width=102,height=21]
Text area pref size is : java.awt.Dimension[width=100,height=16]
Min size is : java.awt.Dimension[width=102,height=21]
Text area min size is : java.awt.Dimension[width=100,height=16]
getPreferredSize() exception!
java.lang.NullPointerException
at javax.swing.BoxLayout.checkRequests(BoxLayout.java:466)
at javax.swing.BoxLayout.preferredLayoutSize(BoxLayout.java:281)
at javax.swing.plaf.basic.DefaultMenuLayout.preferredLayoutSize(DefaultMenuLayout.java:43)
at java.awt.Container.preferredSize(Container.java:1597)
at java.awt.Container.getPreferredSize(Container.java:1582)
at javax.swing.JComponent.getPreferredSize(JComponent.java:1636)
at TestPopup$1.run(TestPopup.java:26)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:646)
at java.awt.EventQueue.access$000(EventQueue.java:84)
at java.awt.EventQueue$1.run(EventQueue.java:607)
at java.awt.EventQueue$1.run(EventQueue.java:605)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:616)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Test finished
很难看出这会误用swing API,因为它应该完全在EDT中运行,并且应该在崩溃之前设置首选大小,实际上上面似乎没有一点最小/首选大小设置为null的堆栈。是否可能在此处调用另一个线程,或者布局中缺少某些东西?具有此跟踪的唯一bug report在我的Java环境中标记为已修复。
答案 0 :(得分:3)
由此可能的解决方案似乎是:
答案 1 :(得分:2)
这似乎是DefaultMenuLayout
的一项功能,见here。它扩展BoxLayout
并期望Container
推迟的非空目标BasicPopupMenuUI
。一种替代方法是使用不同的布局,例如:
basicPopupMenu.setLayout(new GridLayout());