Я хотел бы отображать каждый элемент в QTreeView по-разному в зависимости от количества атрибутов, хранящихся в базе данных, и в зависимости от того, является ли элемент папкой или файлом. Однако я не понимаю, как QTreeView или QFileSystemModel взаимодействуют с делегатом. Всякий раз, когда элемент должен быть отрисован, в том числе во время инициализации, я ожидаю предоставить делегату все необходимые параметры, а затем использовать серию операторов if
внутри делегата, чтобы установить, как отрисовывается конкретный элемент. Я нашел только метод .setItemDelegate
и не знаю, когда и как на самом деле вызывается делегат или как он перебирает все элементы в модели. Ниже приведен пример, основанный на материалах в Интернете. Есть две проблемы:
Я разместил в комментариях код, который не смог заставить работать. Как только я пойму, как делегат может получать информацию от QTreeView (или вызывающего класса), я полагаю, что смогу сделать все остальное.
Мне не удалось заставить этот подкласс QTreeView отображать значки папок и файлов.
Код:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class fileSystemDelegate(QItemDelegate):
def __init__(self, parent=None):
QItemDelegate.__init__(self, parent) #shouldn't this insure the icons are drawn?
def paint(self, painter, option, index):
painter.save()
# set background
painter.setPen(QPen(Qt.NoPen))
if option.state & QStyle.State_Selected: #DURING DRAW LOOP: idx = self.currentIndex(); if self.fileSystemModel.isDir(idx): PAINT RED
painter.setBrush(QBrush(Qt.red))
else:
painter.setBrush(QBrush(Qt.white)) #ELSE PAINT WHITE
painter.drawRect(option.rect)
# draw item
painter.setPen(QPen(Qt.black))
text = index.data(Qt.DisplayRole)
painter.drawText(option.rect, Qt.AlignLeft, text) #there is no painter.drawIcon?
painter.restore()
class fileSystemBrowser(QTreeView):
def __init__(self, parent=None):
super().__init__(parent)
delegate = fileSystemDelegate()
self.setItemDelegate(delegate) # how to provide delegate with additional info about the item to be drawn ?
self.fileSystemModel = QFileSystemModel()
self.fileSystemModel.setRootPath(QDir.currentPath())
self.setModel(self.fileSystemModel)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = fileSystemBrowser()
window.show()
sys.exit(app.exec_())
ИЗМЕНИТЬ 1:
Я добавил пример «базы данных» в виде словаря и изменил подход, чтобы полагаться на метод данных, а не на делегат. Я ожидаю, что этот код будет выполнять поиск по словарю всякий раз, когда информация отображается в дереве, и, следовательно, печатать на терминале, когда пользователь вводит C:\Program Files\Internet Explorer\
на компьютере с Microsoft Windows. Однако он просто отображает каталог, ничего не выводя на терминал. Я хотел бы знать:
Как получить операторы
if
в методе данных для запуска каждого элемента на дисплее по мере их рисования?Как отобразить значок после отображения значка по умолчанию в той же строке?
Код:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
database = {'C:\Program Files\Internet Explorer\ExtExport.exe':(1,3), 'C:\Program Files\Internet Explorer\iexplore.exe':(0,0)}
class fileSystemBrowser(QTreeView):
def __init__(self, parent=None):
super().__init__(parent)
self.fileSystemModel = QFileSystemModel()
self.fileSystemModel.setRootPath(QDir.currentPath())
self.setModel(self.fileSystemModel)
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
path = self.fileSystemModel.filePath(index)
if self.fileSystemModel.isDir(index):
if database.get(path) != None:
if database[path][0] > 0:
print("Acting on custom data 0.") # add another icon after the regular folder icon
if database[path][1] > 0:
print("Acting on custom data 1.") # add another (different) icon after the regular folder or previous icon
if __name__ == '__main__':
app = QApplication(sys.argv)
window = fileSystemBrowser()
window.show()
sys.exit(app.exec_())
ИЗМЕНИТЬ 2:
Подкласс модели определенно имел значение. Теперь скрипт, похоже, вызывает мой новый метод данных для каждого элемента. К сожалению, метод данных пока не работает, поэтому в результате получается древовидное представление без значков и текста. Иногда я получаю сообщение об ошибке: «QFileSystemWatcher: не удалось добавить пути: C:/PerfLogs». Основываясь на примерах в Интернете, я прокомментировал, где, по моему мнению, могут быть мои ошибки, но я пока не могу заставить это работать. Что я делаю неправильно?
import sys
from PySide.QtCore import *
from PySide.QtGui import *
database = {'C:\Program Files\Internet Explorer\ExtExport.exe':(1,3), 'C:\Program Files\Internet Explorer\iexplore.exe':(0,0)}
class newFileModel(QFileSystemModel):
def __init__(self, parent=None):
QFileSystemModel.__init__(self, parent)
#self.elements = [[Do I need this? What should go here?]]
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
path = self.filePath(index)
if self.isDir(index):
if database.get(path) != None:
if database[path][0] > 0:
print("Acting on custom data 0.") # I can add code here for different color text, etc.
if database[path][1] > 0:
print("Acting on custom data 1.") # I'll add code later
#return self.data(index, role) # Do I need this about here?
class fileSystemBrowser(QTreeView):
def __init__(self, parent=None):
super().__init__(parent)
self.fileSystemModel = newFileModel()
self.fileSystemModel.setRootPath(QDir.currentPath())
self.setModel(self.fileSystemModel)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = fileSystemBrowser()
window.show()
sys.exit(app.exec_())
QFileInfo
ясен и выглядит очень полезным. Спасибо за знакомство. С помощьюstyle = qApp.style()
вы получаете копию объекта стиля приложения, а затем устанавливаете две иконки для адаптации к этому стилю? Запятая здесьSP_MessageBoxWarning),
просто для того, чтобы скобка была на следующей строке? 23.10.2017print('found:', (major, minor), path)
какprint('found: (%d,%d), %s' % (major, minor, path))
. Я не понимал, что ваш синтаксис действителен. 23.10.2017if path in database:
гораздо более интуитивно понятен, чем мойif database.get(path) != None:
. Я не знал, чтоin
нацелится на ключи. 23.10.2017columnCount
. Это проблема индексов, начинающихся с нуля или единицы? 23.10.2017if extra:
поclass FileSystemBrowser(QTreeView):
я в полной растерянности. Вы тестируете разные роли, но где эти роли установлены? Является ли роль параметром элемента данных, фазой отрисовки на экране, чем-то еще? Не могли бы вы добавить несколько комментариев? 23.10.2017style()
, чтобы пример работал без необходимости предоставления каких-либо файлов значков. Конечно, вы можете использовать любые значки, которые вам нравятся. Завершающая запятая по умолчанию — распространенная идиома в python: она упрощает сопровождение кода, потому что вы можете переставлять элементы вlist
,dict
и т. д., не беспокоясь о последующем исправлении запятых. Без этого очень легко ввести тонкие ошибки. Например, в списке строк отсутствие запятой может привести к объединению соседних строк. 23.10.2017print
я обычно слишком ленив, чтобы печатать все эти форматы. (3) Методget
имеет свои применения, ноin
быстрее и читабельнее. (4) Да - количество всегда будет на единицу больше, чем самый высокий индекс, из-за подсчета с нуля. 23.10.2017if role == Qt.DecorationRole:
роль задается представлением, когда оно выводит элементы данных на экран? Он постоянно делает запросы от модели? Взгляд говорит: Эй! Я сейчас работаю над элементом данных с индексом 6, есть ли Qt.DecorationRole для этого элемента? Как насчет ToolTipRole? Хорошо, теперь элемент данных с индексом 7... 23.10.2017