6

I have a code like that:

// In MyPanel.java
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    // Draw something
    mypanel_count++;
}

// In Test.java
public void testLargeData()
{
    while (notDone)
    {
        panel.repaint();
        // do huge work
        test_count++;
        System.out.println("Test_count: " + test_count + ", MyPanel_count: " + mypanel_count);
    }
}

// Output !!!
Test_count: 752, MyPanel_count: 23
Test_count: 753, MyPanel_count: 23
Test_count: 754, MyPanel_count: 23
Test_count: 755, MyPanel_count: 24

But when I change panel.repaint() to panel.paintComponent(panel.getGraphics()), the out is right:

Test_count: 752, MyPanel_count: 752
Test_count: 753, MyPanel_count: 753
Test_count: 754, MyPanel_count: 754
Test_count: 755, MyPanel_count: 755

Why? paintComponent method works, but sometimes it's blind, so I don't want to use it. Anybody can give me some suggestions? Thanks!

Bood Carley
  • 538
  • 1
  • 4
  • 15
  • http://stackoverflow.com/questions/9389187/difference-between-paint-paintcomponent-and-paintcomponents-in-swing. – Raghunandan Nov 19 '12 at 12:00
  • @Raghunandan: thanks for your answer, but it isn't my trouble. – Bood Carley Nov 19 '12 at 12:02
  • did you tried [JComponent.html#paintImmediately(int, int, int, int)](http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#paintImmediately%28int,%20int,%20int,%20int%29) – mKorbel Nov 19 '12 at 12:05
  • paintImmediately(...) as suggested by mKorbel should help.http://stackoverflow.com/questions/4120528/repaint-in-a-loop. I know this is not an answer. But i guess the solution is threads. – Raghunandan Nov 19 '12 at 12:18
  • `SwingUtilities.invokeLater` don't work for me. – Bood Carley Nov 19 '12 at 12:26
  • @Bood Carley question in this form isn't answearble, there are a few code, any important methods for comparisions test, nor an SSCCE, what do you really expecting, – mKorbel Nov 19 '12 at 12:49
  • @mKorbel: I want to find a solution for "re-paint" immediately, not blind, that all. `paintImmediately` sometimes blind. – Bood Carley Nov 19 '12 at 13:00
  • @Bood Carley we can works with given infos, otherwise this one will be only your personal issue, nobody knows ... whats representing code posted in your questiod, ideas, scenario, fly to the moon ???, for why, what please, for better help sooner post an [SSCCE](http://sscce.org/), short, runnable, compilable, just about a.m. described issue, – mKorbel Nov 19 '12 at 13:05
  • @Bood Carley in all cases repaint should be last code line, prepare all Object, put those Object to the Array, inside paintComponent loop in Array, then to call repaint, everything, any another code line moreover is useless, simple prepare everything before, no idea about – mKorbel Nov 19 '12 at 13:08
  • @mKorbel: Thanks for your suggestion. – Bood Carley Nov 19 '12 at 13:25

3 Answers3

13

If you read the documentation of repaint carefully, you will notice that it states that (emphasis mine):

If this component is a lightweight component, this method causes a call to this component's paint method as soon as possible. Otherwise, this method causes a call to this component's update method as soon as possible.

This means that AWT/Swing is allowed to optimize repainting by merging repaints that are requested in a rapid succession. There is also a repaint(long time) method, which allows you to control how long AWT/Swing is allowed to wait with fullfilling your repaint request. It might still merge requests though, especially if you do them in a loop.

It might be helpful to read the article "Painting in AWT and Swing", which tries to explain the various concepts involved.

To get the panel repainted for every iteration, you would have to wait for a paint to happen and then proceed with your loop. This means you need some synchronization between your processing thread (the loop) and the AWT/Swing thread. As a rough idea, you could for example wait() on the panel object at the end of your loop if it has not been repainted since the last call to repaint() and call notifyAll() at the end of your panel's paintComponent() method. However, this can be tricky to implement right, so you should only do this if you really need "real-time" redrawing of your component. As an alternative, paintImmediately(...) could be used, but you would have to do all your processing in the event dispatching thread, like this:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        while(notDone) {
            // Do your processing
            panel.paintImmediately(...);
        }
    }
});

Note that this will stop any event processing including mouse and keyboard input from being processed while your loop is running. You can read more about Swing and Threading in "Concurrency in Swing"

Simon Lehmann
  • 9,924
  • 4
  • 39
  • 52
  • `repaint(long time)` does about nothing on my system, there is still a wait of 0.5 seconds or something similar (I know, as I'm implementing a clock). The whole Swing timing is shit, at least on Ubuntu, and that's on a AMD 3600X which has a zero load on not just one but all cores. – Maarten Bodewes Nov 26 '20 at 23:47
1

As the other answers say: it's a problem of when AWT is calling paint().

If you do some work that needs information from painted/layouted Components, what helps is also to put this work into a worker thread that waits until the painting is done.

In your case that would be something like:

panel.repaint();

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        // do huge work
        test_count++;
        System.out.println("Test_count: " + test_count 
             + ", MyPanel_count: " + mypanel_count);
    }
});

Although I'm not sure how it would behave in your while loop.

Terry
  • 12,591
  • 12
  • 51
  • 84
0

understand that you do not have complete control over if or when paint(...) get's called, and that repaint() calls are only a suggestion to the JVM to paint. If too many repaint() requests come in and they stack up as yours are doing, then they will be combined

refer : https://stackoverflow.com/a/13256847/1423083

Community
  • 1
  • 1
Mukul Goel
  • 8,317
  • 5
  • 34
  • 72