Достижение границы для QTreeWidgetItem в PyQT - PullRequest
0 голосов
/ 14 сентября 2011

Я не вижу никакого способа определить таблицу стилей для определенного QTreeWidgetItem, поэтому я решил попытаться выяснить свое решение, используя либо SetBackground, либо SetForeground. Эффект, которого я пытаюсь достичь, - это граница вокруг одного элемента виджета для дерева, но я не могу понять, как нарисовать его вручную с помощью QBrush, даже если это так. Есть идеи? Заранее спасибо.

1 Ответ

2 голосов
/ 14 сентября 2011

Нельзя нарисовать границу с одним QTreeWidgetItem, вам нужно использовать делегата.
И вы можете хранить стиль рамки в каждом элементе, для которого вы хотите иметь рамку под пользовательской «ролью», чтобы иметь возможность извлекать ее и использовать внутри делегата.

Вот полный рабочий и прокомментированный пример:

import sys
from PyQt4 import QtGui, QtCore

class BorderItemDelegate(QtGui.QStyledItemDelegate):
    def __init__(self, parent, borderRole):
        super(BorderItemDelegate, self).__init__(parent)
        self.borderRole = borderRole

    def sizeHint(self, option, index):        
        size = super(BorderItemDelegate, self).sizeHint(option, index)
        pen = index.data(self.borderRole).toPyObject()
        if pen is not None:        
            # Make some room for the border
            # When width is 0, it is a cosmetic pen which
            # will be 1 pixel anyways, so set it to 1
            width = max(pen.width(), 1)            
            size = size + QtCore.QSize(2 * width, 2 * width)
        return size

    def paint(self, painter, option, index):
        pen = index.data(self.borderRole).toPyObject()
        # copy the rect for later...
        rect = QtCore.QRect(option.rect)
        if pen is not None:
            width = max(pen.width(), 1)
            # ...and remove the extra room we added in sizeHint...
            option.rect.adjust(width, width, -width, -width)      

        # ...before painting with the base class method...
        super(BorderItemDelegate, self).paint(painter, option, index)

        # ...then paint the borders
        if pen is not None:
            painter.save()  
            # The pen is drawn centered on the rectangle lines 
            # with pen.width()/2 width on each side of these lines.
            # So, rather than shifting the drawing of pen.width()/2
            # we double the pen width and clip the part that would 
            # go outside the rect.
            painter.setClipRect(rect, QtCore.Qt.ReplaceClip);          
            pen.setWidth(2 * width)
            painter.setPen(pen)
            painter.drawRect(rect)     
            painter.restore()

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    mainWindow = QtGui.QMainWindow() 
    mainWindow.resize(300,300); 

    # Define the Qt.ItemDataRole we will be using 
    MyBorderRole = QtCore.Qt.UserRole + 1

    # Create and populate the view
    treeWidget = QtGui.QTreeWidget(mainWindow)
    for i in range(3):
        item = QtGui.QTreeWidgetItem(["Item %d"%(i)])                
        treeWidget.addTopLevelItem(item)        
        treeWidget.expandItem(item);
        for j in range(10):
            subItem = QtGui.QTreeWidgetItem(["SubItem %d %d"%(i,j)])
            pen = QtGui.QPen(QtGui.QColor.fromHsv(j*25, 255, 255))
            pen.setWidth(j)
            # Store the border pen in the item as the role we defined
            subItem.setData(0, MyBorderRole, pen)
            item.addChild(subItem)

    # Pass the role where we stored the border pen to the delegate constructor
    delegate = BorderItemDelegate(treeWidget, MyBorderRole) 
    treeWidget.setItemDelegate(delegate)

    mainWindow.setCentralWidget(treeWidget)
    mainWindow.show()   

    sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...