当数据源与 QSortFilterProxyModel 之间发生变化时,动态更新 QTableView
Updating QTableView on the fly when data source changes with a QSortFilterProxyModel in between
我正在尝试在数据源 (Pandas Dataframe) 更改时更新 QTableView。
我使用 QAbstractTableModel 作为“基础”table 模型和 QSortFilterProxyModel 进行一些过滤。
有时在运行时数据源会发生变化。据此,我的目标是重置“基础”table 模型 -> 通知代理模型 -> 更新 QTableView。
我尝试了以下代码,但这并没有在主窗口 class.
中调用 on_event() 后更改 TableView
下面是执行table代码...
import sys
import pandas as pd
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt
class DataStore(object):
def __init__(self):
data = {'Name': ['name1', 'name2',"name3"],
'Value': ['value1', 'value2',"value3"],
'Setting': ["TRUE", "TRUE","FALSE"]
}
df = pd.DataFrame (data, columns = ['Name','Value','Setting'])
self.df = df
self.model = TableModel(self.df)
self.proxy_model = ProxyModel(self.model)
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setDynamicSortFilter(True)
class ProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent):
QtCore.QSortFilterProxyModel.__init__(self, parent)
# Random filtering
def filterAcceptsRow(self, sourceRow, sourceParent):
print("Entered filterAcceptsRow function with source row: {}".format(sourceRow))
idx = self.sourceModel().index(sourceRow, 2, sourceParent)
value = idx.data()
if value == "TRUE":
return True
if value == "FALSE":
return False
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self.__data = data
def data(self, index, role):
if role == Qt.DisplayRole:
value = self.__data.iloc[index.row(), index.column()]
return str(value)
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.DisplayRole:
if orientation == Qt.Horizontal:
return str(self.__data.columns[section])
if orientation == Qt.Vertical:
return str(self.__data.index[section])
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ds = DataStore()
self.table = QtWidgets.QTableView()
self.table.setModel(self.ds.proxy_model)
self.on_event()
self.setCentralWidget(self.table)
self.setGeometry(600, 100, 400, 200)
def on_event(self):
data = {'Name': ['new_name1', 'new_name2',"new_name3"],
'Value': ['new_value1', 'new_value2',"new_value3"],
'Description': ['new_descr1', 'new_descr2',"new_descr3"],
'Setting': ["TRUE", "FALSE","TRUE"]
}
new_df = pd.DataFrame (data, columns = ['Name','Value','Setting'])
self.ds.model.beginResetModel()
self.ds.df = new_df
self.ds.model.endResetModel()
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
问题不在于 QSortFilterProxyModel,而是 sourceModel 中的信息未更新,您正在将 df 复制到 DataStore 但更新 TableModel 信息导致该错误。
import sys
import pandas as pd
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt
class DataStore(object):
def __init__(self):
data = {
"Name": ["name1", "name2", "name3"],
"Value": ["value1", "value2", "value3"],
"Setting": ["TRUE", "TRUE", "FALSE"],
}
df = pd.DataFrame(data, columns=["Name", "Value", "Setting"])
self.model = TableModel(df)
self.proxy_model = ProxyModel()
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setDynamicSortFilter(True)
@property
def df(self):
return self.model.df
@df.setter
def df(self, df):
self.model.df = df
class ProxyModel(QtCore.QSortFilterProxyModel):
def filterAcceptsRow(self, sourceRow, sourceParent):
print("Entered filterAcceptsRow function with source row: {}".format(sourceRow))
idx = self.sourceModel().index(sourceRow, 2, sourceParent)
value = idx.data()
if value == "TRUE":
return True
if value == "FALSE":
return False
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self.__data = data
@property
def df(self):
return self.__data
@df.setter
def df(self, df):
self.beginResetModel()
self.__data = df.copy()
self.endResetModel()
def data(self, index, role):
if role == Qt.DisplayRole:
value = self.__data.iloc[index.row(), index.column()]
return str(value)
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.DisplayRole:
if orientation == Qt.Horizontal:
return str(self.__data.columns[section])
if orientation == Qt.Vertical:
return str(self.__data.index[section])
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ds = DataStore()
self.table = QtWidgets.QTableView()
self.table.setModel(self.ds.proxy_model)
self.on_event()
self.setCentralWidget(self.table)
self.setGeometry(600, 100, 400, 200)
def on_event(self):
data = {
"Name": ["new_name1", "new_name2", "new_name3"],
"Value": ["new_value1", "new_value2", "new_value3"],
"Description": ["new_descr1", "new_descr2", "new_descr3"],
"Setting": ["TRUE", "FALSE", "TRUE"],
}
new_df = pd.DataFrame(data, columns=["Name", "Value", "Setting"])
self.ds.df = new_df
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
我正在尝试在数据源 (Pandas Dataframe) 更改时更新 QTableView。 我使用 QAbstractTableModel 作为“基础”table 模型和 QSortFilterProxyModel 进行一些过滤。
有时在运行时数据源会发生变化。据此,我的目标是重置“基础”table 模型 -> 通知代理模型 -> 更新 QTableView。
我尝试了以下代码,但这并没有在主窗口 class.
中调用 on_event() 后更改 TableView下面是执行table代码...
import sys
import pandas as pd
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt
class DataStore(object):
def __init__(self):
data = {'Name': ['name1', 'name2',"name3"],
'Value': ['value1', 'value2',"value3"],
'Setting': ["TRUE", "TRUE","FALSE"]
}
df = pd.DataFrame (data, columns = ['Name','Value','Setting'])
self.df = df
self.model = TableModel(self.df)
self.proxy_model = ProxyModel(self.model)
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setDynamicSortFilter(True)
class ProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent):
QtCore.QSortFilterProxyModel.__init__(self, parent)
# Random filtering
def filterAcceptsRow(self, sourceRow, sourceParent):
print("Entered filterAcceptsRow function with source row: {}".format(sourceRow))
idx = self.sourceModel().index(sourceRow, 2, sourceParent)
value = idx.data()
if value == "TRUE":
return True
if value == "FALSE":
return False
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self.__data = data
def data(self, index, role):
if role == Qt.DisplayRole:
value = self.__data.iloc[index.row(), index.column()]
return str(value)
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.DisplayRole:
if orientation == Qt.Horizontal:
return str(self.__data.columns[section])
if orientation == Qt.Vertical:
return str(self.__data.index[section])
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ds = DataStore()
self.table = QtWidgets.QTableView()
self.table.setModel(self.ds.proxy_model)
self.on_event()
self.setCentralWidget(self.table)
self.setGeometry(600, 100, 400, 200)
def on_event(self):
data = {'Name': ['new_name1', 'new_name2',"new_name3"],
'Value': ['new_value1', 'new_value2',"new_value3"],
'Description': ['new_descr1', 'new_descr2',"new_descr3"],
'Setting': ["TRUE", "FALSE","TRUE"]
}
new_df = pd.DataFrame (data, columns = ['Name','Value','Setting'])
self.ds.model.beginResetModel()
self.ds.df = new_df
self.ds.model.endResetModel()
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
问题不在于 QSortFilterProxyModel,而是 sourceModel 中的信息未更新,您正在将 df 复制到 DataStore 但更新 TableModel 信息导致该错误。
import sys
import pandas as pd
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt
class DataStore(object):
def __init__(self):
data = {
"Name": ["name1", "name2", "name3"],
"Value": ["value1", "value2", "value3"],
"Setting": ["TRUE", "TRUE", "FALSE"],
}
df = pd.DataFrame(data, columns=["Name", "Value", "Setting"])
self.model = TableModel(df)
self.proxy_model = ProxyModel()
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setDynamicSortFilter(True)
@property
def df(self):
return self.model.df
@df.setter
def df(self, df):
self.model.df = df
class ProxyModel(QtCore.QSortFilterProxyModel):
def filterAcceptsRow(self, sourceRow, sourceParent):
print("Entered filterAcceptsRow function with source row: {}".format(sourceRow))
idx = self.sourceModel().index(sourceRow, 2, sourceParent)
value = idx.data()
if value == "TRUE":
return True
if value == "FALSE":
return False
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self.__data = data
@property
def df(self):
return self.__data
@df.setter
def df(self, df):
self.beginResetModel()
self.__data = df.copy()
self.endResetModel()
def data(self, index, role):
if role == Qt.DisplayRole:
value = self.__data.iloc[index.row(), index.column()]
return str(value)
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.DisplayRole:
if orientation == Qt.Horizontal:
return str(self.__data.columns[section])
if orientation == Qt.Vertical:
return str(self.__data.index[section])
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ds = DataStore()
self.table = QtWidgets.QTableView()
self.table.setModel(self.ds.proxy_model)
self.on_event()
self.setCentralWidget(self.table)
self.setGeometry(600, 100, 400, 200)
def on_event(self):
data = {
"Name": ["new_name1", "new_name2", "new_name3"],
"Value": ["new_value1", "new_value2", "new_value3"],
"Description": ["new_descr1", "new_descr2", "new_descr3"],
"Setting": ["TRUE", "FALSE", "TRUE"],
}
new_df = pd.DataFrame(data, columns=["Name", "Value", "Setting"])
self.ds.df = new_df
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()