widavies
widavies

Reputation: 986

Error with creating a game launcher

I'm making a simple java game and trying to implement a launcher at the beginning of the game.

For example, a JFrame with a button in it that starts my application when it's pressed.

What I'm trying to do is have the main method call a separate class that opens a JFrame, and an ActionListener for the JButton that calls new Cliker(); when it's called.

However, when new Cliker(); is called outside of the main method, it opens the game JFrame, but not the JPanel.

Why is this error happening, and how could I fix it? I am relatively new to programming so I apologize in advance for any unclear points about this question or my program.

I would greatly appreciate your help. If you need any more classes to help answer my question, just ask, or if you have any other questions feel free to let me know.

package com.Cliker;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import com.Cliker.Accessories.Music;

public class Cliker extends JFrame {

private static final long serialVersionUID = 1L;

int score = 0;

JButton ball = new JButton(new ImageIcon("res/textures/ball/ball.PNG"));
JFrame gameFrame = new JFrame("Cliker v1.0");

public static void main(String[] args){
    new Cliker();
}


public Cliker() {

    gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    gameFrame.add(new MyPanel());
    gameFrame.pack();
    gameFrame.setVisible(true);
    gameFrame.setResizable(false);
    gameFrame.setLocationRelativeTo(null);

    ClikerGame play = new ClikerGame();
    play.run(this);

}

class MyPanel extends JPanel implements MouseListener {

    private static final long serialVersionUID = 1L;

    public MyPanel() {

        setBackground(Color.CYAN);

        ball.addMouseListener(new MouseListener() {

            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getSource() == ball) {
                    score++;
                    Music.music(4);
                    repaint();

                }

            }

            @Override
            public void mouseClicked(MouseEvent e) {

            }

            @Override
            public void mouseEntered(MouseEvent e) {

            }

            @Override
            public void mouseExited(MouseEvent e) {

            }

            @Override
            public void mouseReleased(MouseEvent e) {

            }
        });
        ball.setBorder(null);

        add(ball);
        addMouseListener(this);

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setFont(new Font("Fixedsys", Font.BOLD, 30));
        g.setColor(Color.BLACK);
        g.drawString(String.valueOf(score), getWidth() / 2, 40);

    }

    public Dimension getPreferredSize() {
        return new Dimension(700, 500);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getSource() == this) {

            this.setBackground(Color.RED);

            gameFrame.setVisible(false);

            ClikerEndGame sendData = new ClikerEndGame();

            try {

                sendData.finish(score);

            } catch (Exception e1) {
                JOptionPane.showInputDialog(null,"The game has encountered an error. Error code: 001");
                e1.printStackTrace();
            }




        }

    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent arg0) {

    }
}

}

Next Class

package com.Cliker;

import javax.swing.JButton;
import javax.swing.JOptionPane;
import com.Cliker.Accessories.Music;

 public class ClikerGame implements Runnable {

 private int x, y, xa = 2, ya = 2;


public void run(Cliker panel) {


    JButton ball = panel.ball;

    Music.music(2);

    while (true) {
        try {
            x += xa;
            y += ya;
            if (x < 0 || x > 700 - 20 ) {

                Music.music(1);

                xa = -xa;
            }

            else if (y < 0 || y > 500 - 20 ){

                Music.music(1);

                ya = -ya;

            }

            Thread.sleep(15);

            ball.setBounds(x,y,30,30);
        } catch (Exception e) {
                JOptionPane.showMessageDialog(null,"Error 1");

        }

    }
}
public void run() {
    this.run();

}

}

Upvotes: 0

Views: 88

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347334

Basically, you're violating the single thread rules of Swing, the ClikerGame is running a while-loop which is blocking the Event Dispatching Thread, preventing it from processing new events, including paint events.

The reason that it works from main, is main isn't called from within the EDT, basically, it was a fluke. When you call new Clicker() from within the ActionListener of your JButton however, you are running from within the context of the EDT, hence your problem.

Take a look at Initial Threads and Concurrency in Swing for more details.

The "immediate" solution might look like using a Thread, but this would also violate the single rules of Swing, as Swing is not thread safe and you should never update the UI from outside the context of the EDT.

A better solution might be to use a Swing Timer to act as a pseudo loop instead. This is notified, at regular intervals, withing the context of the EDT

Maybe, something like...

public class ClikerGame {

    private int x, y, xa = 2, ya = 2;
    private Clicker clicker;

    private Timer timer;

    public ClikerGame(Clicker clicker) {
        this.clicker = clicker;

        timer = new Timer(15, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    x += xa;
                    y += ya;
                    if (x < 0 || x > 700 - 20) {

                        Music.music(1);

                        xa = -xa;
                    } else if (y < 0 || y > 500 - 20) {

                        Music.music(1);

                        ya = -ya;

                    }

                    Thread.sleep(15);

                    clicker.ball.setBounds(x, y, 30, 30);
                    clicker.ball.getParent().repaint();
                } catch (Exception e) {
                    JOptionPane.showMessageDialog(null, "Error 1");

                }
            }
        });
    }

    public void start() {
        if (!timer.isRunning()) {
            Music.music(2);
            timer.start();
        }
    }

    public void stop() {
        timer.stop();
        // Stop the music
    }
}

Upvotes: 2

Related Questions