在你将这篇文章标记为重复和referance 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));
}
}
}
这会产生相同的错误
答案 0 :(得分:3)
不,您的问题不是JFrame为null,而是您的Test.gui1变量为null。我在你的代码中添加了一行来测试它:
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在关键时刻为空的具体原因是因为在GUI1构造函数完成之前,对象gui1 = new GUI1();
的赋值不会发生。