Python 向QTreeView/QFileSystemModel中的项添加其他信息

Python 向QTreeView/QFileSystemModel中的项添加其他信息,python,qt,pyside,qtreeview,qfilesystemmodel,Python,Qt,Pyside,Qtreeview,Qfilesystemmodel,我希望根据数据库中存储的许多属性以及项目是文件夹还是文件,以不同的方式呈现QTreeView中的每个项目。但是,我不理解QTreeView或QFileSystemModel如何与委托通信。无论何时必须绘制项目,包括在初始化期间,我都希望为委托提供它所需的所有参数,然后在委托中使用一系列if语句来设置特定项目的绘制方式。我只找到了.setItemDelegate方法,不知道何时或如何实际调用委托,也不知道它如何循环遍历模型中的所有项。下面是一个基于在线材料的示例。有两个问题: 我把代码放在我无法工

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

  • 我把代码放在我无法工作的注释中。一旦我了解了委托如何从QTreeView(或调用类)接收信息,我相信我可以完成其余的工作

  • 我无法让QTreeView的这个子类显示文件夹和文件图标

  • 代码:

    编辑1:

    我以字典的形式添加了一个“数据库”示例,并改变了依赖数据方法而不是委托的方法。我希望这段代码在树中显示信息时执行字典查找,因此当用户在Microsoft Windows计算机上输入
    C:\Program Files\Internet Explorer\
    时,会打印到终端。但是,它只显示目录,而不向终端打印任何内容。我想知道:

  • 如何使data方法中的
    if
    语句在绘制时为显示中的每个项目触发

  • 在同一行上显示默认图标后,如何显示图标

  • 代码:

    编辑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_())
    

    下面是一个基本演示,演示如何添加带有图标和其他格式的额外列。请注意,尝试规范化文件路径,以便比较和字典查找更可靠:

    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
    方法中使用的角色都记录在下,介绍如下:

    模型中的每个项都有一组与其关联的数据元素, 每个人都有自己的角色。视图使用这些角色来指示 模型需要哪种类型的数据。自定义模型应该返回 这些类型的数据


    对于已添加的额外列,必须提供所有内容,因为它是一个虚拟列,不属于基础模型的一部分。但对于其他列,我们只需调用基类实现即可获得默认值(当然,如果需要,我们还可以为这些列返回自定义值以修改现有行为)。

    根据您想要做的具体操作,项委托可能会有些过分。你确定你想自己画所有的东西吗?这可能是一项艰巨的工作。您希望更改哪些特定属性?子类化文件模型并重新实现
    数据
    方法看起来更容易实现。我想根据fileSystemBrowser类实例(最终)可用的参数更改视图中的背景颜色、文本颜色、文本字体以及可能的图标。是文件模型子类化和重写数据方法的示例吗?如果是这样的话,很遗憾,我不理解这一点。我熟悉像ggplot2 for R这样的图形系统。对于Qt委托,我正在寻找但没有找到任何熟悉的东西。您需要对模型进行子类化,而不是树视图。除了为它们创建额外的列之外,我看不到任何添加多个图标的简单方法。在文件图标之后插入附加图标的想法对我来说似乎很奇怪-它肯定会产生一个非常混乱和丑陋的界面。额外的列将更加用户友好,并且更易于实现。函数必须返回所请求的数据,在您的情况下,它不会返回任何内容,如果您只想知道它是否正在调用,我建议
    返回QFileSystemModel.data(self、index、role)
    在本例中,我在Linux中使用了没有空格的路径,如果在输入数据库中的路径时打印了该函数,则该函数可以完美地工作。我要花一天或更多的时间来研究你是如何完成的。(对我来说)有很多新方法。@davideps。很高兴你觉得它有用。请随意询问我使用的方法是否有什么让您困惑的地方。
    QFileInfo
    上的文档非常清晰,看起来非常有用。谢谢你的介绍。使用
    style=qApp.style()
    可以获得应用程序“样式对象”的副本,然后设置两个图标以适应该样式?这里的尾随逗号是否只是为了让括号位于下一行?从Python教程中,我学会了在打印时始终使用占位符,并将
    print('found:',(major,minor),path)
    写成
    print('found:(%d,%d),%s%%(major,minor,path))
    。我没有意识到您的语法是有效的。数据库中的
    if路径:
    比我的
    if数据库更直观。get(path)!=无:
    。我没有意识到中的
    会以键为目标。
    
    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_())