QListView视图中的最大项目数

问题描述 投票:0回答:1

我需要计算QListView当前视图中的最大项目数。我写了这样的代码:

void MyListView::resizeEvent(QResizeEvent *event)
{
    QListView::resizeEvent(event);

    QFontMetrics fm (this->font());
    int fontHeight = fm.lineSpacing();

    QRect cr = contentsRect();
    int windowHeight = cr.bottom() - cr.top();

    int maxItemsCount = windowHeight / fontHeight;
    qDebug()<<"max items in view: "<< maxItemsCount;

}

但是计算出的最大物品数量不正确。例如。就我的窗口高度和字体高度而言,实际上当前视图有28个项目,因此我可以看到32个最大项目。也许有人可以提出建议,如何正确计算?

qt qt5 qlistview
1个回答
0
投票

我的想法是使用QListView::indexAt()(从QAbstractView继承)获得行的索引

  1. [左上角
  2. 左下角

列表视图视口的数量,并根据它们的不同来确定可见项目的数量。

为了检查这一点,我制作了一个MCVE testQListViewNumVisibleItems.cc

// Qt header:
#include <QtWidgets>

class ListWidget: public QListWidget {

  public:
    ListWidget(QWidget *pQParent = nullptr): QListWidget(pQParent) { }
    virtual ~ListWidget() = default;
    ListWidget(const ListWidget&) = delete;
    ListWidget& operator=(const ListWidget&) = delete;

    int getNumVisibleItems() const
    {
      const QSize size = viewport()->size();
      const QModelIndex qMIdx0 = indexAt(QPoint(0, 0));
      const QModelIndex qMIdx1 = indexAt(QPoint(0, size.height() - 1));
      //qDebug() << "qMIdx0:" << qMIdx0 << "qMIdx1:" << qMIdx1;
      return qMIdx0.isValid()
        ? (qMIdx1.isValid() ? qMIdx1.row() : count()) - qMIdx0.row()
        : 0;
    }
};

const int MaxItems = 20;

// main application
int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  ListWidget qLst;
  qLst.resize(200, 200);
  qLst.show();
  // timer to populate list view
  using namespace std::chrono_literals;
  QTimer qTimer;
  qTimer.setInterval(1000ms);
  // install signal handlers
  int n = 0;
  QObject::connect(&qTimer, &QTimer::timeout,
    [&]() {
      qLst.addItem(QString("item %0").arg(++n));
      qDebug() << "Visible items:" << qLst.getNumVisibleItems();
      if (n >= MaxItems) qTimer.stop();
    });
  // runtime loop
  qTimer.start();
  return app.exec();
}

CMakeLists.txt

project(QListViewNumVisibleItems)

cmake_minimum_required(VERSION 3.10.0)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(Qt5Widgets CONFIG REQUIRED)

include_directories("${CMAKE_SOURCE_DIR}")

add_executable(testQListViewNumVisibleItems testQListViewNumVisibleItems.cc)

target_link_libraries(testQListViewNumVisibleItems Qt5::Widgets)

[已在Windows 10的VS2017中构建并测试:

snapshot of testQListViewNumVisibleItems.exe (animated)


在实现了我的想法后,我在Google上搜索了一下,可能会看到其他方法。 (我承认我应该做过。)

因此,我发现了以下可能的重复项:

SO: Simple way to get all visible items in the QListView

接受的答案只包含indexAt的提示以及指向Qt-FAQ文章的链接:

How can i get hold of all of the visible items in my QListView?

为了获得QListView http://doc.qt.io/qt-5/qlistview.html中的可见项,您可以使用indexAt()http://doc.qt.io/qt-5/qlistview.html#indexAt对其进行迭代。您可以使用indexAt(QPoint(0,0))来获取第一个可见项,然后为了在下一个位置获取索引,然后使用visualRect()http://doc.qt.io/qt-5/qlistview.html#visualRect来查找对itemAt()的下一次调用应该。这个职位是:

visualRect.y() + visualRect.height() + 1 effectively.

请参见以下示例:

#include <QtGui>
QList <QModelIndex>myList;

class ListView : public QListView
{
  Q_OBJECT
public:
  ListView()
  {
    QStringListModel *myModel = new QStringListModel(this);
    QStringList list;
    list << "a" << "b" <<"c" <<"d" <<"e" <<"f" <<"g" <<"h" <<"i" <<"j" <<"k";
    myModel->setStringList(list);
    setModel(myModel);
    QTimer::singleShot(3000, this, SLOT(test1()));
  }
  public slots:
    void test1()
    {

      QModelIndex firstIndex = indexAt(QPoint(0, 0));
      if (firstIndex.isValid()) {
        myList << firstIndex;
      } while (viewport()->rect().contains(QPoint(0, visualRect(firstIndex).y() + visualRect(firstIndex).height() + 1 ))) {
        firstIndex = indexAt(QPoint(0, visualRect(firstIndex).y() + visualRect(firstIndex).height() + 1 ));
        myList << firstIndex;
      }
      qDebug() << myList.count() << "are visible";
    }
};

#include "main.moc"

int main(int argc, char** argv)
{
  QApplication app(argc, argv);
  ListView window;
  window.resize(100, 50);
  window.show();
  return app.exec();

}
© www.soinside.com 2019 - 2024. All rights reserved.