微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

QSortFilterProxyModel headerData

如何解决QSortFilterProxyModel headerData

我有 2 个 QTableViews 连接到 2 个 QSortFilterProxyModels,它们只连接到 1 个源模型 (QsqlRelationalTableModel)。

在对任何代理模型进行排序或过滤时,它会反映在相应的表视图中。但 当我修改其中一个代理模型的标头数据(装饰角色)时,它会出现在两个表视图中。

我的问题是,头数据是直接应用于源模型还是仅应用于代理?

我用它来创建一个 sqlite 示例数据库

conn = sqlite3.connect('customers.db')
c = conn.cursor()
c.execute("PRAGMA foreign_keys=on;")

c.execute("""CREATE TABLE IF NOT EXISTS provinces (
        ProvinceId TEXT PRIMARY KEY,Name TEXT NOT NULL
        )""")

c.execute("""CREATE TABLE IF NOT EXISTS customers (
        CustomerId TEXT PRIMARY KEY,Name TEXT NOT NULL,ProvinceId TEXT,FOREIGN KEY (ProvinceId) REFERENCES provinces (ProvinceId) 
                ON UPDATE CASCADE
                ON DELETE RESTRICT
        )""")

c.execute("INSERT INTO provinces VALUES ('N','northern')")
c.execute("INSERT INTO provinces VALUES ('E','Eastern')")
c.execute("INSERT INTO provinces VALUES ('W','Western')")
c.execute("INSERT INTO provinces VALUES ('S','Southern')")
c.execute("INSERT INTO provinces VALUES ('C','Central')")

c.execute("INSERT INTO customers VALUES ('1','customer1','N')")
c.execute("INSERT INTO customers VALUES ('2','customer2','E')")
c.execute("INSERT INTO customers VALUES ('3','customer3','W')")
c.execute("INSERT INTO customers VALUES ('4','customer4','S')")
c.execute("INSERT INTO customers VALUES ('5','customer5','C')")

conn.commit()
conn.close()

这是为代理模型应用装饰时显示我的问题的窗口:

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.db = QsqlDatabase.addDatabase("QsqlITE")
        self.db.setDatabaseName("customers.db")
        self.db.open()

        self.model = QsqlRelationalTableModel(self,self.db)
        self.model.setTable("customers")
        self.model.select()

        self.proxy1 = QSortFilterProxyModel()
        self.proxy1.setSourceModel(self.model)

        self.proxy2 = QSortFilterProxyModel()
        self.proxy2.setSourceModel(self.model)

        hBox = QHBoxLayout()

        self.tblView1 = QTableView()
        self.tblView1.setModel(self.proxy1)

        self.tblView2 = QTableView()
        self.tblView2.setModel(self.proxy2)

        hBox.addWidget(self.tblView1)
        hBox.addWidget(self.tblView2)

        icon = QIcon(Qpixmap("Resources/icon.png"))

        self.proxy1.setHeaderData(
            1,Qt.Orientation.Horizontal,icon,Qt.ItemDaTarole.decorationRole)

        widget = QWidget()
        widget.setLayout(hBox)
        self.setLayout(hBox)
        self.show()


def main():
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec_())


if __name__ == '__main__':
    main()

解决方法

问题是因为proxymodel的setHeaderData方法调用了sourcemodel的setHeaderData,也就是相当于调用了sourceModel的方法,导致它也传播到了其他proxymodel。一种可能的解决方案是覆盖代理模型的 headerData 方法,以便它仅在该代理模型中返回所需的值。

import sys

from PyQt5.QtCore import QSortFilterProxyModel,Qt
from PyQt5.QtGui import QIcon,QPixmap
from PyQt5.QtWidgets import QWidget,QHBoxLayout,QTableView,QApplication
from PyQt5.QtSql import QSqlDatabase,QSqlRelationalTableModel


class SortFilterProxyModel(QSortFilterProxyModel):
    def headerData(self,section,orientation,role=Qt.DisplayRole):
        if (
            section == 1
            and orientation == Qt.Horizontal
            and role == Qt.ItemDataRole.DecorationRole
        ):
            return QIcon(QPixmap("Resources/icon.png"))
        return super().headerData(section,role)


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("customers.db")
        self.db.open()

        self.model = QSqlRelationalTableModel(self,self.db)
        self.model.setTable("customers")
        self.model.select()

        self.proxy1 = SortFilterProxyModel()
        self.proxy1.setSourceModel(self.model)

        self.proxy2 = QSortFilterProxyModel()
        self.proxy2.setSourceModel(self.model)

        hBox = QHBoxLayout(self)

        self.tblView1 = QTableView()
        self.tblView1.setModel(self.proxy1)

        self.tblView2 = QTableView()
        self.tblView2.setModel(self.proxy2)

        hBox.addWidget(self.tblView1)
        hBox.addWidget(self.tblView2)


def main():
    App = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(App.exec_())


if __name__ == "__main__":
    main()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。