Java 调用getPreferredSize()的仅EDT代码中的BoxLayout异常
以下是:Java 调用getPreferredSize()的仅EDT代码中的BoxLayout异常,java,swing,Java,Swing,以下是: 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
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。这里是否可能调用了另一个线程,或者布局中缺少了什么?在我的Java环境中,唯一具有此跟踪的标记为fixed。这似乎是的一个功能,请参阅。它扩展了
BoxLayout
,并需要一个非空的目标容器
,而BasicPopupMenuUI
将其延迟。一种选择是使用不同的布局,例如:
basicPopupMenu.setLayout(new GridLayout());
这似乎是一个特征,可见。它扩展了
BoxLayout
,并需要一个非空的目标容器
,而BasicPopupMenuUI
将其延迟。一种选择是使用不同的布局,例如:
basicPopupMenu.setLayout(new GridLayout());
在BoxLayout源代码中,
checkRequests()
遍历组件的所有子组件,检查其所有大小要求。也许您的代码是在创建JPopUp菜单objecdt时,但在创建和呈现其所有子组件之前执行此操作的。在BoxLayout源代码中,checkRequests()
遍历组件的所有子组件,检查其所有大小要求。也许您的代码是在创建JPopUp菜单objecdt时,但在创建和呈现其所有子组件之前执行此操作的。只是一个噱头。这得到了一个支持票,因为它指出了问题的根本原因,但我不能接受它作为答案,因为正如你所说的,有其他方法可以改变布局,但在很多情况下这不是一个选项。重量级contianers必须是pack(),也许要更改默认布局管理器这得到了一个赞成票,因为它指出了问题的根本原因,但我不能接受它作为答案,因为正如你所说的,在很多情况下,更改布局是没有选择余地的。重量级contianers必须是pack(),可能要更改默认布局管理器,您可以在EDT上对.getPreferredSize()
调用进行排队,这将足够延迟以防止错误。或者您可以在EDT上对.getPreferredSize()
调用进行排队,这将足够延迟以防止错误。