在您将此帖子标记为重复项并引用What is a NullPointerException, and how do I fix it?之前,我已经阅读了(我仍然是java的新手,可能无法正确理解),似乎看不到它与我的错误有何关系。
我试图处理一个Java swing JFrame并在其位置加载另一个,并使它起作用。即使它确实可以满足我的要求,它仍然会给我java.lang.NullPointerException错误。据我了解,该错误所连接的代码正在按我的意愿运行。
这是我的相关代码。如果您需要我添加我认为不必要的任何其他代码,请告诉我,我将进行编辑。
编辑
我删除了所有先前的代码,并为您添加了mcve代码。
package test;
public final class Test {
private static GUI1 gui1;
private static GUI2 gui2;
public static void main(String[] args) {
startGUI1();
}
public static void startGUI1() {
gui1 = new GUI1();
}
public static GUI1 getGUI1() {
return gui1;
}
public static void startGUI2() {
gui2 = new GUI2();
}
public static GUI2 getGUI2() {
return gui2;
}
}
包装测试;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GUI1 {
JFrame frame;
public GUI1() {
frame = new JFrame();
frame.setVisible(true);
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.add(new Pane());
}
public class Pane extends JComponent {
public Pane() {
try {
Scanner read = new Scanner(new File("user.txt"));
if (read.nextInt() != 0) {
test.Test.startGUI2();
test.Test.getGUI1().frame.dispose();
}
} catch (FileNotFoundException ex) {
Logger.getLogger(GUI1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
包装测试;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GUI2 {
JFrame frame;
public GUI2() {
frame = new JFrame();
frame.setVisible(true);
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.add(new Pane());
}
public class Pane extends JComponent {
JLabel label = new JLabel("GUI2");
JButton button = new JButton("Start Gui1");
public Pane() {
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(5, 5, 5));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setStroke(new BasicStroke(5.0F));
}
}
}
这会产生相同的错误
最佳答案
不,您的问题不是JFrame为空,而是您的Test.gui1变量为空。我在您的代码中添加了一行以对其进行测试:
public Pane() {
try {
Scanner read = new Scanner(new File("user.txt"));
if (read.nextInt() != 0) {
Test.startGUI2();
// ********** two lines below added ******
System.out.println("gui1 null? " + (Test.getGUI1() == null));
System.out.println("frame null? " + (frame == null));
Test.getGUI1().frame.dispose();
}
} catch (FileNotFoundException ex) {
Logger.getLogger(GUI1.class.getName()).log(Level.SEVERE, null, ex);
}
这将返回:
gui1 null? true
frame null? false
您试图在gui1 GUI1对象的构造函数完成之前调用它的方法,这很危险。
但是同样,最终的解决方案可能会有所不同,这取决于您要实现的目标。如果您的目标是交换视图,那么我在Andrew Thompson任职-您应该使用CardLayout切换JPanel视图。
测试我是否正确的另一种方法是,看看如果我们在GUI1构造函数中调用您的帧交换代码,而不是通过使用
SwingUtilities.invokeLater(Runnable)
在Swing事件线程上对其进行排队来给它一些延迟,会发生什么。在下面的代码中,尝试对CREATE_ERROR布尔值使用不同的值运行它。换句话说,用
public static final boolean CREATE_ERROR = true;
然后用
public static final boolean CREATE_ERROR = false;
看看会发生什么
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TestA {
private static GUI1A gui1;
private static GUI2A gui2;
public static void main(String[] args) {
startGUI1();
}
public static void startGUI1() {
gui1 = new GUI1A();
}
public static GUI1A getGUI1() {
return gui1;
}
public static void startGUI2() {
gui2 = new GUI2A();
}
public static GUI2A getGUI2() {
return gui2;
}
}
class GUI1A {
public static final boolean CREATE_ERROR = true;
private JFrame frame1 = new JFrame("Frame 1");
public GUI1A() {
frame1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame1.add(new JLabel("This is Frame 1"));
frame1.pack();
frame1.setLocationByPlatform(true);
frame1.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (!CREATE_ERROR) {
swapFrames();
}
}
});
if (CREATE_ERROR) {
swapFrames();
}
}
private void swapFrames() {
TestA.startGUI2();
System.out.println("GUI1 is null: " + (TestA.getGUI1() == null));
System.out.println("frame1 is null: " + (frame1 == null));
TestA.getGUI1().getFrame().dispose();
}
public JFrame getFrame() {
return frame1;
}
}
class GUI2A {
private JFrame frame2 = new JFrame("Frame 2");
public GUI2A() {
frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame2.add(new JLabel("This is Frame 2"));
frame2.pack();
frame2.setLocationByPlatform(true);
frame2.setVisible(true);
}
}
附带说明一下,尽管我已经显示了单独的对话框窗口,但我很少交换这样的JFrame(不要以为我曾经考虑过)。另外,我会注意从EDT中读取所有文件。例如,为了获取您的代码,我将使用SwingWorker:
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
final MyWorker myWorker = new MyWorker();
myWorker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
int result = myWorker.get().intValue();
if (result != 0) {
TestB.startGUI2();
System.out.println("gui1 null? " + (TestB.getGUI1() == null));
System.out.println("frame null? " + (frame == null));
TestB.getGUI1().frame.dispose();
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
});
myWorker.execute();
}
}
private class MyWorker extends SwingWorker<Integer, Void> {
@Override
protected Integer doInBackground() throws Exception {
int result = 0;
Scanner read = null;
try {
read = new Scanner(new File(USER_FILE_PATH));
result = read.nextInt();
} catch (FileNotFoundException ex) {
Logger.getLogger(GUI1B.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (read != null) {
read.close();
}
}
return result;
}
}
gui1在关键时刻为null的特定原因是因为在GUI1构造函数完成之前,没有为它分配对象
gui1 = new GUI1();
。