2011-09-13 71 views
0

我沒有看到有任何方法可以爲特定的QTreeWidgetItem定義樣式表,所以我決定嘗試使用SetBackground或SetForeground來解決我的解決方案。我試圖實現的效果是圍繞一個樹形視圖的單個widgetite的邊界,但我不知道如何用QBrush手動繪製一個,如果甚至如何去做。有任何想法嗎?提前致謝。在PyQT中實現QTreeWidgetItem的邊框

回答

2

你不能單獨畫一個帶有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_()) 
+0

巨大!如果只有所有的SO反應都清楚,簡潔並且有幫助。我永遠在你的債務! – Cryptite

+0

現在愚蠢的問題,你如何去除物品的邊界?例如,我可以將其顏色設置爲0,但仍然存在邊框的輪廓。 – Cryptite

+1

通過使用'item.setData(0,MyBorderRole,None)將數據設置爲'None'' – alexisdm