[英]Java Swing: NullPointerException in own created resizable GUI
首先,我知道使用setLayout(null)
並不是最好的方法,但該程序的目標是嘗試編寫一個可自行調整大小的GUI。
首先,這三個類(分裂GroundFrame.java
和HomeScreen.java
的原因是將來會有多個窗口):
Start.java
public class Start {
public static void main(String[] arg){
new GroundFrame();
}
}
GroundFrame.java
public class GroundFrame extends JFrame{
static final long serialVersionUID = 0;
Container contentPane;
HomeScreen homeScreen;
public GroundFrame(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private void createAndShowGUI(){
createBasicFrame();
createPaneAndAddHome();
setVisible(true);
}
private void createBasicFrame(){
addComponentListener(new ComponentListener() {
public void componentShown(ComponentEvent e) {}
public void componentResized(ComponentEvent e) {
homeScreen.resizeHome(getContentPane().getSize());
}
public void componentMoved(ComponentEvent e) {}
public void componentHidden(ComponentEvent e) {}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = getContentPane();
contentPane.setPreferredSize(new Dimension(600, 400));
contentPane.setLayout(null);
pack();
}
private void createPaneAndAddHome(){
homeScreen = new HomeScreen(contentPane.getSize());
contentPane.add(homeScreen);
}
}
HomeScreen.java
public class HomeScreen extends JPanel{
static final long serialVersionUID = 0;
private JLabel labelHeader, labelFooter;
private JTextField textField;
private int x, y;
public HomeScreen(final Dimension dimension){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowPanel(dimension);
}
});
}
private void createAndShowPanel(Dimension dimension){
labelHeader = new JLabel("HEADER");
textField = new JTextField();
labelFooter = new JLabel("FOOTER");
setupPanel(dimension);
}
private void setupPanel(Dimension dimension){
x = dimension.width;
y = dimension.height;
setBounds(0,0,x,y);
setLayout(null);
setupTitle(new Dimension(x,y));
}
private void setupTitle(Dimension dimension){
x = dimension.width;
y = dimension.height;
labelHeader.setBounds((int)(x*0.1), (int)(y*0.1), (int)(x*0.8), (int)(y*0.3));
labelHeader.setOpaque(true);
labelHeader.setBackground(Color.cyan);
labelHeader.setFont(new Font("Arial", Font.PLAIN, (int)(y*0.25)));
textField.setBounds((int)(x*0.25), (int)(y*0.45), (int)(x*0.5), (int)(y*0.1));
textField.setFont(new Font("Arial", Font.PLAIN, (int)(y*0.08)));
labelFooter.setBounds((int)(x*0.1), (int)(y*0.6), (int)(x*0.8), (int)(y*0.3));
labelFooter.setOpaque(true);
labelFooter.setBackground(Color.cyan);
labelFooter.setFont(new Font("Arial", Font.PLAIN, (int)(y*0.25)));
add(labelHeader);
add(labelFooter);
add(textField);
}
public void resizeHome(Dimension dimension){
setupPanel(dimension);
}
}
現在一切都按照我的想法運行,但是我在HomeScreen.java
后續行中得到NullpointerException
labelHeader.setBounds((int)(x*0.1), (int)(y*0.1), (int)(x*0.8), (int)(y*0.3));
這是錯誤消息
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at gui.HomeScreen.setupTitle(HomeScreen.java:45)
at gui.HomeScreen.setupPanel(HomeScreen.java:39)
at gui.HomeScreen.resizeHome(HomeScreen.java:64)
at gui.GroundFrame$2.componentResized(GroundFrame.java:43)
at java.awt.AWTEventMulticaster.componentResized(AWTEventMulticaster.java:159)
at java.awt.Component.processComponentEvent(Component.java:6331)
at java.awt.Component.processEvent(Component.java:6285)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Window.processEvent(Window.java:2022)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:703)
at java.awt.EventQueue.access$000(EventQueue.java:102)
at java.awt.EventQueue$3.run(EventQueue.java:662)
at java.awt.EventQueue$3.run(EventQueue.java:660)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:676)
at java.awt.EventQueue$4.run(EventQueue.java:674)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:673)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
盡管如此,該計划仍然沒有發生任何事情。 畢竟,程序啟動時會出現錯誤,因此在沒有執行手動調整大小的位置(錯誤消息指示從HomeScreen
的resizeHome()
調用錯誤)。 為什么會這樣? 為什么程序繼續運行? 是否有可能構建GUI本身是ComponentListener
的componentResized()
的第一次調用?
這是因為您在構造函數中使用了SwingUtilities#invokeLater
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
你創建的是你UI中的競爭條件。
基本上, homeScreen.resizeHome
被調用(來自componentResized
)BEFORE HomeScreen#createAndShowPanel
被調用,因此意味着lablelHeader
還沒有被初始化...
您當前的事件序列看起來像......
new GrounFrame()
invokeLater
GroundFrame#createAndShowGUI
GroundFrame#createBasicFrame
(添加ComponentListener
, pack
) GroundFrame#createPaneAndAddHome
new HomeScreen
invokeLater
HomeScreen#createAndShowPanel
...立即返回... GrounFrame#setVisible(true)
GrounFrame#ComponentListener#componentResized
HomeScreen#resizeHome
HomeScreen#setupPanel
Null Pointer Exception
HomeScreen#createAndShowPanel
您應該將UI與main
的EDT同步
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GroundFrame();
}
});
}
並刪除對SwingUtilities#invokeLater
的其他引用
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.