在您将此帖子标记为重复项并引用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();

10-08 02:34