0

I am getting some strange errors when running my Java game. I've been working on this game for weeks as a project for my computer science class and it is due on 6/4/2015, so I appreciate any help. Initially I wrote the game in a class called Game and ran it from a static method called run. Later, I decided to add a GUI menu in a class called Control. To run the game now, I call the main method in the Control class. This menu has a button with an action listener. When the button is clicked, the run method in the Game class is called. If I click and run the run method directly the game works fine. But if I click the button which calls the run method it draws a frame, but not the actual game.

Here is my code for the GUI:

    public class Control extends JFrame implements ActionListener {

    // JPanel
    public JPanel pnlButton = new JPanel();

    // Buttons
    public JButton btnAddFlight = new JButton("Multiplayer");
    public JButton single = new JButton("Singleplayer");

    public Control() throws IOException,InterruptedException {
        super("Bouncy Ball");
        //Set button size
        btnAddFlight.setBounds(150, 400, 220, 30);
        single.setBounds(150,350,220,30);

        // JPanel bounds
        pnlButton.setBounds(0, 0, 500, 500);
        pnlButton.setBackground(Color.WHITE);

        // Adding the Bouncy Ball logo to JPanel
        String path = "gg.jpg";
        File file = new File(path);
        BufferedImage image = ImageIO.read(file);
        JLabel label = new JLabel(new ImageIcon(image));
        label.setBounds(179,50,150,150);

        //Action Listener setup
        single.addActionListener(this);

        //add buttons and title logo to JPanel
        pnlButton.add(btnAddFlight);
        pnlButton.add(label);
        pnlButton.add(single);

        //Set up and add the instructions to the JPanel
        JLabel gg = new JLabel("Welcome to Bouncy Ball, a game where you have to manipulate");
        gg.setFont(new Font("Serif", Font.PLAIN, 18));
        gg.setBounds(0,10,500,500);
        pnlButton.add(gg);
        JLabel f = new JLabel("the window size with WASD to win! Click the buttons to start.");
        f.setFont(new Font("Serif", Font.PLAIN, 18));
        f.setBounds(0,28,500,500);
        pnlButton.add(f);
        pnlButton.setLayout(null);

        //Add JPanel to JFrame
        this.add(pnlButton);

        // JFrame properties
        setSize(500, 500);       
        setTitle("Bouncy Ball");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);;
    }

    @Override
    public void actionPerformed(ActionEvent submitClicked) {
        try{
            isClicked = true;

            Game.run();
        }
        catch(InterruptedException a){}
    }

    public static void main(String[] args) throws IOException,InterruptedException{
        new Control();
    }
}

and here is the run method in my game class:

public static void run() throws InterruptedException {
    //Setting up JFrame
    frame = new KeyFrame("Bouncy Ball");
    frame.setSize(1000, 1000);

    //Setting up Scanner and get user level input
    Scanner scan = new Scanner (System.in);
    System.out.println("Level one, two, three, or four?(must be an int, four is multiplayer)");
    f = scan.nextInt();

    //Display JFrame
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.toFront();

    //Add Game JPanel
    game = new Game();
    frame.add(game);

    //Setting up game basics
    b = new Ball(game,0,0,30,30);
    setUpLevel();
    objList.add(0,b);

    //Main Game Loop
    while (true) {
        //Request Focus
        game.requestFocusInWindow();

        //Update current Time
        lastStartTime = System.currentTimeMillis();

        //Move the ball and the player
        p.move();
        b.move();

        //Refresh JPanel
        game.repaint();
        Thread.sleep(10);

        //Check if the player wins or loses
        checkWin();
        checkLoss();
    }
}

If I call the run method directly it works, but not if I click the button in the GUI. I have a feeling that it is a thread issue, because the main thread ends once run is called. I'm not a 100% percent sure as to the cause though. I'd appreciate any responses, I've been working on this game for weeks as a project for my computer science class and it is due on 6/4/2015.

1 Answer 1

1

Swing is single threaded - all painting, events, etc...occur on this thread (named the EDT). The Game.run method is called on the EDT, which in turn executing a long running task (eg while (true), Thread.sleep) - this prevents the EDT from doing anything else. To perform animation, consider using a Thread, or better yet a Swing Timer.

Sign up to request clarification or add additional context in comments.

4 Comments

Swing Timer is simple, but if you're going to tell 'em to create a Thread, then you should also say that the thread must not call any Swing methods other than SwingUtilities.invokeLater().
@copeg Thank you so much. I created a new thread and called my run method from there and everything works perfectly now.
@user1615326, if using a Thread, please note @james large comment above RE: calls to Swing (eg repaint, requestFocusInWindow) should be dispatched to the EDT using SwingUtilities.invokeLater.
Thanks, I'll change my code to do that. A quick question though, my code works fine even though I'm calling repaint without using SwingUtilities.invokeLater. Why do I have to use SwingUtilities.invokeLater? Are there any benefits?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.