python - PyQT QTableWidget अत्यंत धीमा




(2)

जीयूआई अनुप्रयोगों में एक ऐसी स्थिति में आता है जहां एक सारणी या सूची प्रारूप में बहुत सी मदों को प्रदर्शित करने की ज़रूरत होती है (उदाहरण के लिए तालिका में बड़ी संख्या में पंक्तियां प्रदर्शित करना)। जीयूआई जवाबदेही बढ़ाने का एक तरीका कुछ वस्तुओं को लोड करना है जब स्क्रीन प्रदर्शित होती है और यूज़र एक्शन के आधार पर बाकी मदों के लोडिंग को स्थगित करना है। क्यूटी माँग पर डेटा लोड करने की आवश्यकता को हल करने के लिए एक समाधान प्रदान करता है।

आप इस तकनीक के कार्यान्वयन को इस लिंक में पेजिंग कहते हैं

यह वह कूट है जिसे मैं क्यूटी डिज़ाइनर में तैयार की गई तालिका भरने के लिए उपयोग करता हूं। किसी भी तालिका के लिए सार्वभौमिक बनने के लिए डिज़ाइन किया गया, यह ठीक काम करता है, लेकिन ... जब मैं 18 स्तंभों और ~ 12000 पंक्तियों वाला एक डेटासेट प्रदर्शित करने का प्रयास करता हूं, तो यह केवल 30 सेकंड या अधिक के लिए फ्रीज़ करता है। तो, क्या मैं गलत कर रहा हूं और क्या किसी भी तालिका के लिए अभी भी उपयुक्त कोड रखने में तेजी लाने का कोई तरीका है?

यह मेरा कोड है:

...blablabla...

self.connect(self, SIGNAL("set"), self.real_set)

...blablabla...

def set_table(self, table, data):
    self.emit(SIGNAL('set'), table, data)

def real_set(self, table, data):
    """
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Assuming data is list of dict and table is a QTableWidget.

    Get first key and get len of contents
    """
    for key in data:
        rows = len(data[key])
        table.setRowCount(rows)
        break

    """
    Forbid resizing(speeds up)
    """
    table.horizontalHeader().setResizeMode(QHeaderView.Fixed)
    table.verticalHeader().setResizeMode(QHeaderView.Fixed)
    table.horizontalHeader().setStretchLastSection(False)
    table.verticalHeader().setStretchLastSection(False)

    """
    Set number of columns too
    """
    table.setColumnCount(len(data))
    table.setHorizontalHeaderLabels(sorted(data.keys()))

    """
    Now fill data
    """
    for n, key in enumerate(sorted(data.keys())):
        for m, item in enumerate(data[key]):
            newitem = QTableWidgetItem(item)
            table.setItem(m, n, newitem)

यहां एक टेस्ट स्क्रिप्ट है जो टेबल को पॉपुलिंग करने के कुछ तरीके की तुलना करती है।

कस्टम मॉडल बहुत तेज है, क्योंकि इसमें सभी वस्तुओं को सामने नहीं बनाया है - लेकिन ध्यान दें कि यह एक बहुत ही बुनियादी कार्यान्वयन है, इसलिए सॉर्टिंग, संपादन, आदि लागू नहीं होता है। (अधिक विवरण के लिए मॉडल / देखें प्रोग्रामिंग देखें) ।

from random import shuffle
from PyQt4 import QtCore, QtGui

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self, data, parent=None):
        super(TableModel, self).__init__(parent)
        self._data = data

    def rowCount(self, parent=None):
        return len(self._data)

    def columnCount(self, parent=None):
        return len(self._data[0]) if self.rowCount() else 0

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            row = index.row()
            if 0 <= row < self.rowCount():
                column = index.column()
                if 0 <= column < self.columnCount():
                    return self._data[row][column]

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.table = QtGui.QTableView(self)
        self.tablewidget = QtGui.QTableWidget(self)
        self.tablewidget.setSortingEnabled(True)
        self.button1 = QtGui.QPushButton('Custom Model', self)
        self.button1.clicked.connect(
            lambda: self.populateTable('custom'))
        self.button2 = QtGui.QPushButton('StandardItem Model', self)
        self.button2.clicked.connect(
            lambda: self.populateTable('standard'))
        self.button3 = QtGui.QPushButton('TableWidget', self)
        self.button3.clicked.connect(
            lambda: self.populateTable('widget'))
        self.spinbox = QtGui.QSpinBox(self)
        self.spinbox.setRange(15000, 1000000)
        self.spinbox.setSingleStep(10000)
        layout = QtGui.QGridLayout(self)
        layout.addWidget(self.table, 0, 0, 1, 4)
        layout.addWidget(self.tablewidget, 1, 0, 1, 4)
        layout.addWidget(self.button1, 2, 0)
        layout.addWidget(self.button2, 2, 1)
        layout.addWidget(self.button3, 2, 2)
        layout.addWidget(self.spinbox, 2, 3)
        self._data = []

    def populateTable(self, mode):
        if mode == 'widget':
            self.tablewidget.clear()
            self.tablewidget.setRowCount(self.spinbox.value())
            self.tablewidget.setColumnCount(20)
        else:
            model = self.table.model()
            if model is not None:
                self.table.setModel(None)
                model.deleteLater()
        if len(self._data) != self.spinbox.value():
            del self._data[:]
            rows = list(range(self.spinbox.value()))
            shuffle(rows)
            for row in rows:
                items = []
                for column in range(20):
                    items.append('(%d, %d)' % (row, column))
                self._data.append(items)
        timer = QtCore.QElapsedTimer()
        timer.start()
        if mode == 'widget':
            self.tablewidget.setSortingEnabled(False)
            for row, items in enumerate(self._data):
                for column, text in enumerate(items):
                    item = QtGui.QTableWidgetItem(text)
                    self.tablewidget.setItem(row, column, item)
            self.tablewidget.sortByColumn(0, QtCore.Qt.AscendingOrder)
        else:
            self.table.setSortingEnabled(False)
            if mode == 'custom':
                model = TableModel(self._data, self.table)
            elif mode == 'standard':
                model = QtGui.QStandardItemModel(self.table)
                for row in self._data:
                    items = []
                    for column in row:
                        items.append(QtGui.QStandardItem(column))
                    model.appendRow(items)
            self.table.setModel(model)
            self.table.setSortingEnabled(True)
            self.table.sortByColumn(0, QtCore.Qt.AscendingOrder)
        print('%s: %.3g seconds' % (mode, timer.elapsed() / 1000))

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 50, 1200, 800)
    window.show()
    sys.exit(app.exec_())




qtablewidget