如何在QTreeView中更改特定分支的颜色?

时间:2011-08-17 18:50:30

标签: python qt

我有一个QTreeView,我已经想出如何在我的主类中使用setStyleSheet来设置它的样式:

self.view.setStyleSheet("""
    QTreeView::item {
        margin: 2px;
    }
""")

这将调整整个QTreeView的样式。但我希望树中的某些项目能够加粗。当我创建分支(使用[the parent widget].appendRow("the name of the item"))时,有没有办法“标记”或隔离特定项目,以便它可以以相同的方式设置样式?我认为答案与'AccessibleName'或'ObjectName'属性有关,但我无法在其上找到文档。

更新:这是我到目前为止所做的:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import division
from __future__ import print_function
from future_builtins import *

import os, sys
from PySide.QtCore import *
from PySide.QtGui import *

path_to_media = '/Volumes/show/vfx/webisodes/%d1%/seq/%d2%/%d3%/renders/2d/comp/'

class FileTree(QTreeView):
    """Main file tree element"""
    def __init__(self):
        QTreeView.__init__(self)
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Space or event.key() == Qt.Key_Return:
            index = self.selectedIndexes()[0]
            crawler = index.model().itemFromIndex(index)
            if crawler.uri:
                print("launching", crawler.uri)
                p = os.popen(('open -a "RV.app" "'+ crawler.uri) +'"', "r")
        QTreeView.keyPressEvent(self, event)

class Branch(QStandardItem):
    """Branch element"""
    def __init__(self, label, uri = None, tag = None):
        QStandardItem.__init__(self, label)
        self.uri = uri

class AppForm(QMainWindow):
    def __init__(self, parent = None):
        super(AppForm, self).__init__(parent)
        self.model = QStandardItemModel()
        self.view = FileTree()
        self.view.setStyleSheet("""
            QTreeView::item {
                margin: 2px;
            }
        """)
        self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.view.setModel(self.model)
        self.setCentralWidget(self.view)
        self.Grow()
        # self.view.setSortingEnabled(True)

    def Grow(self):
        """Populates FileTree (using BuildBranch())"""
        global path_to_media
        self.path = {}
        self.path['source'] = path_to_media
        self.path['parts'] = []
        self.path['depth'] = 0
        self.path['crawl'] = {}
        for i in self.path['source'].split('%'):
            if i[0] == "d" and i[1].isdigit():
                self.path['depth'] += 1
            else:
                self.path['parts'].append(i)
        self.BuildBranch(self.path['parts'], self.path['depth'], parentWidget = self.model.invisibleRootItem())

    def BuildBranch(self, parts, depth, uri = '', count = 0, parent = '', parentWidget = ''):
        """Recursively crawls folder structure and adds appropriate branches"""
        if not uri: uri = parts[0]
        else: uri += parent + parts[count]
        try:
            if os.listdir(uri):
                for i in os.listdir(uri):
                    if i[0] != '.':
                        if count != depth:
                            if os.path.isdir(uri):
                                thisWidget = Branch(i)
                                parentWidget.appendRow(thisWidget)
                                self.BuildBranch(parts, depth, uri, count + 1, i, parentWidget = thisWidget)
                            else:
                                thisWidget = Branch(i)
                                parentWidget.appendRow(thisWidget)
                        elif count == depth:
                            thisWidget = Branch(i, uri + i, 'media')
                            parentWidget.appendRow(thisWidget)
            else:
                print("nothing here; nuking " + parent)
                # Need to add code to nuke unused branch
        except OSError:
            print("Folder structure error... nuking the branch")
            # Need to add code to nuke unused branch

def main():
    app = QApplication(sys.argv)
    form = AppForm()
    form.resize(800, 600)
    form.setWindowTitle('Qt Dailies')
    form.show()
    app.exec_()

if __name__ == "__main__":
    main()

更新2:好的,我修改了我的Branch类,如果将'bold'传递给它,它会使分支变粗(理论上)......

class Branch(QStandardItem):
    def __init__(self, label, uri = None, tag = None):
        QStandardItem.__init__(self, label)
        self.uri = uri
        if tag == 'bold':
            self.setData(self.createBoldFont(), Qt.FontRole)
    def createBoldFont(self):
        if self.font: return self.font
        self.font = QFont()
        self.font.setWeight(QFont.Bold)
        return self.font

...但是在代码运行时,似乎没有任何事情发生。我还没有得到什么?

2 个答案:

答案 0 :(得分:1)

Qt的模型 - 视图架构允许描述正在执行的different roles的数据。例如,有一个编辑数据,显示数据等的角色。您对字体角色(即Qt::FontRole)感兴趣,因为font有一个weight枚举,其中加粗是一个价值。

建立分支时,首先需要确定哪些项目应该加粗。我假设你有一个这样的方法可以识别它们是否应该是粗体:

def should_be_bolded(self, item):
    return 1 # your condition checks

现在只需在字体上设置权重,并使用setData方法设置项目的字体角色:

def BuildBranch(...):
    thisWidget = Branch(i)
    if self.should_be_bolded(thisWidget):
        thisWidget.setData(self.createBoldFont(), Qt.FontRole)

def createFont(self):
    if self.font: return self.font
    self.font = QFont()
    self.font.setWeight(QFont.Bold)
    return self.font

但是等等......你已经有了QtandardItem的子类,所以你可以使用它:

class Branch(QStandardItem):
    """Branch element"""
    def __init__(self, label, uri = None, tag = None):
        QStandardItem.__init__(self, label)
        self.uri = uri
        if self.should_be_bolded():
            self.bold_myself()

您必须修复should_be_boldedbold_myself方法,相应地进行清理,但希望您明白这一点。

Stephen pointed out你也可以将QAbstractItemModel中的一个子类化,就像你正在使用的QStandardItemModel一样,并返回一个特定的Qt.FontRole。他的方式使得这些知识隐含在模型中。确定知识最佳所在的位置并将其放置在最合适的位置,无论是项目,树创建算法,模型还是视图模型。

答案 1 :(得分:0)

在模型的data()方法中,您可以添加代码以根据项目的内容设置字体。例如,如果您想在一个特定行中加粗所有内容,

def data(self, index, role):

    if role == QtCore.Qt.FontRole:
       if index.row() == 1:
           boldFont = QtGui.QFont()
           boldFont.setBold(True)
           return boldFont

您需要一种方法来在为其指定索引时检索分支的名称。这取决于树模型的实现。

Qt模型/视图tutorial有一个很好的例子,尽管它是用C ++编写的。请参阅第2.2节(使用角色扩展只读示例)。