1

So, I have an object that extends JPanel and displays dots in a matrix via paintComponent. The dots of the matrix can move, disappear or multiply given certain conditions, and I want to show their evolution over time automatically like so:

for(int i = 0; i < 100; ++i){

    matrix = calculateNextMatrix();    //Calculate possible movements, deaths or births of dots
    myGraphic.updateMatrix(matrix);    //Pass new dots to the JPanel object
    myGraphic.repaint();               //Draw new dots
    Thread.sleep(100);                 //Wait 0.1 seconds for next iteration (yes, this should be in a 
                                       //try-catch)
}

However, I only get drawn the last iteration after the loop is finished, and all the previous calls to repaint() are basically ignored. If I do the iterations only one at a time (for example, via a manual button press), I have no problem.

Is there any way to get multiple, periodic repaint calls automatically?

ThiroSmash
  • 13
  • 2
  • yes because repaint means , repaint it with that new thing , means remove everything which was there previously – Abhinav Chauhan Apr 11 '20 at 16:09
  • 1
    *Is there any way to get multiple, periodic repaint calls automatically?* - you use a `Swing Timer` to schedule the animation. This means your code needs to be restructure to pass a parameter to your code to indicate the current "state". Read the section from the Swing tutorial on [How to Use Timers](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) for more information. Check out:https://stackoverflow.com/a/33907282/131872 for an example. In your case you would invoke a method on your class to set the state to the next iteration and then invoke repaint(). – camickr Apr 11 '20 at 16:22
  • How are you starting your loop? If you are starting it on the EDT, say when a button is pressed, then you are occupying the EDT until your loop finishes, then the EDT can update, but you'll be at the end. – matt Apr 11 '20 at 16:53

1 Answers1

3

I had a simile problem with JComponent in my library and I found a solution with swing timer, I reported the java description of timer

In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread. However, you might use a general-purpose timer if you don't plan on touching the GUI from the timer, or need to perform lengthy processing.

You can use Swing timers in two ways:

  • To perform a task once, after a delay. For example, the tool tip manager uses Swing timers to determine when to show a tool tip and when to hide it.
  • To perform a task repeatedly. For example, you might perform animation or update a component that displays progress toward a goal.

I think you are in one of this cases.

Without a minimal example reproducible, I can use the my code.

You should create the Swing action listener, like this:

public class UpdateComponentListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            count += 10;
            timeLabel.setText(count + "");
            //The label call repaint
            //in your app you should be call the repaint

            //In your cases
            /*
                matrix = calculateNextMatrix();    //Calculate possible movements, deaths or births of dots
                myGraphic.updateMatrix(matrix);    //Pass new dots to the JPanel object
                myGraphic.repaint(); 
             */
        }
}

The timer constructor get in input the delay and the action listener, so you can build your timer, with this code:

Timer timer = new Timer(1000, new UpdateComponentListener());
timer.start();

You can stop, restart your timer, so you should be set how propriety the timer.

The GUI example:

enter image description here

I wrote the post and after I see the @camickr comment. I post the answer because my work is finished but, the comment answered your question.

I hope to have to build a food example

vincenzopalazzo
  • 1,487
  • 2
  • 7
  • 35
  • +1. I think you can also replace `repaint` with [`paintImmediately`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JComponent.html#paintImmediately-int-int-int-int-) as it *is useful if one needs to update the display while the current event is being dispatched* according to the docs. `repaint` is going to coalesce fast subsequent events and we don't want this behavior here. However only `JComponent`s support it. Not plain `Component`s. – gthanop Apr 12 '20 at 15:01
  • Thank for the upvote, I don't insert the details on repaint component because this depends on the structure of application. An example: if the JPanel is inside the JSplitPane, you should be call repaint on the updateUI() on JPanel and repaint on the SplitPane. I think that this depend to structure of the code. But yes, you can also call `paintImmediately`, thanks for the suggestion. – vincenzopalazzo Apr 12 '20 at 16:07
  • 1
    This is exactly what I needed, and well explained. Thanks! – ThiroSmash Apr 12 '20 at 18:48