QListView mit großerer Datenmenge zu langsam

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

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
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.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

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.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

@mkallas: Danke, uniformItemSizes hats gebracht!
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

@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(.)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

PyQt Class Reference hat geschrieben:setUniformItemSizes (self, bool enable)
Ich wuerde sagen mit

Code: Alles auswählen

list_view.setUniformItemSizes(True)
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

@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.
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

Vielen Dank!
Antworten