Прокси-модель, содержащая на 1 столбец больше, чем модель-источник.
qt5, model, proxy, QIdentityProxyModel, column, PyQt5
Здравствуйте!
Пытаюсь переопределить QIdentityProxyModel так, чтобы она имела на 1 столбец больше, чем ее модель-источник, но никак не могу добиться успешного результата.
Вот заготовка, очищенная от мусора:
#!/usr/bin/python3 # -*- coding: utf-8 -*- """Попытка реализовать прокси-модель, содержащую на 1 столбец больше, чем модель-источник.""" import sys import typing from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * app = None class MyProxyModel(QIdentityProxyModel): """Прокси-модель, содержащая на 1 столбец больше, чем модель-источник.""" VALUE = "===" def columnCount(self, parent: QModelIndex = None) -> int: """Переопределяет соответствующий родительский метод. columnCount(self, parent: QModelIndex = QModelIndex()) -> int """ if not self.sourceModel(): return 0 return super().columnCount() + 1 def data(self, proxyIndex: QModelIndex, role: int = None) -> typing.Any: """Переопределяет соответствующий родительский метод. data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any """ assert self.checkIndex(proxyIndex) if role is None: role = Qt.DisplayRole if not self.sourceModel(): return None if role == Qt.DisplayRole: if proxyIndex.column() == self.columnCount() - 1: # text = "" # for column in range(self.columnCount() - 1): # # index = self.index(proxyIndex.row(), column, proxyIndex.parent()) # index = self.sibling(proxyIndex.row(), column, proxyIndex) # text += "->" + str(super().data(index)) # return text return self.VALUE return super().data(proxyIndex, role) def headerData(self, section: int, orientation: int, role: int = None) -> typing.Any: """Переопределяет соответствующий родительский метод. headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.DisplayRole) -> Any """ if role is None: role = Qt.DisplayRole if orientation == Qt.Horizontal and role == Qt.DisplayRole and section == self.columnCount() - 1: return "New column" return super().headerData(section, orientation, role) # def mapFromSource(self, sourceIndex: QModelIndex) -> QModelIndex: # # return super().mapFromSource(sourceIndex) # if not self.sourceModel() or not sourceIndex.isValid(): # return QModelIndex() # # assert sourceIndex.model() is self.sourceModel() # return self.createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer()) # # def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex: # # return super().mapToSource(proxyIndex) # if not self.sourceModel() or not proxyIndex.isValid(): # return QModelIndex() # # assert proxyIndex.model() is self # return self.sourceModel().createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer()) def main(): global app app = QApplication(sys.argv) sourceModel = QFileSystemModel(app) sourceModel.setRootPath(".") proxyModel = MyProxyModel(app) proxyModel.setSourceModel(sourceModel) treeView = QTreeView() treeView.setMinimumWidth(800) treeView.setModel(proxyModel) treeView.setColumnWidth(0, 400) # TODO: По прежнему выделяет только ячейку. Надо переопределить MyProxyModel.mapSelection<From/To>Source()! treeView.setSelectionBehavior(treeView.SelectRows) # treeView.setSelectionMode(treeView.SingleSelection) treeView.show() def checkProxyModel(): print("BEGIN checkProxyModel()") assert proxyModel.columnCount() == sourceModel.columnCount() + 1 proxyIndexWithZeroColumn = proxyModel.index(0, 0) sourceIndexWithZeroColumn = sourceModel.index(0, 0) assert proxyModel.data(proxyIndexWithZeroColumn) == sourceModel.data(sourceIndexWithZeroColumn) proxyIndexWithPenultimateColumn = proxyModel.index(0, proxyModel.columnCount() - 2) sourceIndexWithLastColumn = sourceModel.index(0, sourceModel.columnCount() - 1) assert proxyModel.data(proxyIndexWithPenultimateColumn) == sourceModel.data(sourceIndexWithLastColumn) proxyIndexWithLastColumn = proxyModel.index(0, proxyModel.columnCount() - 1) assert proxyModel.data(proxyIndexWithLastColumn, Qt.DisplayRole) == proxyModel.VALUE print("END checkProxyModel()") QTimer.singleShot(0, checkProxyModel) sys.exit(app.exec()) if __name__ == '__main__': main()
В отображении появляется новый столбец с нужным заголовком, но без данных.
Я не понимаю, каким образом мне нужно переопределить методы mapFromSource/mapToSource, чтоб все заработало...
Или же вообще нужно переопределять index(), parent() и прочие?..
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.Вам це подобається? Поділіться в соціальних мережах!
sf
- sdfsdfkp fgskpgokspdog
- 14 жовтня 2024 р. 12:09
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:90бали,
- Рейтинг балів8
МВ
- Максим Васильев
- 02 жовтня 2024 р. 01:14
Qt - Тест 001. Сигналы и слоты
- Результат:68бали,
- Рейтинг балів-1
ЛС
- Лев Семенов
- 30 вересня 2024 р. 08:04
C++ - Тест 001. Первая программа и типы данных
- Результат:53бали,
- Рейтинг балів-4
Останні коментарі
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
Игорь Максимов05 жовтня 2024 р. 04:51
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Анатолий Кононенко04 лютого 2024 р. 22:50
Тепер обговоріть на форумі
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
ИМ
Реализация навигации по разделам Спасибо Евгений!
Игорь Максимов03 жовтня 2024 р. 01:05
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
Кирилл Гусарев27 вересня 2024 р. 06:09
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
Добрый день.
Вот рабочий вариант
Вам надо было метод index переопределить, чтобы создавался QModelIndex для вашей спец-колонки
Огромное спасибо за ответ!:)
Но вариант все же не является рабочим.
Почти всегда дерево отображается корректно и даже раскрываются новые уровни, если нажать точно на треугольник слева. Но если сменить выделенный элемент, например, щелкнуть мышкой на какую-нибудь ячейку, то приложение падает, и единственным выводом в консоль является:
qVersion() == 5.11.1, OS == Kubuntu 18.04
Также приложение падает, если вернуть в метод data() строчку
Изучение исходников метода index() в QFileSystemModel и QStandardItemModel ничем пока не помогло. :(
Падение с assert - это уже питоновские заморочки, дайте туда более корректную проверку, поскольку проверка на None просто не работает адекватно в том случае.
Что касается установки информации, то возможно, что ещё потребуется перепределить метод setData. Переопределите его и посмотрите через print, что туда прилетает в индексе и роли.
До setData() я еще не добрался, так как пока что даже reed only модель не работает.
В конкретном данном случае в
всегда передается экземпляр QModelIndex. Поэтому это не является проблемой обработки None.
Да и на падения при смене текущей ячейки это не влияет.
Я Вам очень благодарен за то, что все равно пытаетесь помочь!
Если определить метод index() таким костыльным и затратным образом:
то приложение уже перестает падать, но строку вьюха выделить все еще не может, так как для модельного индекса из моего столбца internalPointer() хранит данные, отличающиеся от данных для других столбцов.
Также в этом случае в консоль выводится соответствующее сообщение:
Can't select indexes from different model or with different parents
В итоге, эмулировать существование дополнительных столбцов через QIdentityModel на PyQt5(5.11.1) получается только для плоских (табличных, списочных) моделей.
Для древовидных моделей при создании модельного индекса в internalPointer необходимо хранить некие данные о родителе. Но если установить в него данные можно, то при считывании PyQt не может определить их тип из-за того, что в С++ они объявлены как void*, если считывать через internalPointer(), и qintptr, если считывать через internalId().
В следствие чего, программа крашится.
Попробуйте ещё PySide 2 - это официально поддерживаемый пакет привязок Python к Qt, возможно, что там не будет таких проблем.
Вот работающий вариант переопределения метода index():
Теперь корректно устанавливаются дынные об элементе-предке и программа больше не крашится.
Но остается вопрос, как заставить вьюху менять выделение/текущий индекс при щелчке мышкой по ячейкам из нового столбца?..
Изучение исходников QTreeView и QAbstractItemView показало, что для осуществления обработки нажатий по элементам нового столбца необходимо переопределить метод sibling():
Полагаю, что вам придётся везде создавать соответствующий валидный индекс для дополнительного столбца, если что-то не работает