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



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

问题

我想按照对数组而不是行、列值的操作,以"矢量化"的方式填充或读取QTableWidget。我在这篇文章中看到了其他使用QTableView的例子。我如何从QTableWidget到Dataframe检索数据?但这仍然对单个值而不是数组或列表进行操作。这可能吗?

通常情况下,当我对行、列值进行操作时,我会这样做:

# 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等其他选项持开放态度。我感谢你的帮助,马塞洛。

使用TableView并重新实现QAbstractTableModel可以做到这一点。您将调用TableWidget.model().setColumn(col, array_items)而不是TableWidget.setColumn(col, array_items)。原则上,为了让它与TableWidget一起工作,您必须重新实现QTableWidget类,但我发现这是不必要的。

在我的示例中,我使用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()

最新更新