To restart painting after clicking button in frame

Viewed 67

I am trying to restart the painting after clicking restart button in the frame.
But after clicking the button, it seems that two animation start working together as you can see in the gif below: OutputGIF

After clicking the button, two count label seems to be working simultaneously but the painting remains the same and doesn't start from initial position.
I have commented across the action listener of button.
CODE:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.*;

class Count {
    private int num;

    public Count() {
        this.num = 1;
    }

    // Generate Next Number
    public void generate(int currentNumber) {
        this.num = currentNumber;
        this.num += 1;
    }

    public int getNumber() {
        return this.num;
    }
}

interface Callback {
    public void action(int cnt);
}

class Panel extends JPanel {
    private final BufferedImage image;
    private Count count;
    private Callback onUpdate;


    public void setOnUpdateAction(Callback action) {
        this.onUpdate = action;
    }

    public Panel() {
        this.image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
        this.count = new Count();
        Timer timer = new Timer(0, ae -> createImage(image));
        timer.setDelay(1000);
        timer.start();
    }

    public void createImage(BufferedImage image) {
        Graphics g = image.getGraphics();

        int number = this.count.getNumber();

        // Set field on frame which will be added to bottomPanel
        for (int i = 0; i < (number * 20); i++) {
            for (int j = 0; j < (number * 20); j++) {
                g.setColor(Color.GRAY);
                g.fillRect(i, j, 20, 20);
                g.setColor(Color.GREEN);
                g.drawRect(i, j, 20, 20);
            }
        }

        // Generating next number
        this.count.generate(number);
        onUpdate.action(this.count.getNumber());
        repaint();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);
    }
}

class GUI extends JFrame {
    private JPanel leftPanel;
    private JPanel rightPanel;
    private JLabel countLabel;
    private JButton restartButton;

    public GUI() {

        /*Panels*/
        leftPanel = new JPanel();
        rightPanel = new JPanel();
        
        /* Button */
        restartButton = new JButton(UIManager.getIcon("FileView.directoryIcon"));
        
        leftPanel.add(restartButton);
        
        updateLabel(0);

        Panel matrixPanel = new Panel();
        matrixPanel.setPreferredSize(new Dimension(300, 300));

        matrixPanel.setOnUpdateAction(new Callback() {
            @Override
            public void action(int cnt) {
                countLabel.setText("Count #" + cnt);
            }
        });
        
        /* Restart Button, Action Listener */
        restartButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Panel mPanel = new Panel();
                mPanel.setPreferredSize(new Dimension(300, 300));
                System.out.println("New Defined");
                mPanel.setOnUpdateAction(new Callback() {
                    @Override
                    public void action(int cnt) {
                        countLabel.setText("Count #" + cnt);
                    }
                });
                rightPanel.add(mPanel);
            }
            
        });
        /* Action Listener Part End */

        rightPanel.add(matrixPanel);
        
        setLayout(new GridLayout(1, 2));
        
        add(leftPanel);
        add(rightPanel); 

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        pack();
    }

    public void updateLabel(int number) {
        /*Label - 1*/
        countLabel = new JLabel();
        countLabel.setName("CountLabel");
        countLabel.setText("Count #" + number);
        countLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
        countLabel.setBounds(10, 5, 300, 20);

        leftPanel.add(countLabel);
    }
}

public class NumberPresentation {
    public static void main(String[] args) {
        new GUI().setVisible(true);
    }
}

In the action listener of button, I again define the object of Panel class and add it to the right panel which is added into the frame.

How can I program the button so that it will restart the painting after clicking it?

1 Answers

When button pressed (within its assigned action listener):

  • Call .stop() on the Swing Timer
  • Create a new BufferedImage and assign it to your BufferedImage variable
  • Re-set the count object back to starting state and reset any state fields that are used to do your drawing
  • Then restart the Swing Timer

The bottom line and general goal is that you want to return the GUI to its original state, however that "state" is defined. Usually this means returning key state-fields back to their original values and recreating any animation loops that were started (here, your Swing Timer).

Related