【问题标题】:Catch QWidget real visibility status changing捕捉 QWidget 真实可见性状态变化
【发布时间】:2015-01-21 11:49:43
【问题描述】:

我有基于 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 包含一些 MiddleWidget,MiddleWidget 包含一些 ChildWidget。 MiddleWidget 也可以展开或折叠 - 折叠时,ChildWidgets 不“可见”(isVisible() == false)。

当用户上下滚动 ParentWidget 时,“可见”的 ChildWidgets (isVisible() == true) 实际上可能在屏幕上不可见。 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);
}

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

  • ChildWidgets 不知道如何更改其真实可见性并且依赖于 ParentWidget
  • 当ParentWidget的paint事件发生时,所有的ChildWidgets都应该被检查

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

【问题讨论】:

  • it's inefficiently to store all pictures in memory。你如何储存它们?
  • ChildWidget 有 QPixmap 字段
  • 足够好...像素图是否已经预先调整大小?请注意,隐藏小部件的绘制事件的缺失来自您面临的相同问题:一般来说,您不希望将 CPU 浪费在无论如何都隐藏的小部件上。
  • 是的,所有像素图都已预先调整大小。主要问题是我不能说将创建多少个 ChildWidget。在某些情况下,我看到它可以达到 200-300 个实例,这不是限制。因此,最好浪费 cpu 时间,而不是达到操作系统内存限制并导致应用程序故障。我只是认为可能有一些肮脏的深层 QWidget 秘密可以让我捕捉到最后的绘画事件或其他东西 :) 但是非常感谢您的回答!
  • 你看到我的编辑了吗? QPixmapCache 允许您为所有这些像素图使用共享缓存。我其实很期待自己使用它。

标签: c++ qt visibility qwidget qscrollarea


【解决方案1】:

QWidget 可以自己捕捉到改变它的真实可见性状态吗?

没有。

小部件知道它可见的唯一真正方法是在它执行paintEvent 时。但是小部件无法知道它真的不可见。

所以我想在什么时候加载图片 ChildWidget 确实出现在屏幕上并且用户可以看到它;什么时候 ChildWidget 消失,图片应该存储到文件并擦除 凭记忆。

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

编辑:我没用过,但是有QPixmapCache。您可以在ChildWidget 实例之间共享缓存并管理可用像素图的限制。
There is a tutorial on how to use a Qpixmap cache.

【讨论】:

  • 感谢您的回答。太糟糕了:(我不能使用 QGraphicsView,因为应用程序完全基于小部件;ChildWidgets 应该表现得像 QWidgets。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多