4

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:

  • ChildWidgets don't know about change their real visibility and depends on ParentWidget
  • when ParentWidget's paint event occurs, all ChildWidgets should be checked

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?

serg.v.gusev
  • 501
  • 4
  • 13
  • `it's inefficiently to store all pictures in memory`. How do you store them? – UmNyobe Jan 21 '15 at 13:02
  • ChildWidget has QPixmap field – serg.v.gusev Jan 21 '15 at 14:21
  • Good enough... Is the pixmap already pre-resized ? Note that the absence of a paintevent for hidden widget come from the same problem you face: in general you dont want to waste cpu on a widget which is hidden anyway. – UmNyobe Jan 21 '15 at 17:12
  • Yes, all pixmaps are already pre-resized. Main problem is that i can't say how many ChildWidgets will be created. In some cases i've seen it can be up to 200-300 instances and this is not the limit. So it's better to waste cpu time rather than reach the OS memory limits and get application fault. I just thought that there can be some dirty deep QWidget secrets that allow me to catch last paintevent or something :) However thank you very much for your answers! – serg.v.gusev Jan 22 '15 at 10:48
  • did you see my edit? `QPixmapCache` allow you to use a shared cache for all those pixmaps. I actually look forward to use it myself. – UmNyobe Jan 22 '15 at 11:21

1 Answers1

3

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.

UmNyobe
  • 22,539
  • 9
  • 61
  • 90
  • Thank you for answer. Too bad :( I can't use QGraphicsView as application is completely widget-based; ChildWidgets should behave as QWidgets. – serg.v.gusev Jan 21 '15 at 14:19