在 PyQt5 中填充或读取 QTableWidget 的最快方法

Fastest way to fill or read from a QTableWidget in PyQt5

我在 PyQt5 中有一个 QTableWidget,我从一个 python numpy 数组字典或一个 pandas DataFrame 中填充它。

问题

我想按照对数组而不是行、列值的操作,以 'vectorized' 的方式填充或读取 QTableWidget。我在这个 post How can I retrieve data from a QTableWidget to Dataframe? 中看到了其他使用 QTableView 的示例,但这仍然对个人值而不是数组或列表进行操作。这可能吗?

通常我在对行、列值进行操作时这样做:

# To Writte
TableWidget.setItem(row, col, tableItem)

# To Read
TableWidget.item(i, j).data()

我想做这样的事情:

# To Writte
TableWidget.setColumn(col, array_items)

# To Read
TableWidget.getColumn(col).data()

我更愿意继续使用 QTableWidget,但我对 QTableView 等其他选项持开放态度。 感谢您的帮助,Marcelo。

可以使用 TableView 和 re-implemented QAbstractTableModel 来做到这一点。您将调用 TableWidget.model().setColumn(col, array_items) 而不是 TableWidget.setColumn(col, array_items)。原则上让它与 TableWidget 一起工作,你必须 re-implement QTableWidget class,但我发现没有必要。

在我的示例中,我使用 pandas DataFrame 作为数据容器。您可以使用列名设置和获取数据。

这是完整的示例:

import sys
import typing

import pandas as pd
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableView, QWidget, QGridLayout, QPushButton


class TableModel(QAbstractTableModel):

    def __init__(self, table_data, parent=None):
        super().__init__(parent)
        self.table_data = table_data

    def rowCount(self, parent: QModelIndex = ...) -> int:
        return self.table_data.shape[0]

    def columnCount(self, parent: QModelIndex = ...) -> int:
        return self.table_data.shape[1]

    def data(self, index: QModelIndex, role: int = ...) -> typing.Any:
        if role == Qt.DisplayRole:
            return str(self.table_data.loc[index.row()][index.column()])

    def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return str(self.table_data.columns[section])

    def setColumn(self, col, array_items):
        """Set column data"""
        self.table_data[col] = array_items
        # Notify table, that data has been changed
        self.dataChanged.emit(QModelIndex(), QModelIndex())

    def getColumn(self, col):
        """Get column data"""
        return self.table_data[col]


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = QMainWindow()

    widget = QWidget()

    layout = QGridLayout()
    widget.setLayout(layout)
    table_data = pd.DataFrame(data={'col1': [1, 2, 3, 4, 5, 6, 7, 8], 'col2': [1, 2, 3, 4, 5, 6, 7, 8]})
    table = QTableView()
    table.setModel(TableModel(table_data=table_data))
    layout.addWidget(table)

    button = QPushButton("Set col1")
    button.clicked.connect(lambda: table.model().setColumn("col1", [8, 7, 6, 5, 4, 3, 2, 1]))

    button_2 = QPushButton("Read col1")
    button_2.clicked.connect(lambda: print(table.model().getColumn("col1")))

    layout.addWidget(button)
    layout.addWidget(button_2)
    win.setCentralWidget(widget)

    win.show()
    app.exec()