Search code examples
javaswingtimer

When I add a timer the images won't load anymore


I am trying to create an Asteroids-game, but I am already struggling at the very beginning: I want to create a countdown before the game starts. To do that, I'm using a timer which starts when pressing the button "start" and which (should) load a BufferedImage every second, then display it on a JFrame.

The entire thing worked perfectly before I added the timer. However, the image is still being drawn, and the method run() of the TimerTask is still being used completely. However, the image does not appear on my JFrame.

public class Main implements ActionListener {

    private static File load = null;
    private static BufferedImage image = null;
    private JFrame frame;
    private JButton start;
    private JLabel game_name;
    private JLabel screen;
    private ImageIcon icon;
    private Asteroids aster = new Asteroids();
    private static Main m = new Main();

    protected static int height = 550;
    protected static int width = 800;
    protected static int cd = 0;

    /*
     * Here the JFrame frame gets created and set up, and the main method 
     * does its job. I believe only the actionPerformed method to be 
     * important, so I removed this part from the post.
     *
     */


    private void addScreen() {
        frame.add(screen);
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        // Cleaning the screen
        start.setVisible(false);
        game_name.setVisible(false);

        // Creating the image
        aster.spawn(5);

        // creating the countdown timer
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {            
            public void run() {
                // creating countdown
                aster.initialScreen();

                // Reading the image
                load = new File(aster.filePath + aster.fileName + ".png");
                image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                try {
                image = ImageIO.read(load); 
                } catch (IOException i) {
                    System.out.println("Reading has encountered an error: \n" + i); }

                // Implementing the Image
                screen = new JLabel();
                screen.setSize(width, height);
                icon = new ImageIcon(image);
                screen.setIcon(icon);
                m.addScreen();
                System.out.println("roger");
            }

        }, 0, 1000);

    } // end actionPerfomed()

} // end class

Can someone spot the mistake? I really don't understand what the problem is, I am new to timers though, so if something I do is really stupid please tell me.


Solution

  • Alright, so I somehow solved the problem: First of, I did change the util.Timer to a swing.Timer, however, that in itself did not help. Before, I was saving each image after it was drawn on my desktop, and then I was loading it onto the screen when it should be displayed. I played around with the code a little, and discovered that I don't need to save it but can actually reference it directly by making it static. When I did that, the problem disappeared. Here a code example of what I mean:

    Before:

    // In the drawing class
    save = new File(aster.filePath + aster.fileName + ".png");
    image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    try {
        ImageIO.write(image, "png", save); 
        } catch (IOException i) {
        System.out.println("Writing has encountered an error: \n" + i); }
    
    // In the displaying class
    load = new File(aster.filePath + aster.fileName + ".png");
    image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    try {
        image = ImageIO.read(load); 
        } catch (IOException i) {
        System.out.println("Reading has encountered an error: \n" + i); }
    ImageIcon icon = new ImageIcon(image);
    displayingJLabel.setIcon(icon);
    frame.add(displayingJLabel);
    

    After:

    // One static declaration and initialization of an BufferedImage in the drawing class
    public static BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    // Drawing Code
    
    // Accessing the image
    ImageIcon icon = new ImageIcon(DrawingClass.image);
    displayingJLabel.setIcon(icon);
    frame.add(displayingJLabel);
    

    Essentially, everything is the same except that the entire saving and reading process has been skipped, and instead of several local BufferedImage am I using only one static BufferedImage.

    I don't know for sure why this worked, but my guess is that the entire reading and writing process simply took too long for the Timer to go off every second, and this new method is a lot faster. I haven't tried to do the whole thing with a util.Timer again, but I think the swing.Timer probably has its fair share in solving this problem.