繁体   English   中英

向 QTreeView/QFileSystemModel 中的项目添加附加信息

[英]Add additional information to items in a QTreeView/QFileSystemModel

我想根据存储在数据库中的许多属性以及项目是文件夹还是文件,以不同的方式呈现 QTreeView 中的每个项目。 但是,我不明白 QTreeView 或 QFileSystemModel 如何与委托进行通信。 每当必须绘制项目时,包括在初始化期间,我希望为委托提供它所需的所有参数,然后在委托中使用一系列if语句来设置如何绘制特定项目。 我只找到了.setItemDelegate方法,不知道实际调用委托的时间或方式,也不知道它如何循环遍历模型中的所有项目。 以下是基于在线材料的示例。 有两个问题:

  1. 我将代码放在我无法开始工作的注释中。 一旦我了解了委托如何从 QTreeView(或调用类)接收信息,我相信我可以完成剩下的工作。

  2. 我无法让 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\\时打印到终端。 但是,它只显示目录而不向终端打印任何内容。 我想知道:

  1. 如何在 data 方法中获取if语句以在绘制时为显示中的每个项目触发?

  2. 显示默认图标,如何在同一行显示图标?

代码:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM