Seite 1 von 1

QListView mit großerer Datenmenge zu langsam

Verfasst: Mittwoch 5. August 2009, 11:08
von HerrHagen
Hallo,

ich hab kürzlich anggefangen mich in PyQt einzuarbeiten. Nun bin ich auf folgendes Problem gestoßen:
Ich möchte eine größere Datenmenge (ca. 100.000 Elemente) in einer Liste oder Tabelle darstellen. In dem Moment wo die Daten in die Liste übernommen werden, friert allerdings alles ein. Eine Reaktion der Oberfläche setzt erst nach ca. 10s. wieder ein. Danach lässt sich wieder normal mit der Oberfläche arbeiten. Scrollen und verändern der Fenstergröße gehen ebenfalls flüssig. Das ListWiew scheint an sich keine Probleme mit der Datenmenge zu haben, wenn sie erstmal eingetragen wurde.
Um das Problem zu verdeutlichen habe ich folgende Zeilen geschrieben (leicht abgewandelt von hier (ich weiß, schlechte Namen, Sternchen, etc.)):

Code: Alles auswählen

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyWindow(QWidget): 
    def __init__(self, *args): 
        QWidget.__init__(self, *args) 

        # create table
        list_data = list("ABCDEFG")
        lm = MyListModel(list_data, self)
        lv = QListView()
        lv.setModel(lm)

        # button
        test_button = QPushButton("Test")
        QObject.connect(test_button, SIGNAL("clicked()"), lm.fill_in_much_data)

        # layout
        layout = QVBoxLayout()
        layout.addWidget(lv)
        layout.addWidget(test_button)         
        self.setLayout(layout)
        
class MyListModel(QAbstractListModel): 
    def __init__(self, datain, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args) 
        self.listdata = datain
 
    def rowCount(self, parent=QModelIndex()): 
        return len(self.listdata) 
 
    def data(self, index, role): 
        if index.isValid() and role == Qt.DisplayRole:
            return QVariant(self.listdata[index.row()])
        else: 
            return QVariant()
    def fill_in_much_data(self):
        self.listdata = range(100000)
        self.reset()

if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.show() 
    sys.exit(app.exec_())
Nach drücken auf dem Button wird die Datenbasis auf 100.00 Elemente geändert und die Oberfläche friert ein. Wie kann ich das verhindern?
Ich hab es auch schon mit einem QListWidget probiert und die Elemente über addItem hinzugefügt. Die Schleife mit dem Hinzufügen der Elemente ist schnell (ca. 0.5) abgearbeitet. Danach friert die Oberfläche aber ebenso kurz ein.

MFG HerrHagen

Verfasst: Mittwoch 5. August 2009, 19:25
von BlackJack
@HerrHagen: Ich kenne mich mit Qt nicht aus, aber für so etwas haben GUI-Toolkits in der Regel etwas für "virtuelle" Listen/Tabellen, also wo man nicht alle Daten in die GUI füttert, sondern ein Modell übergeben kann, von dem die GUI dann dynamisch immer nur den Teil abfragt, der gerade sichtbar dargestellt werden soll.

Verfasst: Donnerstag 6. August 2009, 09:06
von mkesper
Ein Blick in die QListView Class Reference zeigt einen Parameter LayoutMode, der auf Batched gestellt werden kann. Noch wichtiger ist aber vermutlich das, was unter "Improving Performance" steht: uniformItemSizes auf True setzen. Ansonsten berechnet er ziemlich umständlich die Höhe jedere Zeile beim Einfügen, was natürlich die 10s Wartezeit erklärt.

Verfasst: Donnerstag 6. August 2009, 09:49
von HerrHagen
@mkallas: Danke, uniformItemSizes hats gebracht!

Verfasst: Donnerstag 6. August 2009, 18:34
von microkernel
@HerHagen:
Kannst du mal bitte die lösung in dein Beispiel Problem einfügen. Habe nähmlich das gleiche Problem aber versteh' leider nicht wie dieses "uniformItemSizes" funktioniert.

lg
microkernel(.)

Verfasst: Donnerstag 6. August 2009, 19:18
von cofi
PyQt Class Reference hat geschrieben:setUniformItemSizes (self, bool enable)
Ich wuerde sagen mit

Code: Alles auswählen

list_view.setUniformItemSizes(True)

Verfasst: Donnerstag 6. August 2009, 19:31
von HerrHagen
@microkernel: Die Eigenschaft lässt sich auch direkt im QtDesigner dem Element schon zuweisen (also einfach bei UniformItemSize ein Häkchen setzen) falls du damit deine Oberfläche erstellst.
Ich habe übrigens mal meine Liste durch eine Tabelle ersetzt. Dort treten auch in der Standartkonfiguration keine Geschwinkigkeitsprobleme auf.

Verfasst: Donnerstag 6. August 2009, 19:54
von microkernel
Vielen Dank!