3

デリゲートを使用してツリー アイテムの背景色だけを変更するにはどうすればよいですか?

テキストの上にペイントせずにこれを行う方法を理解できませんでした。つまり、以下のコードを使用すると、テキストの上に色が描画されます。テキストは背景のにあります...

def paint(self, painter, option, index):
    MyDelegate.paint(self, painter, option, index)

    painter.save()

    # set background color
    painter.setPen(QPen(Qt.NoPen))
    if self.item.is_set and option.state & QStyle.State_Selected:
        painter.setBrush(QBrush(QtGui.QColor(100, 200, 0, 200)))
    else:
        painter.setBrush(QBrush(Qt.NoBrush))

    painter.drawRect(option.rect)

    painter.restore()

できるだけ継承したい。

...

コメントに関して、「QTableView行に色を設定する」という回答を適用しようとしましたが、Pythonで機能させることができないようです。optionV4.backgroundBrush() がどのように機能するかはわかりません。この変更が戻り値なしで使用されることになっているように、オプションは参照によって使用されますか?

(これらはオーバーライドせずに使用されますpaint)

def initStyleOption(self, option, index):
    print("initStyleOption...")
    MyBaseDelegate.initStyleOption(self, option, index)

    optionV4 = QtGui.QStyleOptionViewItemV4(option)
    optionV4.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))

私もこれを試しました:

def initStyleOption(self, option, index):
    MyBaseDelegate.initStyleOption(self, option, index)
    option.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))

...この:

def initStyleOption(self, option, index):
    option.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))
    MyBaseDelegate.initStyleOption(self, option, index)

ドキュメントによると、これは何も返さないはずなので、オプション IS は参照渡しであると仮定します。これは理にかなっています。

動作する別の例を見つけました(ただし、理解しようとはしていません)

def paint(self, painter, option, index):
    option = QtGui.QStyleOptionViewItemV4(option)  # Needed for "widget"
    self.initStyleOption(option, index)  # <--- I did not override this

    option.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))
    option.widget.style().drawControl(QStyle.CE_ItemViewItem, option, painter)

    ColumnBaseDelegate.paint(self, painter, option, index)

...しかし、背景色は選択色によって塗りつぶされます。アイテムが選択されたときに背景色を変更しようとしているので、これは問題です。選択色を操作するための別のブラシまたは方法はありますか? 特定の種類のアイテムを別の色にする必要があります。

自分の背景を描画する前に選択状態を反転することを示す答えを試しましたが、何らかの理由で空の背景が描かれました。それをペイントに入れることはうまくいきましたが...

def paint(self, painter, option, index):

    if option.state & QStyle.State_Selected:
        option.state &= ~QStyle.State_Selected  # Invert state

        # This "cast", which is needed to get option.widget, seems to be
        #   needed for backgroundBrush as well.
        option = QtGui.QStyleOptionViewItemV4(option)  # Cast for widget
        option.backgroundBrush = QBrush(QColor(100, 200, 100, 200))

        option.widget.style().drawControl(QStyle.CE_ItemViewItem, option, painter)

    super(MyDelegate, self).paint(painter, option, index)

理由がわからないので、現時点では回答に追加しません。

4

1 に答える 1

4

選択したアイテムの背景色をオーバーライドするには、 で選択済みフラグを無効にしinitStyleOptionます。例えば:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class SelectionColorDelegate(QStyledItemDelegate):
        def __init__(self, parent):
        super(SelectionColorDelegate, self).__init__(parent)

    def initStyleOption(self, option, index):
        # let the base class initStyleOption fill option with the default values
        super(SelectionColorDelegate,self).initStyleOption(option, index)
        # override what you need to change in option
        if option.state & QStyle.State_Selected:
            option.state &= ~ QStyle.State_Selected
            option.backgroundBrush = QBrush(QColor(100, 200, 100, 200))

if __name__ == "__main__":
    app = QApplication(sys.argv)    
    treeWidget = QTreeWidget()
    treeWidget.setColumnCount(2)
    for i in range(5):
        item = QTreeWidgetItem(["Item %d"%i, "data" ])
        treeWidget.addTopLevelItem(item)
        for j in range(3):
            subItem = QTreeWidgetItem(["SubItem %d, %d"%(i,j), "subdata"])
            item.addChild(subItem)
        treeWidget.expandItem(item)

    treeWidget.setItemDelegate(SelectionColorDelegate(treeWidget))    
    treeWidget.show()   

    app.exec_()
    sys.exit()

QTreeView.drawRowどうやら、デリゲートpaint関数が呼び出される前に背景もペイントされるため、インデントされたアイテムの場合、その背景の一部はデフォルトの色を保持します。

于 2012-06-09T01:31:36.373 に答える