PYQT5 setCellWidget () на QTableWidget замедляет интерфейс - PullRequest
0 голосов
/ 25 февраля 2020

При использовании setCellWidget() в PyQT5 на QTableWidget() у меня возникают проблемы с производительностью. Как только моя for -l oop содержит около 100 записей, поступающих из базы данных SQL, задержка становится заметной. Около 500 записей задержка занимает до 3 секунд.

Я отключил часть setCellWidget() и протестировал 20 000 записей, и задержка едва ли была. Таким образом, выполнение и получение запроса не задерживает код.

self.queueTable - это QTableWidget () из 8 столбцов и столько же строк, сколько возвращено запросом, хранящимся в переменной tasks

Вот код, который я использовал:

    def buildQueueInUI(self):
        global userAccount
        .....
        tasks = Query(SQLconn, 'SQLITE', False).readParameterized(QueryStrings.myQueuedJobsList, [userAccount])
        for row in tasks:
            rowPosition = self.queueTable.rowCount()
            self.queueTable.insertRow(rowPosition)
            btt=QPushButton('DELETE')
            btt.clicked.connect(cancelTask)
            self.queueTable.setCellWidget(rowPosition, 0, btt)  ##turning this into a comment fixes the slowdown issue
            self.queueTable.setItem(rowPosition, 1, Tables.noEditTableWidget(self, str(row[0])))
            self.queueTable.setItem(rowPosition, 2, Tables.noEditTableWidget(self, str(row[2])))


         ....

Я читал, что QPushButton «дорогой» ( Зачем получать Python с PyQt5 медленным при создании большого количества QPushButtons? ), но проблема остается при использовании другие виджеты, такие как комбинированный список (пример непрактичного кода с комбинированным списком :)

    def buildQueueInUI(self):
        global userAccount
        .....
        tasks = Query(SQLconn, 'SQLITE', False).readParameterized(QueryStrings.myQueuedJobsList, [userAccount])
        for row in tasks:
            rowPosition = self.queueTable.rowCount()
            self.queueTable.insertRow(rowPosition)
            combo = QComboBox()
            combo.addItem("keep")
            combo.addItem("remove")
            self.queueTable.setCellWidget(rowPosition, 0, combo)  ##turning this into a comment fixes the slowdown issue
            self.queueTable.setItem(rowPosition, 1, Tables.noEditTableWidget(self, str(row[0])))
            self.queueTable.setItem(rowPosition, 2, Tables.noEditTableWidget(self, str(row[2])))

         ....

Только без выполнения вызова setCellWidget() на QTableWidget с QPushButton() или QComboBox() I может сделать таблицу без задержек.

В типичном сценарии использования было бы около 500 - 750 задач в очереди. Как я могу получить QPushButton() без задержек, вызванных setCellWidget()? У меня уже есть слушатель cellDoubleClicked.connect и настраиваемое контекстное меню на table`, так что это не вариант.

Моя система:

  • Python 3.7
  • PYQT5 5.14.1
  • Windows 10 64 бит

1 Ответ

1 голос
/ 26 февраля 2020

Вы можете попробовать установить количество строк до -100 * вместо добавления одной строки за раз. Рассмотрим, например, следующий пример

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QTableWidgetItem
from time import time

class CreateTable(QtWidgets.QWidget):

    def __init__(self, parent = None):
        super().__init__(parent)
        fill_button_1 = QtWidgets.QPushButton('fill table - set row count')
        fill_button_1.clicked.connect(self.buildQueueInUI_1)

        fill_button_2 = QtWidgets.QPushButton('fill table - insert rows')
        fill_button_2.clicked.connect(self.buildQueueInUI_2)

        hlayout = QtWidgets.QHBoxLayout()
        hlayout.addWidget(fill_button_1)
        hlayout.addWidget(fill_button_2)

        self.table = QtWidgets.QTableWidget(self)
        self.table.setColumnCount(2)

        layout = QtWidgets.QVBoxLayout(self)
        layout.addLayout(hlayout)
        layout.addWidget(self.table)

    def buildQueueInUI_1(self):
        nrows = 500
        self.table.setRowCount(0)
        t0 = time()
        last_row = self.table.rowCount()
        self.table.setRowCount(nrows+self.table.rowCount())
        for i in range(500):
            row = last_row+i
            button = QtWidgets.QPushButton('Click', self)
            button.clicked.connect(lambda _, x=row+1: print('button', x))
            self.table.setCellWidget(row, 0, button)
            self.table.setItem(row, 1, QTableWidgetItem(f'item {row}'))
        print(f'set row count: {time()-t0:.4f} seconds')

    def buildQueueInUI_2(self):
        nrows = 500
        self.table.setRowCount(0)
        t0 = time()
        for i in range(nrows):
            row = self.table.rowCount()
            self.table.insertRow(row)
            button = QtWidgets.QPushButton('Click', self)
            button.clicked.connect(lambda _, x=row+1: print('button', x))
            self.table.setCellWidget(row, 0, button)
            self.table.setItem(row, 1, QTableWidgetItem(f'item {row}'))
        print(f'insert rows: {time() - t0:.4f} seconds')

if __name__ == "__main__":
    app = QApplication([])
    win = CreateTable()
    win.show()
    app.exec_()

Выход

set row count: 0.0359 seconds
insert rows: 1.0572 seconds
...