gpt4 book ai didi

python - tableview 在对 tablemodel 排序后未更新

转载 作者:行者123 更新时间:2023-11-28 18:22:22 25 4
gpt4 key购买 nike

想法是通过 PyQt5 MV 编程习惯用法显示数据帧,并对显示的数据帧执行一些基本的排序和过滤操作。

显示部分一切正常,但现在我卡在了工具的排序部分。打印语句向我展示了它自己排序的数据框,它是未更新的 View 。所以现在到代码:

import sys
import operator
tmp = [('23-02-1978', '19:03:13', 'eh', None, 'even more some data'),
('23-02-1978', '19:01:45', 'ss', 'some data ', 'even more some data'),
('23-02-1978', '19:02:55', 'he', 'some data ', 'even more some data')]


tmp1 = [('23-02-1978', '19:02:33', 'eh', 'some data ', '666', 'even more some data'),
('23-02-1978', '19:03:22', 'ss', 'some data ', '777', 'even more some data'),
('23-02-1978', '19:01:45', 'he', 'some data ', '888', 'even more some data')]


from PyQt5.QtWidgets import (QMainWindow, QApplication, QWidget, QAction,
QGroupBox, QCheckBox, QTableView, QTableWidgetItem,
QTabWidget, QGridLayout,QLineEdit, QFormLayout,
QVBoxLayout, QHBoxLayout, QLabel, QDialog, QHeaderView)

from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal, QAbstractTableModel, QVariant, QModelIndex, QSortFilterProxyModel


from pandas import DataFrame


class DataFrameModel(QAbstractTableModel):
def __init__(self):
""" datain: a list of lists
headerdata: a list of strings
"""
super(DataFrameModel, self).__init__()
self._df = DataFrame()

def setDataFrame(self, df):
self._df = df;

def signalUpdate(self):
''' tell viewers to update their data (this is full update, not
efficient)'''
self.layoutChanged.emit()


#------------- table display functions -----------------
def headerData(self, section, orientation, role=Qt.DisplayRole):
if role != Qt.DisplayRole:
return QVariant()

if orientation == Qt.Horizontal:
try:
return self._df.columns.tolist()[section]
except (IndexError, ):
return QVariant()
elif orientation == Qt.Vertical:
try:
# return self.df.index.tolist()
return self._df.index.tolist()[section]
except (IndexError, ):
return QVariant()

def data(self, index, role=Qt.DisplayRole):
if role != Qt.DisplayRole:
return QVariant()

if not index.isValid():
return QVariant()

return QVariant(str(self._df.ix[index.row(), index.column()]))

def flags(self, index):
flags = super(DataFrameModel, self).flags(index)
return flags

def setData(self, index, value, role):
row = self._df.index[index.row()]
col = self._df.columns[index.column()]
if hasattr(value, 'toPyObject'):
# PyQt4 gets a QVariant
value = value.toPyObject()
else:
# PySide gets an unicode
dtype = self._df[col].dtype
if dtype != object:
value = None if value == '' else dtype.type(value)
self._df.set_value(row, col, value)
return True

def rowCount(self, parent=QModelIndex()):
return len(self._df.index)

def columnCount(self, parent=QModelIndex()):
return len(self._df.columns)

def sort(self, column, order=Qt.AscendingOrder):
"""Sort table by given column number.
"""
print('sort clicked col {} order {}'.format(column, order))
self.layoutAboutToBeChanged.emit()
print(self._df.columns[column])
self._df.sort_values('time', ascending=order == Qt.AscendingOrder, inplace=True)
print(self._df)
self.layoutChanged.emit()


class DataFrameWidget(QWidget):
''' a simple widget for using DataFrames in a gui '''
def __init__(self, dataFrame, parent=None):
super(DataFrameWidget, self).__init__(parent)

self.dataModel = DataFrameModel()
# Set DataFrame
self.dataTable = QTableView()
# self.proxy = QSortFilterProxyModel()
# self.proxy.setSourceModel(self.dataModel)
self.dataTable.setModel(self.dataModel)

self.dataTable.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)

self.setDataFrame(dataFrame)
self.dataTable.setSortingEnabled(True)
self.dataTable.sortByColumn(0,0)


layout = QVBoxLayout()
layout.addWidget(self.dataTable)
self.setLayout(layout)

def setDataFrame(self, dataFrame):
self.dataModel.setDataFrame(dataFrame)
self.dataModel.signalUpdate()


def testDf():
''' creates test dataframe '''
# data = {'int': [1, 2, 3], 'float': [1.5, 2.5, 3.5],
# 'string': ['a', 'b', 'c'], 'nan': [np.nan, np.nan, np.nan]}

# data = [(1, 1.5, 'a', np.nan),
# (2, 2.5, 'b', np.nan),
# (3, 3.5, 'c', np.nan)]



return DataFrame(tmp, columns=['date', 'time', 'string', 'nan', 'bla'])

class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)

df = testDf() # make up some data
widget = DataFrameWidget(df)

layout = QVBoxLayout()
layout.addWidget(widget)
self.setLayout(layout)

if __name__ == '__main__':

app = QApplication(sys.argv)
form = Form()
form.show()
exit(app.exec_())

使用 SortFilterProxy 适用于此示例,但在较大的数据帧上速度非常慢。

上面的代码示例对于非数据帧数据确实有效,读取已排序。仅使用元组列表创建模型/ View 效果很好。

我找到的建议主要有两个方向:记得给 View 发信号或使用 sortfilterproxy。我记得并尝试过但到目前为止没有成功。似乎与数据框的使用有关。欢迎所有建议。提前致谢。

最佳答案

在下一部分中,我将展示您的印象结果,其中我们看到它被重新排序,而且索引也被重新排序,这导致在未更新时发生变化。

sort clicked col 0 order 1
date
date time string nan bla
0 23-02-1978 19:03:13 eh None even more some data
2 23-02-1978 19:02:55 he some data even more some data
1 23-02-1978 19:01:45 ss some data even more some data
sort clicked col 0 order 0
date
date time string nan bla
1 23-02-1978 19:01:45 ss some data even more some data
2 23-02-1978 19:02:55 he some data even more some data
0 23-02-1978 19:03:13 eh None even more some data

要更新数据,您必须使用 reset_index() 重置索引。

def sort(self, column, order):
"""Sort table by given column number.
"""
print('sort clicked col {} order {}'.format(column, order))
self.layoutAboutToBeChanged.emit()
print(self._df.columns[column])
self._df.sort_values('time', ascending=order == Qt.AscendingOrder, inplace=True)
self._df.reset_index(inplace=True, drop=True) # <-- this is the change
print(self._df)
self.layoutChanged.emit()

关于python - tableview 在对 tablemodel 排序后未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44145170/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com