Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-62309

Drawing text with QPainter in a reimplementation of the paint() method of a QAbstractItemDelegate's subclass is noticably slower than drawing shapes and pixmaps.

    XMLWordPrintable

Details

    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 -QTBUG-54180-, 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.

      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);
      }
      

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            esabraha Eskil Abrahamsen Blomfeldt
            scopchanov Michael Scopchanov
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes