5 Replies Latest reply on Dec 8, 2009 1:27 PM by 796262

    Help With Menus

    795507
      I'm writing the following class as a screen manager test using Pong to learn how to implement game menus. Whenever I run the following code, it runs the GameMenu() object fine, but when it switches to GameMenuSettings(), I get "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException". Am I missing a method that I have to call when I switch between objects?

      public class GameManager extends JPanel
      {
          public static int gameState;
      
          public static JFrame frame;
      
          public static int width, height;
          
          public static boolean thisActive;
          
          public GameManager()
          {
              width = 500;
              height = 500;
      
              gameState = 0;
      
              this.setPreferredSize(new Dimension(width, height));
      
              thisActive = true;
          }
      
          public void tic()
          {
              switch(gameState)
              {
                  case 0:
                      GameMenu menu = new GameMenu();
                      
                      frame.add(menu);
                      frame.validate();
                      frame.pack();
                      
                      while(thisActive)
                      {
                          try
                          {
                              menu.tic();
      
                              repaint();
                              
                              Thread.sleep(1000 / 30);
                          }
                          catch (Exception ex)
                          {
                              System.err.println(ex);
                          }
                      }
                      
                      frame.remove(menu);
                      
                      break;
                  case 1:
                      GameMenuSettings settings = new GameMenuSettings();
                      
                      frame.add(settings);
                      frame.validate();
                      frame.pack();
      
                      while(thisActive)
                      {
                          try
                          {
                              settings.tic();
      
                              Thread.sleep(1000 / 30);
                          }
                          catch (Exception ex)
                          {
                              System.err.println(ex);
                          }
                      }
      
                      frame.remove(settings);
      
                      break;
                  case 4:
                      System.exit(0);
                      break;
                  default:
                      gameState = 0;
                      break;
              }
          }
      
          public static void setGameState(int i)
          {
              gameState = i;
          }
      
          public static void setThisActive(boolean b)
          {
              thisActive = b;
          }
          
          public static void main(String[] args)
          {
              GameManager manager = new GameManager();
              frame = new JFrame("Pong");
              
              frame.setResizable(false);
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           frame.setVisible(true);
      
              while(true)
              {
                  manager.tic();
              }
          }
      }
        • 1. Re: Help With Menus
          796262
          Abion47 wrote:
          I'm writing the following class as a screen manager test using Pong to learn how to implement game menus. Whenever I run the following code, it runs the GameMenu() object fine, but when it switches to GameMenuSettings(), I get "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException". Am I missing a method that I have to call when I switch between objects?
          This isn't really the code we need to see. We need to see what goes on in the menu and settings tic( ) methods. Try boiling it down to an [SSCCE |http://sscce.org] (keep in mind the short part).
          • 2. Re: Help With Menus
            795507
            Nothing really going on in those methods.

            (menu)
            public void tic()
                {
                    repaint();
                }
            
            @Override
            public void paintComponent(Graphics g)
                {
                    g.setColor(Color.black);
                    g.fillRect(0, 0, windowWidth, windowHeight);
                    
                    g.setColor(Color.red);
                    
                    g.fill3DRect(playLocX, playLocY, (int)playRect.getWidth(), (int)playRect.getHeight(), true);
                    g.fill3DRect(setLocX, setLocY, (int)settingsRect.getWidth(), (int)settingsRect.getHeight(), true);
                    g.fill3DRect(credLocX, credLocY, (int)creditsRect.getWidth(), (int)creditsRect.getHeight(), true);
                    g.fill3DRect(quitLocX, quitLocY, (int)quitRect.getWidth(), (int)quitRect.getHeight(), true);
            
            public void mouseClicked(MouseEvent e)
                {
                    Point p = new Point(e.getX(), e.getY());
                    if (playRect.contains(p))
                    {
                        System.out.println("Play!");
                    }
                    else if (settingsRect.contains(p))
                    {
                        GameManager.setGameState(1);
                        GameManager.setThisActive(false);
                    }
                    else if (quitRect.contains(p))
                    {
                        GameManager.setGameState(4);
                        GameManager.setThisActive(false);
                    }
                }
            (settings)
            public void tic()
                {
                    repaint();
                }
            
            @Override
            public void paintComponent(Graphics g)
                {
                    g.setColor(Color.black);
                    g.fillRect(0, 0, width, height);
            
                    g.setColor(Color.red);
            
                    g.fillRect(0, 400, (int)exitRect.getWidth(), (int)exitRect.getHeight());
                }
            
            public void mouseClicked(MouseEvent e)
                {
                    Point p = new Point(mx, my);
            
                    if (exitRect.contains(p))
                    {
                        GameManager.setThisActive(false);
                        GameManager.setGameState(0);
                    }
                }
            Besides, each screen works fine individually. I only get the error when I switch from one screen to the other. Doesn't that mean that the error is in the manager class?
            • 3. Re: Help With Menus
              796262
              Abion47 wrote:
              Nothing really going on in those methods.

              Besides, each screen works fine individually. I only get the error when I switch from one screen to the other. Doesn't that mean that the error is in the manager class?
              Eh, maybe. The reason I asked for that code was because nothing really popped out to me as something that would cause a NullPointerException. Try to narrow it down (using a debugger or good old fashioned print statements) to figure out exactly which line is causing the problem.
              • 4. Re: Help With Menus
                795507
                Okay, so I went in and put print statements after every statement to see where the error was occurring, where each print statement would print a different number. The problem is that some numbers are repeating when they aren't supposed to (like numbers that print outside of a while loop while the code is working that particular while loop), and the exception is appearing randomly across the numbers - sometimes it appears after "5", sometimes after "7", sometimes after "21", etc.

                This is just making me more confused...

                Here's the full exception being thrown, if it helps:
                Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
                        at javax.swing.JComponent._paintImmediately(JComponent.java:5087)
                        at javax.swing.JComponent.paintImmediately(JComponent.java:4882)
                        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:803)
                        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
                        at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:694)
                        at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
                        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
                        at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
                        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
                        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
                        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
                        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
                        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
                        at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
                • 5. Re: Help With Menus
                  796262
                  The problem could be that you're changing the state of your GUI on a Thread other than the Event Dispatching Thread, where all swing work should take place.

                  To test my theory, try wrapping everything in your main method inside an invokeLater( ), which ensures that the work gets done on the EDT.
                      public static void main(String[] args)
                      {
                          javax.swing.SwingUtilities.invokeLater(new Runnable(){
                             GameManager manager = new GameManager();
                             frame = new JFrame("Pong");
                          
                             frame.setResizable(false);
                          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                          frame.setVisible(true);
                   
                             while(true)
                             {
                                 manager.tic();
                             }
                         });
                      }
                  If that doesn't help, then I'd suggest boiling your problem down to an [SSCCE |http://sscce.org] and posting a question on the swing forums (make sure you link back to this post).

                  For more on threading in swing (including the EDT), check out the [Concurrency |http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html] tutorials.

                  Edit- I should say that this is only to test the theory. Calling Thread.sleep( ) on the EDT is a horrible idea. But if this makes your problem go away, you need to track down where you're doing GUI work off the EDT and move that to an invokeLater( ).

                  Edited by: kevinaworkman on Dec 8, 2009 8:26 AM