QTableView 没有显示我的部分数据和 resetHeaderData 没有用 PyQt5 和 Python 触发
QTableView not showing part of my data and resetHeaderData not fired with PyQt5 and Python
这是一个简单的问题,但我无法解决!
- 数据源是pandas的DataFrame,布尔值,我的tableview的第二列值没有显示。为什么?
- 在主窗口 Class 中,我使用 [=24= 的 'setHeaderData' 函数将第二列的名称从 'T/F' 重置为 'True/False' (实际上只是为了测试) ] 继承自 'QAbstractTableModel'。但是第二列名称没有改变。为什么?非常感谢!
import sys
import typing
import pandas as pd
from PyQt5.QtWidgets import QApplication, QMainWindow, \
QWidget, QTableView, QHBoxLayout
from PyQt5.QtCore import QAbstractTableModel, Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
myTable = QTableView()
df_data = [['strong', True], ['Pretty', False]]
df_index = ['0', '1']
df_column = ['Type', 'T/F']
df = pd.DataFrame(data=df_data, index=df_index, columns=df_column)
model = MyTableModel(df)
model.setHeaderData(1, Qt.Horizontal, 'True/False', role=Qt.DisplayRole)
myTable.setModel(model)
hlayout = QHBoxLayout()
hlayout.addWidget(myTable)
dummy_widget = QWidget()
dummy_widget.setLayout(hlayout)
self.setCentralWidget(dummy_widget)
class MyTableModel(QAbstractTableModel):
def __init__(self, data: pd.DataFrame):
super().__init__()
self._data = data
self.header = self._data.columns.tolist()
def data(self, index, role):
if role == Qt.DisplayRole:
value = self._data.iloc[index.row()][index.column()]
return value
def rowCount(self, index) -> int:
return self._data.shape[0]
def columnCount(self, index) -> int:
return self._data.shape[1]
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self._data.columns[section]
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
您的代码中应更改的两件事:
- 在您的 MyTableModel.HeaderData 方法中,您使用 self._data 作为 header 值的来源,而不是 self.header。既然你已经有了 .header 列表,你应该使用它。
- 正如 @musicamante 所述,如果您在视图中使用抽象模型,则需要自己实现
setHeaderData
。
这是一段代码,您可以将其添加到您的模型中 class:
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header[section]
def setHeaderData(self, section: int, orientation: Qt.Orientation, value: typing.Any, role: int = ...) -> bool:
if role == Qt.DisplayRole:
self.header[section] = value
self.headerDataChanged.emit(orientation, section, section)
return True
else:
return False
如 documentation 中所述,对于 setHeaderData
您应该始终发出 headerDataChanged
信号。
编辑:
对于您的问题,为什么您的 bool 数据未显示。
您需要将其转换为字符串。
所以只需将 data
方法更改为:
def data(self, index, role):
if role == Qt.DisplayRole:
value = str(self._data.iloc[index.row()][index.column()])
return value
这是一个简单的问题,但我无法解决!
- 数据源是pandas的DataFrame,布尔值,我的tableview的第二列值没有显示。为什么?
- 在主窗口 Class 中,我使用 [=24= 的 'setHeaderData' 函数将第二列的名称从 'T/F' 重置为 'True/False' (实际上只是为了测试) ] 继承自 'QAbstractTableModel'。但是第二列名称没有改变。为什么?非常感谢!
import sys
import typing
import pandas as pd
from PyQt5.QtWidgets import QApplication, QMainWindow, \
QWidget, QTableView, QHBoxLayout
from PyQt5.QtCore import QAbstractTableModel, Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
myTable = QTableView()
df_data = [['strong', True], ['Pretty', False]]
df_index = ['0', '1']
df_column = ['Type', 'T/F']
df = pd.DataFrame(data=df_data, index=df_index, columns=df_column)
model = MyTableModel(df)
model.setHeaderData(1, Qt.Horizontal, 'True/False', role=Qt.DisplayRole)
myTable.setModel(model)
hlayout = QHBoxLayout()
hlayout.addWidget(myTable)
dummy_widget = QWidget()
dummy_widget.setLayout(hlayout)
self.setCentralWidget(dummy_widget)
class MyTableModel(QAbstractTableModel):
def __init__(self, data: pd.DataFrame):
super().__init__()
self._data = data
self.header = self._data.columns.tolist()
def data(self, index, role):
if role == Qt.DisplayRole:
value = self._data.iloc[index.row()][index.column()]
return value
def rowCount(self, index) -> int:
return self._data.shape[0]
def columnCount(self, index) -> int:
return self._data.shape[1]
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self._data.columns[section]
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
您的代码中应更改的两件事:
- 在您的 MyTableModel.HeaderData 方法中,您使用 self._data 作为 header 值的来源,而不是 self.header。既然你已经有了 .header 列表,你应该使用它。
- 正如 @musicamante 所述,如果您在视图中使用抽象模型,则需要自己实现
setHeaderData
。
这是一段代码,您可以将其添加到您的模型中 class:
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header[section]
def setHeaderData(self, section: int, orientation: Qt.Orientation, value: typing.Any, role: int = ...) -> bool:
if role == Qt.DisplayRole:
self.header[section] = value
self.headerDataChanged.emit(orientation, section, section)
return True
else:
return False
如 documentation 中所述,对于 setHeaderData
您应该始终发出 headerDataChanged
信号。
编辑:
对于您的问题,为什么您的 bool 数据未显示。
您需要将其转换为字符串。
所以只需将 data
方法更改为:
def data(self, index, role):
if role == Qt.DisplayRole:
value = str(self._data.iloc[index.row()][index.column()])
return value