2011-09-13 7 views
0

特定のQTreeWidgetItemのスタイルシートを定義する方法がないことがわかりましたので、SetBackgroundまたはSetForegroundを使用して解決策を見つけようとしました。私が達成しようとしている効果は、ツリービューのための単一のwidgetitemを境界線にしていますが、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

関連する問題