2016-12-29 1 views
0

ein QTableView Da ein Modell benutzerdefinierte Element zeigt mit einer einzigen Spalte aber viele Hunderte von Zeilen, die sectionResizeMode des vertikalen Kopf ResizeToContents Einstellung eine massive negative Auswirkungen hat auf Leistung.Performance-Problem mit QHeaderView :: ResizeToContents für vertikale Header in QTableView

Aus Debug-Gründen habe ich eine Ausgabe in der Methode des Elementmodells hinzugefügt, um zu sehen, welche Zeilen tatsächlich von der Ansicht abgefragt werden. Es stellt sich heraus, dass die Tabellenansicht tatsächlich jede einzelne Zeile in dem Modell abfragt, sobald es mit dem Resize-Modus zu ResizeToContents gesetzt zu machen braucht - egal, wie viele Zeilen selbst angezeigt.

Das folgende Codebeispiel gibt die folgende Ausgabe:

*** show *** 
query 0 
query 1 
query 2 
query 3 
    ... many lines trimmed ... 
query 495 
query 496 
query 497 
query 498 
query 499 
query 0 
query 1 
query 2 
query 3 
    ... many lines trimmed ... 
query 495 
query 496 
query 497 
query 498 
query 499 
query 0 
query 1 
query 2 
query 3 
query 4 
query 5 
query 6 
query 0 
query 1 
query 2 
query 3 
query 4 
query 5 
query 6 

Das heißt, der Blick scheint zunächst zweimal über alle Zeilen zu durchlaufen. Es iteriert dann über die Zeilen, die im Ansichtsfenster der Tabellenansicht tatsächlich sichtbar sind. Wie es zufällig auf meinem Bildschirm ist, sind sieben Reihen sichtbar.

Mit der Linie von Interesse Kommentar gesetzt, der Ausgang des Beispiel reduziert sich auf:

*** show *** 
query 0 
query 1 
query 2 
query 3 
query 0 
query 1 
query 2 
query 3 

Da die Zeilen jetzt ihre Standardhöhe haben, die als vorher etwas größer ist, nur vier Reihen jetzt sichtbar sind. Noch wichtiger ist, dass jetzt insgesamt nur acht Zeilen vom Modell abgefragt werden.

Warum dieses seltsame Verhalten?

SCCE

scce.pro:

QT += core gui widgets 
CONFIG += c++11 
TARGET = sscce 
TEMPLATE = app 
SOURCES += main.cpp 

main.cc:

#include <QAbstractItemModel> 
#include <QApplication> 
#include <QHeaderView> 
#include <QTableView> 
#include <QDebug> 

class Model: public QAbstractItemModel { 
    public: 
     int rowCount(const QModelIndex &parent) const { 
      return parent.isValid() ? 0 : 500; 
     } 

     int columnCount(const QModelIndex &parent) const { 
      return parent.isValid() ? 0 : 1; 
     } 

     QModelIndex parent(const QModelIndex &/* child */) const { 
      return QModelIndex(); 
     } 

     QModelIndex index(int row, int column, const QModelIndex &parent) const { 
      return parent.isValid() ? QModelIndex() : createIndex(row, column, Q_NULLPTR); 
     } 

     QVariant data(const QModelIndex &index, int role) const { 
      if (role == Qt::DisplayRole) 
       qDebug() << "query " << index.row(); 

      return (index.isValid() && (role == Qt::DisplayRole)) ? 
       QStringLiteral("Row %1").arg(index.row()) : QVariant(); 
     } 

     QVariant headerData(int section, Qt::Orientation orientation, int role) const { 
      return ((orientation == Qt::Vertical) && (role == Qt::DisplayRole)) ? section : QVariant(); 
     } 
}; 

int main(int argc, char *argv[]) { 
    QApplication app(argc, argv); 
    QTableView view; 
    view.setModel(new Model()); 

    /* Line of interest: */ 
    view.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); 

    qDebug() << "*** show ***"; 
    view.show(); 
    return app.exec(); 
} 

Antwort

0

ResizeToContents setzt die gleiche Höhe für alle Zeilen, mehr noch, setzt er die Höhe, die am besten passt alle Zeilen, so es muss die ganze Tabelle abfragen.

Wenn Reihen konstant sind und Sie sind in der Lage, ihre Höhe manuell zu bestimmen, können Sie versuchen, die minimal benötigte Höhe zu speichern, dann einen Ereignisfilter installiert zum Ändern der Größe und manuell die Höhe eingestellt. Andere Szenarien sind ähnlich, aber komplexer zu handhaben (Sie müssen beim Hinzufügen/Entfernen/Bearbeiten von Zeilen und so weiter Verbindungen mit Signalen herstellen).

Verwandte Themen