QSortFilterProxyModel headerData
У меня есть 2 QTableView, подключенных к 2 QSortFilterProxyModel, которые подключены только к 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()
1 ответ
Проблема вызвана тем, что метод setHeaderData прокси-модели вызывает setHeaderData исходной модели, то есть это эквивалентно вызову метода sourceModel, заставляя его также распространяться на другие прокси-модели. Возможное решение - переопределить метод 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, orientation, 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()