You can do it in the paint(Graphics &) method. If it’s a big calculation you can start the calculation either on a background thread and issue a repaint() when done. Similar to what Raymond Chen explains here.
On Windows, using the paint callback has the advantage that your GUI will definitely be redrawn, even if your message thread is busy. Windows won’t generate WM_PAINT unless your message queue is empty.
ComponentMovementWatcher will do this for you - it adds listeners to the component tree, and is used for things like heavyweight embedded windows, so it needs to know when the visibility changes.
I use some kind of floating window technique, a component can be a child of a component, but also can be dynamically removed and be a child of another component, in another window.
To avoid unnecessary recalculations, when the parents component will be swapped, the current isShowing() State will be checked after a delay, i made a handy detector Class for this very special kind of use-case:
class AppearsOnScreenDetector
{
public:
AppearsOnScreenDetector(Component* component)
: pimpl(*this, component)
{
};
virtual ~AppearsOnScreenDetector()
{
};
/** This callback happens when the component's first appears on the screen, possibly due to
one of its parents being made visible or invisible, or if it appears on screen again.
If a component is not appearing only for a very short moment of time
the callback will not happen.
*/
virtual void appearsOnScreenCallback() = 0;
private:
struct Pimpl : public Timer, public ComponentMovementWatcher
{
Pimpl(AppearsOnScreenDetector& owner_,Component* component)
: ComponentMovementWatcher(component),owner(owner_),lastShowingState(component->isShowing())
{
};
~Pimpl(){};
virtual void componentMovedOrResized (bool , bool ) override {};
virtual void componentPeerChanged() override {};
virtual void componentVisibilityChanged() override
{
startTimer(10);
}
void timerCallback() override
{
stopTimer();
if (getComponent()==nullptr) return;
bool newShowingState=getComponent()->isShowing();
if (newShowingState!=lastShowingState)
{
if (newShowingState)
{
owner.appearsOnScreenCallback();
};
lastShowingState=newShowingState;
};
};
AppearsOnScreenDetector& owner;
bool lastShowingState;
};
Pimpl pimpl;
};