Results 1 to 4 of 4
  1. #1
    ingfy is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default [SOLVED] Two JPanels and paint(Graphics)

    I am trying to create a game using Java. Until recently, I had very few problems, but when I added a main menu for my game, and at the same time added another JFrame and JPanel, nothing works. The game freezes as soon as I try to go past the main menu, and is trapped in a loop.

    The simplified example I will provide works this way:
    The main method creates a new object, Run(). This object creates a JFrame object and adds a MainMenu object, which is a class I wrote extending JPanel. This panel contains one button, Start Game. The JPanel has an action listener, which checks if the Start Game button is pressed. If it is, the panel disposes the JFrame and creates a new object, of the class Game.

    In Game's constructor, there is first made an object of the class Thing. This is a simple object that only exists for testing purposes, and it represents all the moving objects in my original game. Thing has fields such as coordinates and radius, and methods that get these values. It also includes a public void step() function which moves the thing object vertically downwards 0.5 pixels.

    After an instance of the Thing class is made, a new JFrame object is created, but this time another object of a class extending JPanel is made. This time the class GamePanel is used. GamePanel is a I wrote class extending JPanel and implementing KeyListener. It adds itself as a key listener to the frame. The GamePanel class contains a public void paint(Graphics) method which draws the Thing object at it's position. The public void keyPressed(KeyEvent) method calls different methods in Thing depending on which key is pressed.

    After the GUI is created in the Game object's constructor, a new method is called. I named it private void steps(). This contains an infinite loop (while (true)), which runs the Thing object's step() method and then repaints the GamePanel. Then it uses Thread.sleep() for a little while, before it runs the loop again indefinitely.

    Unfortunately, when running, this does not work. The paint() method in GamePanel is never ran, and the program freezes in the infinite loop. I realize that I made the loop, but shouldn't it still respond to key events, and last but not least paint the graphics?

    Another weird aspect is that when I replace "new Run();" in the main method in the Run class with "new Game();", so that it skips the main menu, everything works. I suspect that since I use classes extending JPanel twice, it somehow doesn't work right, but I don't have all that much experience with Java so I don't really know. Please, can anyone enlighten me why this happens?

    Run.java
    Java Code:
    import javax.swing.JFrame;
    
    public class Run {
    	
    	Run() {
    		createAndShowGUI();
    	}
    	
    	private void createAndShowGUI() {
    		JFrame frame = new JFrame("Menu");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		
    		frame.add(new MainMenu(frame));
    
    		frame.pack();
    		frame.setVisible(true);
    	}
    
    	public static void main(String[] args) {
    		new Run();
    	}
    }
    MainMenu.java
    Java Code:
    import java.awt.event.*;
    import javax.swing.*;
    
    public class MainMenu extends JPanel implements ActionListener {
    	
    	private static final long serialVersionUID = 1480632115673001227L;
    	
    	private GroupLayout layout;
    	private JButton startGame;
    	private JFrame frame;
    
    	MainMenu (JFrame f) {
    		frame = f;
    		createButtons();
    		createGroupLayout();
    	}
    	
    	private void createButtons() {
    		startGame = new JButton();
    		startGame.setText("Start Game");
    		startGame.addActionListener(this);
    	}
    
    	private void createGroupLayout() {
    		layout = new GroupLayout(this);
    		this.setLayout(layout);
    		
    		layout.setAutoCreateGaps(true);
    		layout.setAutoCreateContainerGaps(true);
    				
    		layout.setHorizontalGroup(layout.createSequentialGroup().addGroup(layout.createParallelGroup().addComponent(startGame))	);
    		layout.setVerticalGroup(layout.createSequentialGroup().addGroup(layout.createParallelGroup().addComponent(startGame)));
    	}
    	
    	private void startNewGame() {
    		frame.dispose();
    		new Game();
    	}
    
    	public void actionPerformed(ActionEvent arg0) {
    		if ( arg0.getSource() == startGame ) {
    			startGame.removeAll();
    			startNewGame();
    		}
    	}
    }
    Game.java
    Java Code:
    public class Game {
    	
    	private int w, h;
    	private Thing thing;
    	private GamePanel panel;
    	
    	Game () {
    		w = 200; h = 200;
    		thing = new Thing(this);
    		createAndShowGUI();
    		steps();
    	}
    	
    	private void steps() {
    		while (true) {
    			getActive().step();
    			panel.repaint();
    			
    			System.out.print(".");
    			
    			try {
    				Thread.sleep(1000/30);
    			} catch (InterruptedException e) {
    				;
    			}
    		}
    	}
    	
    	public void setPanel (GamePanel p) {
    		panel = p;
    	}
    	
    	public int getHeight() {
    		return h;
    	}
    	
    	public int getWidth () {
    		return w;
    	}
    	
    	public Thing getActive() {
    		return thing;
    	}
    	
    	private void createAndShowGUI() {
    		JFrame frame = new JFrame("Moles 2");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.add(new GamePanel(frame, this));
    		frame.pack();
    		frame.setVisible(true);
    		frame.setSize(w, h);
    	}
    }
    Thing.java
    Java Code:
    public class Thing {
    	private double x, y, r, floor, gravity, speed;
    	private Game game;
    	
    	Thing (Game g) {
    		game = g;
    		x = 10;
    		y = 10;
    		r = 20;
    		speed = 2;
    		floor = 100;
    		gravity = 0.5;
    	}
    	
    	public void right () { setX(getX() + speed); }
    	
    	public void left () { setX(getX() - speed); }
    	
    	public void up () {	setY(getY() - speed); }
    	
    	public void down () { setY(getY() + speed);	}
    	
    	private void setX (double xx) {	x = xx; }
    	
    	private void setY (double yy) {	y = yy;	}
    	
    	public int getX () { return (int)x; }
    	
    	public int getY () { return (int)y; }
    	
    	public int getR () { return (int)r;	}
    	
    	public void step () {
    		if (y < game.getHeight() - floor)
    			y += gravity;
    	}
    }
    GamePanel.java
    Java Code:
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class GamePanel extends JPanel implements KeyListener {
    	
    	private static final long serialVersionUID = -1597598138698356382L;
    	
    	private JFrame frame;
    	private Game game;
    	
    	GamePanel (JFrame f, Game g) {
    		frame = f;
    		game = g;
    		frame.addKeyListener(this);
    		game.setPanel(this);
    	}
    	
    	public void paint (Graphics g) {
    		Graphics2D g2d = (Graphics2D) g;
    		g2d.setColor(Color.WHITE);
    		g2d.fillRect(0, 0, game.getWidth(), game.getHeight());
    		g2d.setColor(Color.RED);
    		g2d.fillOval(game.getActive().getX(), game.getActive().getY(), game.getActive().getR(), game.getActive().getR());
    	}
    
    	public void keyPressed(KeyEvent arg0) {
    		switch (arg0.getKeyCode()) {
    			case KeyEvent.VK_RIGHT:
    				game.getActive().right(); break;
    			case KeyEvent.VK_LEFT:
    				game.getActive().left(); break;
    			case KeyEvent.VK_UP:
    				game.getActive().up(); break;
    			case KeyEvent.VK_DOWN:
    				game.getActive().down(); break;
    		}
    		repaint();
    	}
    
    	public void keyReleased(KeyEvent arg0) {}
    	
    	public void keyTyped(KeyEvent arg0) {}
    
    }
    Pardon me if this is too long, but I really need help with this one.
    Last edited by ingfy; 04-27-2010 at 05:11 PM.

  2. #2
    ingfy is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default

    Well, I ended up solving this one myself. I had to put my steps() function in a different thread, so I made a new class extending Thread which calls a single step() from Game 30 times every second. If anyone is interested, here is the code for the Step class:

    Step.java
    Java Code:
    public class Step extends Thread {
    	private Game game;
    	
    	
    	Step (Game g) {
    		game = g;
    		start();
    	}
    	
    	public void run () {
    		while (true) {
    			game.step();
    			try {
    				sleep(1000/30);
    			} catch (InterruptedException e) {}
    		}
    	}
    }

  3. #3
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    You're far better off using a Swing Timer, because right now I believe you risk calling Swing code on a non-EDT thread.

  4. #4
    ingfy is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default

    Thanks a lot! I wasn't expecting anymore replies, but now I am glad I checked back just in case. It looks much cleaner now, as well.

Similar Threads

  1. JList and JPanels
    By JetsYanks in forum New To Java
    Replies: 8
    Last Post: 12-25-2009, 03:11 PM
  2. Posistioning Jpanels
    By owain1221 in forum Java Applets
    Replies: 7
    Last Post: 11-16-2009, 12:21 AM
  3. HELP with jPanels
    By maverik_vz in forum AWT / Swing
    Replies: 1
    Last Post: 03-12-2009, 12:46 PM
  4. print variable with paint(Graphics g) ??
    By tghn2b in forum New To Java
    Replies: 10
    Last Post: 12-29-2008, 01:11 PM
  5. How to add Images to JPanels?
    By Soda in forum New To Java
    Replies: 3
    Last Post: 12-08-2007, 06:54 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •