基于单个数据源更新多个 Qt 模型

Posted

技术标签:

【中文标题】基于单个数据源更新多个 Qt 模型【英文标题】:Update multiple Qt models based on a single data source 【发布时间】:2020-07-23 07:37:18 【问题描述】:

我想触发多个模型更新,从而根据原始数据源更新(如对象列表)触发多个视图更新。数据和多个模型之间的映射如何工作?

例如:

我有多个Measurements 的列表,其中包含sizecolorweight 等属性

一个模型用作带有QListView 的接口,它仅显示所有Measurements 中的size 一个模型用作与QTableView 的接口,显示所有测量的sizecolor

然后我触发对原始数据的更新。它可以来自上面提到的连接模型之一或来自外部更新。如何将此更改添加到我的所有关联模型?

我在 Pyside2 中使用 python,但答案可以是 C++

【问题讨论】:

我会考虑实现一个 QAbstractListModel 来提供所有数据(通过角色),然后使用简单的代理模型(QIdentityProxyModel 子类)将该数据映射到列/角色(主要是 Qt: :DisplayRole) 根据各个视图的需要。 听起来不错,我会研究这个方向,谢谢。您可以发表您的评论作为答案,如果它碰巧解决了这个问题,我会投赞成票并接受。 @Frank Osterfeld 我想我应该实现一个 QAbstractTableModel 来将不同的属性存储在不同的列中?或者 QAbstractListModel 是否能够使用角色来做到这一点? 这取决于用例。对于大多数 QML 应用程序,您将使用 QAbstractListModel 派生模型,但对于基于小部件的应用程序,使用多列更为常见。看到问题提到了 QTableView,我想说使用 QAbstractTableModel 作为基础是有意义的。然后,代理可以只是一个过滤掉一些列的 QSortFilterProxyModel。 QStandardItemModel 通常是首选模型。然后在视图中决定应该显示哪些列。无需为抽象模型而烦恼。 【参考方案1】:

正如@Frank Osterfeld 在他的评论中所说,可以将您的所有数据存储在模型中(在我的情况下为QAbstractTableModel),然后过滤掉您在各自视图中不需要的列。

为此,我使用了QSortFilterProxyModel 并覆盖了filterAcceptsColumn() 方法。

这是一个例子:

class MyModel(QAbstractTableModel):
    def __init__(self):
        super().__init__()
        self.data = []
    ... # here are all the things you usually define in an abstract model

class MyProxyModelA(QSortFilterProxyModel):
    def filterAcceptsColumn(self, source_column: int, source_parent: QModelIndex) -> bool:
        """ This filters any column that returns true """
        return source_column != 2

class MyProxyModelB(QSortFilterProxyModel):
    def filterAcceptsColumn(self, source_column: int, source_parent: QModelIndex) -> bool:
        """ This filters any column that returns true """
        return source_column == 2

在我看来:

model = MyModel()  # I put this here for the sake of this example

class MyWidgetA(QWidget):
    def __init__(self):
        super().__init__()

        self.ui = Ui_Form()
        self.ui.setupUi(self)

        self.table = QTableView()

        self.proxy = MyProxyModelA()
        self.proxy.setSourceModel(model)

        self.table.setModel(self.proxy)

        self.ui.layout.addWidget(self.table)


class MyWidgetB(QWidget):
    def __init__(self):
        super().__init__()

        self.ui = Ui_Form()
        self.ui.setupUi(self)

        self.table = QTableView()

        self.proxy = MyProxyModelB()
        self.proxy.setSourceModel(model)

        self.table.setModel(self.proxy)

        self.ui.layout.addWidget(self.table)

现在,您可以在通过MyWidgetAMyWidgetB 修改模型和视图时自动同步您的模型和视图

【讨论】:

以上是关于基于单个数据源更新多个 Qt 模型的主要内容,如果未能解决你的问题,请参考以下文章

Qt 中具有单个模型的表格和列表视图

基于QT的在线打字练习软件助手(C/S模型)good

C#开发BIMFACE系列24 服务端API之获取模型数据9:获取单个房间信息

在多个 qt 线程中使用单个 QSqlDatabase 连接

将多个 Falcor 数据源组合成单个模型

Qt:如何在模型/视图设置中同步对来自多个线程的数据的访问?