QStandardItemModel 和 QAbstractTableModel 之间的速度差异?

Speed differences between QStandardItemModel and QAbstractTableModel?

任何人都可以解释以下内容: 我有 2 个脚本用于在具有过滤字段的表视图中加载 pandas 数据框。具有标准模型的模型在“init”部分加载数据。有了这个,一切都非常快,过滤也是如此。 第二个脚本的运行速度要慢得多,但是有了这个我可以设置我需要的单元格的背景颜色。 这些是脚本:

import timeit

import pandas as pd
from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtCore import QAbstractTableModel
from PyQt5.QtCore import Qt, QSortFilterProxyModel
from PyQt5.QtGui import *
from PyQt5.uic import loadUi


class PandasTableModel(QtGui.QStandardItemModel):

    def __init__(self, data, parent=None):

        QtGui.QStandardItemModel.__init__(self, parent)
        self._data = data

        for col in data.columns:
            data_col = [QtGui.QStandardItem("{}".format(x)) for x in data[col].values]
            self.appendColumn(data_col)
        return

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

    def columnCount(self, parent=None):
        return self._data.columns.size

    def headerData(self, x, orientation, role):

        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[x]
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return self._data.index[x]

    def flags(self, index):
        if not index.isValid():
            return Qt.ItemIsEnabled

        return super().flags(index) | Qt.ItemIsEditable  # add editable flag.

    def setData(self, index, value, role):

        if role == Qt.EditRole:
            # Set the value into the frame.
            self._data.iloc[index.row(), index.column()] = value
            return True

        return False

class TableViewer(QtWidgets.QMainWindow):

    def __init__(self):
        super(TableViewer, self).__init__()

        self.ui = loadUi("QTableViewForm.ui", self)
        self.ui.cmdRun1.clicked.connect(self.RunFunction1)
        self.ui.cmdRun2.clicked.connect(self.RunFunction2)
        self.ui.inputFilter.textChanged.connect(self.SetFilteredView)

        self.showdata()

    def showdata(self):
        start = timeit.default_timer()
        print("Start LoadData")

        data = pd.read_pickle("productdata.pkl")

        self.model = PandasTableModel(data)
        self.ui.tableData.setModel(self.model)
        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setFilterKeyColumn(-1)  # Search all columns.
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.sort(0, Qt.AscendingOrder)
        self.proxy_model.setFilterCaseSensitivity(False)
        self.ui.tableData.setModel(self.proxy_model)

        print("Stop LoadData")
        end = timeit.default_timer()
        print("Process Time: ", (end - start))

    def set_cell_color(self, row, column):
        self.model.change_color(row, column, QBrush(Qt.red))

    def RunFunction1(self):
        start = timeit.default_timer()
        print("Start RunFunction1")
        #Gans de rij in 't rood
        colums = self.proxy_model.columnCount()

        for c in range(colums):

            self.set_cell_color(3, c)

        print("Stop RunFunction1")
        end = timeit.default_timer()
        print("Process Time: ", (end - start))

    def RunFunction2(self):
        start = timeit.default_timer()
        print("Start RunFunction1")
        #Gans de rij in 't rood
        colums = self.proxy_model.columnCount()

        for c in range(colums):

            self.set_cell_color(3, c)

        print("Stop RunFunction1")
        end = timeit.default_timer()
        print("Process Time: ", (end - start))

    def SetFilteredView(self):

        # print("Start set_filter")
        filter_text = self.ui.inputFilter.text()
        self.proxy_model.setFilterFixedString(filter_text)
        filter_result = self.proxy_model.rowCount()
        self.ui.lblResult.setText("(" + str(filter_result) + " records)")


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    win = TableViewer()
    win.show()
    sys.exit(app.exec_())enter code here

慢的:

import timeit

import pandas as pd
from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtCore import QAbstractTableModel
from PyQt5.QtCore import Qt, QSortFilterProxyModel
from PyQt5.QtGui import *
from PyQt5.uic import loadUi


class PandasTableModel(QAbstractTableModel):
    def __init__(self, data, parent=None):
        QAbstractItemModel.__init__(self, parent)
        self._data = data
        self.colors = dict()

    def rowCount(self, parent=None):
        return self._data.index.size
    def columnCount(self, parent=None):
        return self._data.columns.size

    def setData(self, index, value, role):

        if role == Qt.EditRole:
            # Set the value into the frame.
            self._data.iloc[index.row(), index.column()] = value
            return True

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
            if role == Qt.EditRole:
                return str(self._data.iloc[index.row(), index.column()])
            if role == Qt.BackgroundRole:
                color = self.colors.get((index.row(), index.column()))
                if color is not None:
                    return color
        return None

    def headerData(self, rowcol, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[rowcol]
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return self._data.index[rowcol]
        return None

    def change_color(self, row, column, color):
        ix = self.index(row, column)
        self.colors[(row, column)] = color
        self.dataChanged.emit(ix, ix, (Qt.BackgroundRole,))


class TableViewer(QtWidgets.QMainWindow):

    def __init__(self):
        super(TableViewer, self).__init__()

        self.ui = loadUi("QTableViewForm.ui", self)
        self.ui.cmdRun1.clicked.connect(self.RunFunction1)
        self.ui.cmdRun2.clicked.connect(self.RunFunction2)
        self.ui.inputFilter.textChanged.connect(self.SetFilteredView)

        self.showdata()

    def showdata(self):
        start = timeit.default_timer()
        print("Start LoadData")

        data = pd.read_pickle("productdata.pkl")

        self.model = PandasTableModel(data)
        self.ui.tableData.setModel(self.model)
        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setFilterKeyColumn(-1)  # Search all columns.
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.sort(0, Qt.AscendingOrder)
        self.proxy_model.setFilterCaseSensitivity(False)
        self.ui.tableData.setModel(self.proxy_model)

        print("Stop LoadData")
        end = timeit.default_timer()
        print("Process Time: ", (end - start))

    def set_cell_color(self, row, column):
        self.model.change_color(row, column, QBrush(Qt.red))

    def RunFunction1(self):
        start = timeit.default_timer()
        print("Start RunFunction1")
        #Gans de rij in 't rood
        colums = self.proxy_model.columnCount()

        for c in range(colums):

            self.set_cell_color(3, c)

        print("Stop RunFunction1")
        end = timeit.default_timer()
        print("Process Time: ", (end - start))

    def RunFunction2(self):
        start = timeit.default_timer()
        print("Start RunFunction1")
        #Gans de rij in 't rood
        colums = self.proxy_model.columnCount()

        for c in range(colums):

            self.set_cell_color(3, c)

        print("Stop RunFunction1")
        end = timeit.default_timer()
        print("Process Time: ", (end - start))

    def SetFilteredView(self):

        # print("Start set_filter")
        filter_text = self.ui.inputFilter.text()
        self.proxy_model.setFilterFixedString(filter_text)
        filter_result = self.proxy_model.rowCount()
        self.ui.lblResult.setText("(" + str(filter_result) + " records)")


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    win = TableViewer()
    win.show()
    sys.exit(app.exec_())

(我正在加载 2000 行和 35 列)

能给我一个快的有背景色功能的吗?

干杯,约翰逊

而不是

def set_cell_color(self, row, column):
        self.model.change_color(row, column, QBrush(Qt.red))

使用这个

def set_cell_color(self, row, column):
        self.model.item(row, column).setBackground(QBrush(Qt.red))

根据您的要求,您可能需要将 model 替换为 proxy_model,但这取决于行和列是否应引用过滤后模型或基础模型的坐标。所以这取决于你。