捕捉 QWidget 真实可见性状态变化

Catch QWidget real visibility status changing

我有基于 C++ Qt 5.2.1 的项目,其中一个图形组件如下所示:

 +-- 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 ---------------+ |  | |
 | | | ...                          | |  | |
 +-----------------------------------------+

所以,ParentWidget是QScrollArea,其他都是QWidgets。 ParentWidget 包含一些MiddleWidgets,MiddleWidget 包含一些ChildWidgets。 MiddleWidget 也可以展开或折叠 - 折叠时,ChildWidgets 不是 "visible" (isVisible() == false)。

当用户向上和向下滚动 ParentWidget 时,"visible" (isVisible() == true) 的 ChildWidget 实际上可能不会在屏幕上真正可见。 ChildWidgets 包含图片,将所有图片存储在内存中效率低下。所以我想在 ChildWidget 真正出现在屏幕上并且用户看到它时加载图片;当 ChildWidget 消失时,图片应存储到文件并从内存中删除。

现在我可以通过 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);
}

但是这种方式显然有其缺点:

所以我的问题是:QWidget 能否捕捉到改变其真实可见性状态本身?如果不是,也许有更有效的方法来实现这种行为?

can QWidget catch changing its real visibility state itself?

没有

小部件知道它可见的唯一真实方法是在它执行时 paintEvent。但是小部件没有办法知道它真的不可见。

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.

你看过Graphic view framework了吗?它旨在高效处理大量项目,并且处理速度非常快。

编辑:没用过,不过有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.