【问题标题】:Simple way to get all visible items in the QListView获取 QListView 中所有可见项目的简单方法
【发布时间】:2012-03-22 07:48:24
【问题描述】:

我正在尝试使用 Qt 框架开发一个图片库应用程序。应用程序从所选文件夹加载所有图像,并使用 QListView 控件显示这些图像。 但现在我想通过仅加载用户可见的图像来减少内存消耗。由于没有直接功能可以获取视图中的所有可见项目,因此我无法实现这一点。

【问题讨论】:

    标签: qt qlistview


    【解决方案1】:

    您可以使用indexAt 函数获取列表视图的可见项。有关更多详细信息和示例,您可以查看以下文章:

    http://qt-project.org/faq/answer/how_can_i_get_hold_of_all_of_the_visible_items_in_my_qlistview

    【讨论】:

      【解决方案2】:

      我找到了!您必须将列表小部件的垂直滚动条连接到信号:

      connect(ui->listWidget->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(launch_timer()));
      

      每次用户滚动时,都会忽略 valuechanged(int) 信号!问题是,您不应该每次 listwidget 的垂直滚动条的值发生变化时都运行 webclectic 在这个问题中提供的代码,因为在这么短的时间内运行这么多代码,程序将无响应。

      因此,您必须有一个单次计时器并将其指向上面 webclectic 发布的功能。当 launch_timer() 被调用时,你会做这样的事情:

        if(timer->isActive()){
           timer->stop();
           timer->start(300);
         }
         else
            timer->start(300);
      

      timer 的 timeout() 信号会连接到 webclectic 所说的 slot。这样,如果用户一直快速向下滚动,则只会更新最后的项目。通常,它会更新任何可见时间超过 300 毫秒的内容!

      【讨论】:

        【解决方案3】:

        我认为您需要实现自己的模型(查看 QAbstractListModel 文档),这样您就可以决定何时必须加载更多图像以显示并可能释放一些变得不可见的图像.

        【讨论】:

          【解决方案4】:

          虽然这在Qt 4 中并不是那么简单,但是 在下面复制总是很简单:

          #include <private/qlistview_p.h>
          
          class QListViewHelper : public QListView
          {
              typedef QListView super;
              inline QListViewHelper() {} //not intended to be constructed
          public:
              inline static QVector<QModelIndex> indexFromRect(const QListView *view,
                                                                           const QRect &rect)
              {
                  const QListViewPrivate *d = static_cast<const QListViewPrivate *>(QObjectPrivate::get(view)); //to access "QListViewPrivate::intersectingSet(...)"
                  const QListViewHelper *helper = static_cast<const QListViewHelper *>(view); //to access "QListView::horizontalOffset()"
                  return d->intersectingSet(rect.translated(helper->horizontalOffset(), helper->verticalOffset()), false);
              }
              inline static QVector<QModelIndex> visibleItems(const QListView *view)
                  { return indexFromRect(view, view->rect()); }
          
              inline static QModelIndex firstVisible(const QListView *view)
                  { return visibleItems(view).value(0); }
              inline static QModelIndex lastVisible(const QListView *view) {
                  const QVector<QModelIndex> &items = visibleItems(view);
                  return items.value(items.count() - 1);
              }
          };
          
          void ourTest(const QListView *view) {
              QModelIndex &index = QListViewHelper::firstVisible(view);
              qDebug("QListViewHelper: first visible row is %d", index.row());
          
              index = QListViewHelper::lastVisible(view);
              qDebug("QListViewHelper: last visible row is %d", index.row());
          }
          

          用法: QModelIndex &index = QListViewHelper::firstVisible(listViewPointerHere)

          注意:由于它确实使用了 Qt 4.8 私有标头,因此它在以后的版本中可能不再工作,需要进行一些更改。

          【讨论】:

            【解决方案5】:

            您可以跟踪每个绘制事件绘制的所有元素。我使用了委托并重载了绘制事件。

            我还在视图中重载了绘制事件。在此调用期间,所有可见的代理都将获得一个绘制事件。

            如果您只需要知道一个项目是否可见,您可以在 view->paintEvent 中增加一个帧计数并在委托项目中设置该数字。该项目是否可见,该项目与当前帧号匹配。

            如果您需要所有可见项目的列表,请清除 view->paintEvent 中的可见项目列表并将 int delegate->paintEvent 中的每个项目添加到可见项目列表中。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-07-12
              • 1970-01-01
              • 2014-09-22
              相关资源
              最近更新 更多