代码之家  ›  专栏  ›  技术社区  ›  davideps

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

  •  1
  • davideps  · 技术社区  · 7 年前

    我希望根据存储在数据库中的许多属性以及项目是文件夹还是文件,以不同的方式呈现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_())
    

    C:\Program Files\Internet Explorer\ 在Microsoft Windows计算机上。但是,它只显示目录,不向终端打印任何内容。我想知道:

    1. 我怎样才能得到 如果 数据方法中的语句是否在绘制时为显示中的每个项目触发?

    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 :

    子类化模型确实起到了作用。现在,脚本似乎正在对每个项调用我的新数据方法。不幸的是,数据方法还不起作用,因此结果是一个没有图标或文本的树视图。有时我会收到错误:“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_())
    
    1 回复  |  直到 3 年前
        1
  •  1
  •   ekhumoro    7 年前

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

    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 enum ,并介绍如下:

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

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