Force component to repaint itself

windows
gui

#1

Hello, I’m using a HighResolutionTimer to repaint multiple child components at a given interval.

According to the documentation, calling repaint() does not do any repainting immediately, it still waits for the OS to send a Paint message. This works fine in most cases but sometimes the animation will stutter at high frame rates.

Is there any way to manually send a paint message to the window to force a redraw? I noticed that mouse events will force a redraw to occur.


#2

You probably shouldn’t be calling repaint() from a HighResolutionTimer to begin with, since that timer runs in its own thread…And GUI operations are not permitted from other threads. If you are using MessageManagerLock to work around that limitation, then you’ve probably negated the use of HighResolutionTimer anyway.


#3

Thanks for the advice I will re-think my approach. I just learned about the AnimatedAppComponent class, I didn’t know about it until now.


#4

A possible pitfall is that in Windows, paint messages (aka. WM_PAINT) are never queued. You will get a paint message only if there is a repaint pending and the message queue is empty when you try to get the next message. So as long as the GUI thread is busy handling other messages your window will never get repainted.

There’s generally two ways to work around this: The first is to make sure your GUI thread is not busy all the time. What frequency are you using for that timer?

The second is to make sure the GUI thread only gets busy once a paint event is delivered. So either send messages triggering further work from the paint() call, for instance, the timer callback could cancel the timer, and the paint callback could start the timer again. Or change the structure so some of the heavier lifting is done by the paint call.


#5

I’ll try to explain my dilemma with a bit more detail.

I have 10 instances of the same component on the screen, sometimes animated individually and sometimes all at once. Their speed is always the same so only one timer is needed. ~30 fps is fine but anything lower will look choppy and undesirable.

My drawing code is pretty complex, with lots of calls to drawImage, drawText, fillEllipse, and addArc/strokePath. I’ve optimized this code to my best ability by drawing to bitmap buffers first, and only updating those bitmaps when required. My paint() method just draws the bitmaps layered on top of each other. This is already very efficient, I can even bump the frame rate up to 60 without performance loss, but repaint() does not always fire an actual re-paint so it stutters from time to time.

I tried using AnimatedAppComponent but it was extremely slow in comparison, because I was using a single timer to handle all 10 components instead of individual timers for each one. Besides after glancing at the source code for AnimatedAppComponent I realized its using the exact same approach, just a Timer that calls repaint() periodically. The only difference is I was using a HighResolutionTimer.

I even tried using OpenGLAppComponent to work around this issue, but it has its downfalls too. Mainly because drawing to a texture and then rendering the texture is less efficient than drawing directly to the screen, bitmap buffers work just as well. I didn’t have this stuttering issue with OpenGL but I’d rather not use it if I don’t need to.