Details
-
Bug
-
Resolution: Incomplete
-
P3: Somewhat important
-
None
-
5.9.1
-
None
-
MSVC 2017, tested on Windows 7/10
Description
The problem occurs when attempting to create an item delegate with custom textual content to be used in QListView. Changing the base class to QStyledItemDelegate does not improve the speed. It is similar to --, however in this particular case the performance issue exists even if QPainter::setFont() is not used. The Qt examples on item delegates do not help much, as they show how to draw controls, not just text.QTBUG-54180
The example given below illustrates the problem. After showing the application's window, the content of the QListView is shown with a slight, but noticable delay. In some cases this delay lasts up to several seconds. When either of
view->setItemDelegate(new Delegate(this));
or
painter->drawText(0, option.rect.y() + 18, index.data().toString());
are commented there is no observable delay between showing the window and the content of the QListView.
MainWindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QListView> #include <QStandardItemModel> #include "Delegate.h" class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); }; #endif // MAINWINDOW_H
MainWindow.cpp
#include "MainWindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { QStandardItemModel *model = new QStandardItemModel(this); QListView *view = new QListView(this); view->setModel(model); view->setItemDelegate(new Delegate(this)); for (int n = 0; n < 100; n++) { model->appendRow(new QStandardItem("Test " + QString::number(n))); } setCentralWidget(view); }
Delegate.h
#ifndef DELEGATE_H #define DELEGATE_H #include <QAbstractItemDelegate> #include <QPainter> class Delegate : public QAbstractItemDelegate { Q_OBJECT public: explicit Delegate(QObject *parent = nullptr); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; }; #endif // DELEGATE_H
Delegate.cpp
#include "Delegate.h" Delegate::Delegate(QObject *parent) : QAbstractItemDelegate(parent) { } void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->drawText(0, option.rect.y() + 18, index.data().toString()); painter->drawLine(0, option.rect.y() + 19, option.rect.width(), option.rect.y() + 19); } QSize Delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { return QSize(0, 20); }
EDIT
Researching further, I've found out, that the same issue exists when drawing in the paint event of a QWidet's subclass. Here is a minimal example to demonstrate this:
MainWindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QApplication> #include <QCommonStyle> #include <QStyleOptionFrame> #include <QPainter> class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); }; class CustomWidget : public QWidget { Q_OBJECT public: explicit CustomWidget(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *); }; #endif // MAINWINDOW_H
MainWindow.cpp
#include "MainWindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setCentralWidget(new CustomWidget(this)); } CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent) { } void CustomWidget::paintEvent(QPaintEvent *) { QRect g = geometry(); QPainter p(this); QStyleOptionFrame optFrame; QStyleOptionButton optButton; QString str = "Test"; optButton.rect = g; optButton.text = str; optFrame.rect = g.adjusted(10, 10, -10, -10); optFrame.features = QStyleOptionFrame::Rounded; static const QPointF points[4] = { QPointF(10.0, 80.0), QPointF(20.0, 10.0), QPointF(80.0, 30.0), QPointF(90.0, 70.0) }; p.drawRect(g.adjusted(1, 1, -2, -2)); p.drawPolygon(points, 4); QApplication::style()->drawPrimitive(QStyle::PE_Frame, &optFrame, &p, this); // The lines below involve painting of text. Uncommenting any of them leads // to a delay between showing the app's window and the content of the widget // QApplication::style()->drawControl(QStyle::CE_PushButton, &optButton, &p, this); // QApplication::style()->drawItemText(&p, g, Qt::AlignLeft, QPalette(Qt::red), true, str); // p.drawText(20, 40, str); }