2

Before you mark this post as duplicate and referance What is a NullPointerException, and how do I fix it?, I have read that and (I am still new to java and might not understand this correctly) can't seem to see how that is connected to my error.

I am trying to dispose a java swing JFrame and load another in it's place and have gotten this to work. Even though it is doing exactly what I want, it still gives me the java.lang.NullPointerException error. As far as I understand the code that the error is connected to is functioning as I want it to.

Here is my relevant code. If you need me to include any other code I did not think was necessary please let me know and I will edit.

EDIT

I removed all my previous code and have added mcve code for you.

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;
    }
}

package test;

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);
            }
        }
    }
}

package test;

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));
        }
    }
}

this produces the same error

Community
  • 1
  • 1
Julien Vincent
  • 1,210
  • 3
  • 17
  • 40
  • For better help, consider creating and posting a [Minimal, Complete, and Verifiable Example Program](http://stackoverflow.com/help/mcve). Also as an aside, are GeoButtons based on JButtons? If so, you should add ActionListeners to them, not MouseListeners. – Hovercraft Full Of Eels Oct 19 '14 at 17:53
  • The geobuttons arent extending JButtons, no. and I will take a look at the link you sent me now – Julien Vincent Oct 19 '14 at 17:55
  • 1
    OK, as long as they don't extend JButton or AbstractButton or anything similar... Also you will want to learn the general concepts of how to debug a NPE (NullPointerException). **You should inspect the line carefully that throws the exception**, find out which variable is null, and then trace back into your code to see why. With your code snippets posted so far, we cannot do this for you. You will run into these again and again, trust me. – Hovercraft Full Of Eels Oct 19 '14 at 18:00
  • Ok I am pretty sure which variable is being set to null, just not so sure why. I will post my main class code, I am not sure I have set it up properly. Could you take a look at that? :-) **edit** the accessoptions = new AccessOptions(); becomes null (I think) – Julien Vincent Oct 19 '14 at 18:04
  • To add on to my above comment - does disposing a JFrame automatically set the JFrame's variable to null? – Julien Vincent Oct 19 '14 at 18:12
  • No, calling `dispose()` on a JFrame just disposes of its use of system resources. The JFrame object itself is not destroyed, and the resources are re-gained if the frame is made visible again. – Hovercraft Full Of Eels Oct 19 '14 at 18:42
  • This is frustrating.. is there anything in my main class that could cause this error? – Julien Vincent Oct 19 '14 at 18:43
  • Your program structure looks very suspect to me, especially your use of static fields in GeoGrouper and your direct manipulation of class fields. This also could make your code difficult to test. – Hovercraft Full Of Eels Oct 19 '14 at 18:49
  • Hmm.. if you have the time and aren't too busy - You can download all my files from julienvincent.zapto.org. Setting the file userLog.txt to 0 is not logged in and 18 is logged in with a user – Julien Vincent Oct 19 '14 at 18:54
  • I usually don't do this, but I did download your code, but can't get it to run for lack of a database. Do you have test modules for each separate section of code that would allow that section to be tested without the others, and in particular that would allow testing of the code without a database? If not, something you should consider. – Hovercraft Full Of Eels Oct 19 '14 at 19:16
  • That is weird? You should have full connection to the database - I have tried it from other networks and it worked. By ways of running it without connection - I was planning on doing that later. Thanks for taking the time to try though. – Julien Vincent Oct 19 '14 at 19:18
  • I see `Error: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver` at `DBconnect.java:31` which is `results = statement.executeQuery(query);` – Hovercraft Full Of Eels Oct 19 '14 at 19:22
  • Ah that is the driver. It didn't load for some reason. You can re-add it though, the driver is in the dist build under lib. – Julien Vincent Oct 19 '14 at 19:25
  • 1
    I think that instead I'll wait for your [mcve](http://stackoverflow.com/help/mcve) code. – Hovercraft Full Of Eels Oct 19 '14 at 20:18
  • 2
    *"trying to dispose a java swing JFrame and load another in it's place"* Use a **`CardLayout`** instead! – Andrew Thompson Oct 19 '14 at 21:21
  • @Hovercraft Full Of Eels - I added code that you can test – Julien Vincent Oct 20 '14 at 14:13
  • 1+ for the good effort on your part in trying to help us help you. Thanks! – Hovercraft Full Of Eels Oct 20 '14 at 16:29
  • 2
    As a complement to @AndrewThompson's [comment](http://stackoverflow.com/questions/26453520/java-jframe-giving-me-java-lang-nullpointerexception-and-i-cant-figure-out-why#comment41551698_26453520) I will add this link: [The use of multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/questions/9554636/the-use-of-multiple-jframes-good-bad-practice) – Frakcool Oct 20 '14 at 16:45
  • 1
    @Frakcool: I heartily endorse your comment and link -- thanks for posting it! – Hovercraft Full Of Eels Oct 20 '14 at 16:49
  • 1
    @HovercraftFullOfEels yw, just trying to help others too. Since that link was really useful to me when I found it, so I just wanna help more people with it. – Frakcool Oct 20 '14 at 16:58

1 Answers1

3

No, your problem is not that the JFrame is null, but rather your Test.gui1 variable is null. I added a line to your code to test it out:

  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);
     }

This will return:

gui1 null? true
frame null? false

You're trying to call methods on the gui1 GUI1 object before its constructor has completed, a dangerous thing to do.

But again, the ultimate solution may be different and will depend on what you're trying to achieve. If your goal is to swap views, then I'm with Andrew Thompson -- you should switch JPanel views with a CardLayout.


Another way to test that I'm right is to see what happens if we call your frame swapping code in the GUI1 constructor vs giving it a little delay by queuing it on the Swing event thread using SwingUtilities.invokeLater(Runnable). In the code below, try running it with different values for the CREATE_ERROR boolean.

In other words, run it once with

public static final boolean CREATE_ERROR = true; 

and then run it again with

public static final boolean CREATE_ERROR = false; 

and see what happens

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);
   }
}

As a side note, I would rarely if ever swap JFrames like that (don't think I've ever done it come to think of it), although I have shown separate dialog windows. Also, I would take care to do all file reading off of the EDT. For example to take your code, I'd use a 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;
  }
}

The specific reason that gui1 is null at the critical time is because the assignment of an object to it, gui1 = new GUI1(); does not occur until the GUI1 constructor finishes.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373