[英]Add additional information to items in a QTreeView/QFileSystemModel
我想根据存储在数据库中的许多属性以及项目是文件夹还是文件,以不同的方式呈现 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:
我以字典的形式添加了一个示例“数据库”,并更改了依赖数据方法而不是委托的方法。 我希望这段代码在树中显示信息时执行字典查找,因此当用户在 Microsoft Windows 计算机上输入C:\\Program Files\\Internet Explorer\\
时打印到终端。 但是,它只显示目录而不向终端打印任何内容。 我想知道:
如何在 data 方法中获取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 :
对模型进行子类化肯定会有所作为。 现在脚本似乎在每个项目上调用我的新数据方法。 不幸的是, data 方法还没有工作,所以结果是一个没有图标或文本的树视图。 有时我会收到错误消息:“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_())
这是一个基本演示,展示了如何添加带有图标和其他格式的额外列。 请注意,尝试规范化文件路径,以便比较和字典查找应该更可靠:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
database = {
QFileInfo('C:\Program Files\Internet Explorer\ExtExport.exe').absoluteFilePath(): (1, 3),
QFileInfo('C:\Program Files\Internet Explorer\iexplore.exe').absoluteFilePath(): (0, 0),
}
class FileSystemModel(QFileSystemModel):
def __init__(self, parent=None):
super().__init__(parent)
style = qApp.style()
self.icons = [
style.standardIcon(QStyle.SP_MessageBoxInformation),
style.standardIcon(QStyle.SP_MessageBoxWarning),
]
def columnCount(self, parent=QModelIndex()):
return super().columnCount(parent) + 1
def data(self, index, role=Qt.DisplayRole):
extra = False
if index.isValid():
extra = index.column() == self.columnCount(index.parent()) - 1
info = self.fileInfo(index)
path = info.absoluteFilePath()
if path in database:
major, minor = database[path]
print('found:', (major, minor), path)
if extra:
if role == Qt.DecorationRole:
if major > 0:
return self.icons[0]
else:
return self.icons[1]
elif role == Qt.DisplayRole:
return '%s/%s' % (major, minor)
elif role == Qt.ForegroundRole:
if minor > 2:
return QColor('red')
if not extra:
return super().data(index, role)
def headerData(self, section, orientation, role=Qt.DisplayRole):
if (orientation == Qt.Horizontal and
role == Qt.DisplayRole and
section == self.columnCount() - 1):
return 'Extra'
return super().headerData(section, orientation, role)
class FileSystemBrowser(QTreeView):
def __init__(self, parent=None):
super().__init__(parent)
self.fileSystemModel = FileSystemModel()
self.fileSystemModel.setRootPath(QDir.currentPath())
self.setModel(self.fileSystemModel)
self.header().moveSection(self.fileSystemModel.columnCount() - 1, 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = FileSystemBrowser()
window.show()
sys.exit(app.exec_())
编辑:
data
方法中使用的角色都记录在ItemDataRole 枚举下,介绍如下:
模型中的每个项目都有一组与之关联的数据元素,每个元素都有自己的角色。 视图使用角色来向模型指示它需要哪种类型的数据。 自定义模型应该返回这些类型的数据。
对于已添加的额外列,必须提供所有内容,因为它是一个虚拟列,不属于底层模型的一部分。 但是对于其他列,我们可以只调用基类实现来获取默认值(当然,如果需要,我们也可以为这些列返回自定义值以修改现有行为)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.