我需要计算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个最大项目。也许有人可以提出建议,如何正确计算?
我的想法是使用QListView::indexAt()(从QAbstractView
继承)获得行的索引
列表视图视口的数量,并根据它们的不同来确定可见项目的数量。
为了检查这一点,我制作了一个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中构建并测试:
在实现了我的想法后,我在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(); }