serg.v.gusev
serg.v.gusev

Reputation: 511

Catch QWidget real visibility status changing

I have C++ Qt 5.2.1 based project and one of graphic component looks like:

 +-- ParentWidget == QScrollArea ----------+
 |                                       |^|
 | +-- MiddleWidget == QWidget -------+  | |
 | | (>) Expand/collapse button       |  | |
 | |----------------------------------|  | |
 | |                                  |  | |
 | | +-- ChildWidget ---------------+ |  | |
 | | | ...                          | |  |0|
 | | +------------------------------+ |  |0|
 | |                                  |  |0|
 | | +-- ChildWidget ---------------+ |  |0|
 | | | ...                          | |  |0|
 | | +------------------------------+ |  |0|
 | |                                  |  |0|
 | | ...                              |  |0|
 | +----------------------------------+  |0|
 |                                       |0|
 | +-- MiddleWidget == QWidget -------+  |0|
 | | (>) Expand/collapse button       |  | |
 | |----------------------------------|  | |
 | |                                  |  | |
 | | +-- ChildWidget ---------------+ |  | |
 | | | ...                          | |  | |
 | | +------------------------------+ |  | |
 | |                                  |  | |
 | | +-- ChildWidget ---------------+ |  | |
 | | | ...                          | |  | |
 +-----------------------------------------+

So, ParentWidget is QScrollArea, others are QWidgets. ParentWidget contains some MiddleWidgets, MiddleWidget contains some ChildWidgets. MiddleWidget also can be expanded or collapsed - when collapsed, ChildWidgets are not "visible" (isVisible() == false).

When user scrolls ParentWidget up and down, ChildWidgets which are "visible" (isVisible() == true) can actually be not real visible on screen. ChildWidgets contains pictures, and it's inefficiently to store all pictures in memory. So i want to load picture when ChildWidget is really appears on screen and user sees it; when ChildWidget disappears, picture should be stored to file and erased from memory.

Right now i can check such real visibility changing via ParentWidget:

bool ParentWidget::eventFilter(QObject *object, QEvent *event)
{
    if (object == widget() && event->type() == QEvent::Paint) {
        for (auto middle : _middles) {
            for (auto child : middle->childs()) {
                if (!child->visibleRegion().isEmpty()) {
                    ...
                }
            }
        }
    }

    return QScrollArea::eventFilter(object, event);
}

But this way obviously has its disadvantages:

So my question is: can QWidget catch changing its real visibility state itself? If no, maybe there is more effective way to implement such behaviour?

Upvotes: 4

Views: 1793

Answers (1)

UmNyobe
UmNyobe

Reputation: 22890

can QWidget catch changing its real visibility state itself?

No.

The only real way for a widget to know it is visible is when it executes paintEvent. But the widget has no way to know it is really not visible.

So i want to load picture when ChildWidget is really appears on screen and user sees it; when ChildWidget disappears, picture should be stored to file and erased from memory.

Did you look at the Graphic view framework? It is designed to efficiently handle a large number of items, and to do it very fast.

Edit: I have never used it, but there is QPixmapCache . You can share a cache between ChildWidget instances and manage the limit of pixmaps available.
There is a tutorial on how to use a Qpixmap cache.

Upvotes: 4

Related Questions