PyQt6 TableView无法显示float32类型数据问题求助
问题描述
我用 pandas DataFrame 填充 PyQt6 的 TableView,这个 DataFrame 包含6列,其中5列为 String 类型,第6列为 float32 类型。当前遇到的问题是:TableView 无法显示第6列的 float32 数据,该列显示为空,但数据实际存在——调试时点击列头排序可以确认数据确实存在。我需要保留第6列的 float32 类型以实现数值排序(其余列需按字母顺序排序),同时让该列数据正常显示。
以下是相关代码:
main.py
from MainWindow import Ui_MainWindow class TableModel(QtCore.QAbstractTableModel): def __init__(self, data): super(TableModel, self).__init__() self._data = data def data(self, index, role): if role == Qt.ItemDataRole.DisplayRole: value = self._data.iloc[index.row(), index.column()] return value #here returning values as they are so 5 columns strings 6th one float def rowCount(self, index): return self._data.shape[0] def columnCount(self, index): return self._data.shape[1] def headerData(self, section, orientation, role): # section is the index of the column/row. if role == Qt.ItemDataRole.DisplayRole: if orientation == Qt.Orientation.Horizontal: return str(self._data.columns[section]) if orientation == Qt.Orientation.Vertical: return str(self._data.index[section]) app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) #setting up my model df is pandas DataFrame model = TableModel(df) #create sorter model sortermodel = QSortFilterProxyModel() sortermodel.setSourceModel(model) ui.tableView.setSortingEnabled(True) #passing model to tableview (will not work if I remove tableview element from UI designer) ui.tableView.setModel(sortermodel) MainWindow.show() app.exec()
MainWindow.py
from PyQt6 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) self.centralwidget = QtWidgets.QWidget(parent=MainWindow) self.centralwidget.setObjectName("centralwidget") self.tableView = QtWidgets.QTableView(parent=self.centralwidget) self.tableView.setGeometry(QtCore.QRect(-5, 1, 671, 511)) self.tableView.setObjectName("tableView") self.downloadTodaysData = QtWidgets.QPushButton(parent=self.centralwidget) self.downloadTodaysData.setGeometry(QtCore.QRect(670, 20, 75, 24)) self.downloadTodaysData.setObjectName("downloadTodaysData") self.LoadData = QtWidgets.QPushButton(parent=self.centralwidget) self.LoadData.setGeometry(QtCore.QRect(670, 50, 75, 24)) self.LoadData.setObjectName("LoadData") self.pushButton = QtWidgets.QPushButton(parent=self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(670, 80, 75, 24)) self.pushButton.setObjectName("pushButton") self.LastDataLabel = QtWidgets.QLabel(parent=self.centralwidget) self.LastDataLabel.setGeometry(QtCore.QRect(670, 0, 121, 20)) self.LastDataLabel.setObjectName("LastDataLabel") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(parent=MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(parent=MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.tableView.setToolTip(_translate("MainWindow", "<html><head/><body><p><br/></p></body></html>")) self.downloadTodaysData.setText(_translate("MainWindow", "Get Data")) self.LoadData.setText(_translate("MainWindow", "Load Data")) self.pushButton.setText(_translate("MainWindow", "ChartingDatatodo")) self.LastDataLabel.setText(_translate("MainWindow", "Last Data:"))
解决方案
问题根源在于data()方法直接返回了numpy的float32对象,PyQt的DisplayRole无法直接渲染该类型,导致列显示为空,但排序时模型能读取到数值所以排序有效。
解决思路是:在保证排序逻辑依赖原始数值类型的前提下,将float32转换为PyQt可识别的显示类型(比如Python原生float)。修改TableModel的data()方法即可:
修改后的TableModel代码
from MainWindow import Ui_MainWindow import numpy as np class TableModel(QtCore.QAbstractTableModel): def __init__(self, data): super(TableModel, self).__init__() self._data = data def data(self, index, role): if role == Qt.ItemDataRole.DisplayRole: value = self._data.iloc[index.row(), index.column()] # 针对numpy float32类型做转换,转为Python原生float if isinstance(value, np.float32): return float(value) return value # 可选:通过UserRole返回原始值,确保排序逻辑完全基于原始数据类型 elif role == Qt.ItemDataRole.UserRole: return self._data.iloc[index.row(), index.column()] def rowCount(self, index): return self._data.shape[0] def columnCount(self, index): return self._data.shape[1] def headerData(self, section, orientation, role): if role == Qt.ItemDataRole.DisplayRole: if orientation == Qt.Orientation.Horizontal: return str(self._data.columns[section]) if orientation == Qt.Orientation.Vertical: return str(self._data.index[section]) # 其余代码保持不变
说明
- 将numpy float32转为Python原生float后,TableView能正常显示该列数据;
- 原生float依然是数值类型,QSortFilterProxyModel会按数值大小排序,满足需求;
- 字符串列不受影响,依然按字母顺序排序;
- 可选的
UserRole返回原始值,进一步确保排序逻辑完全匹配原始数据类型,若原生float的排序效果已经符合预期,这部分可以省略。
内容的提问来源于stack exchange,提问作者Matthew Grossman
相关产品推荐
相关产品推荐

