Callback when a component or one of its parents become visible


#1

Its possible to get a callback when a component or one of its parents become visible?

I have a component which contains a graphical information which needs to be calculated from time to time.

Most of time the component is “visible”, but added to a parent which is not visible.

Is it possible to get a callback when the component becomes visible to screen.

void visibilityChanged() will be called only if the component itself becomes visible.

isShowing() is the right information, but not a callback?

Something like void showingStateChanged() is missing, or not?


#2

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.


#3

I made a similar feature request in TYOOL 2006 Version 1.38

I guess it’s not happening :frowning:


#4

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.


#5

Thanks for your tips!

ComponentMovementWatcher should do the job.

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;
};