0

i have a treeWidget with itemWidget set on columns, but after dragging the widgets are gone, and the dropping indicator is opaque

  1. How can i make the widget persist after dropping
  2. How to make dropping indicator transparent ? ( i'm on centos 6.5, the compositing manager is not running)

dropping indicator not transparent

item widgets gone after dropping

executable example

#!/usr/bin/env python2
import os
import sys
import re

from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt, QString


class MyTreeWidget(QtGui.QTreeWidget):
    def __init__(self, parent=None):
        super(MyTreeWidget, self).__init__(parent)

class CommandWidget(QtGui.QDialog):

    def __init__(self, parent=None, level=0,script='echo /path/to/script'):
        super(CommandWidget, self).__init__()
        self.layout = QtGui.QHBoxLayout(self)

        browseBtn = QtGui.QPushButton(parent)

        browseBtn.setMinimumSize(QtCore.QSize(0, 25))
        # level, path = val

        # levelNum = re.search('(?<=level).+', level).group()
        browseBtn.setText('%s : %s' % (level, script))
        self._level = int(level)
        self._script = script
        browseBtn.setStyleSheet("text-align: left")

        self.layout.addWidget(browseBtn)

        # self.updateGeometry()
        self.browseBtn = browseBtn
        # self.layout.addWidget(browseBtn)
        self.browseBtn.clicked.connect(self.browseCommandScript)
        self.browseBtn.setIconSize(QtCore.QSize(64, 64))

    def browseCommandScript(self):
        script = QtGui.QFileDialog.getOpenFileName(
            self, 'Select Script file', '/home/xxx/python', ".py Files (*.py);;Executable Files (*)")
        if script:
            self._script = script
            button_label = re.search('[^\\/]*$',script).group()
            self.browseBtn.setText(('%s : %s' % (self._level, button_label)))

    @property
    def level(self):
        return self._level

    @level.setter
    def level(self, value):
        self._level = value

    @property
    def script(self):
        return self._script

    @script.setter
    def script(self, value):
        self._script = value


class MyLineEdit(QtGui.QWidget):
    def __init__(self,value=None,parent=None):
        super(MyLineEdit,self).__init__(parent)
        self.layout = QtGui.QHBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setMargin(3)

        self.lineEdit = QtGui.QLineEdit(value)
        spacer1 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        spacer2 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)

        self.lineEdit.setContentsMargins(2,2,2,2)
        self.lineEdit.setAlignment(Qt.AlignHCenter)

        self.layout.addItem(spacer1)
        self.layout.addWidget(self.lineEdit)
        self.layout.addItem(spacer2)

        self.lineEdit.setMaximumSize(QtCore.QSize(70, 25))
        self.lineEdit.textEdited.connect(self._update_item_widget_data)

    def text(self):
        return self.lineEdit.text()

    def setText(self,text):
        return self.lineEdit.setText(text)   


    def _update_item_widget_data(self,text):
        # print 'update',text
        self.treeWidgetItem.setData(1,Qt.UserRole,text)

class TheUI(QtGui.QDialog):

    def __init__(self, args=None, parent=None):
        super(TheUI, self).__init__(parent)
        self.layout = QtGui.QVBoxLayout(self)
        treeWidget = MyTreeWidget()

        button = QtGui.QPushButton('Add')
        self.layout.addWidget(treeWidget)
        self.cssEditTE = QtGui.QPlainTextEdit()

        self.layout.addWidget(button)
        self.layout.addWidget(self.cssEditTE)

        self.cssEditTE.textChanged.connect(self._update_css)

        treeWidget.setHeaderHidden(True)
        treeWidget.setRootIsDecorated(False)

        layout = QtGui.QHBoxLayout(self)
        rootDecorationCB = QtGui.QCheckBox('RootIsDecorated')
        layout.addWidget(rootDecorationCB)
        self.layout.addLayout(layout)
        rootDecorationCB.stateChanged.connect(self._update_root_decorated)

        indentationSlider = QtGui.QSlider()
        indentationSlider.setOrientation(Qt.Horizontal)
        indentationSlider.setRange(0,100)
        indentationSlider.setValue(20)
        indentationSlider.valueChanged.connect(self._alter_indentation)
        layout.addWidget(indentationSlider)


        self.layout.setStretchFactor(treeWidget,1)

        self.treeWidget = treeWidget
        self.button = button
        self.button.clicked.connect(lambda *x: self.addCmd())

        HEADERS = ( "script", "chunksize", "mem" )
        self.treeWidget.setHeaderLabels(HEADERS)
        self.treeWidget.setColumnCount( len(HEADERS) )

        self.treeWidget.setColumnWidth(0,200)
        self.treeWidget.header().show()

        for i in range(len(HEADERS)):
            self.treeWidget.headerItem().setTextAlignment(i,Qt.AlignHCenter)


        self.treeWidget.setDragDropMode(QtGui.QAbstractItemView.InternalMove)

        self.treeWidget.setIndentation(60)

        self.resize(500,700)

        for i in xrange(2):
            self.addCmd()

        item = self.addCmd()
        self.addCmd(parent = item)
        self.addCmd(parent = item)
        item = self.addCmd()

        item=self.addCmd(parent = item)
        self.addCmd(parent = item)
        self.addCmd()

        self.treeWidget.setColumnWidth(0,200)

    def addCmd(self, level=0, script='echo /path/to/script',parent=None):
        'add a level to tree widget'

        root = self.treeWidget.invisibleRootItem()

        if parent is None:
            parent = root
        item = QtGui.QTreeWidgetItem(parent)
        # item = QtGui.QTreeWidgetItem(self.treeWidget.invisibleRootItem())
        item.setFlags(item.flags() | QtCore.Qt.ItemIsDropEnabled)

        existingLevels = self.treeWidget.topLevelItemCount()
        # level, path = val
        # level = level % existingLevels

        cmdWidget = CommandWidget(self.treeWidget, existingLevels, script)
        self.treeWidget.setItemWidget(item, 0, cmdWidget)

        line_edit_1 = MyLineEdit('1')
        line_edit_2 = MyLineEdit('200')

        self.treeWidget.setItemWidget(item, 1, line_edit_1)
        self.treeWidget.setItemWidget(item, 2, line_edit_2)

        item.setExpanded(True)
        return item

    def _update_css(self):
        self.treeWidget.setStyleSheet(self.cssEditTE.toPlainText())

    def _update_root_decorated(self,state):
        if state == Qt.Checked:
            self.treeWidget.setRootIsDecorated(True)
        else:
            self.treeWidget.setRootIsDecorated(False)
        self.treeWidget.updateGeometries()

    def _alter_indentation(self,value):
        print value
        self.treeWidget.setIndentation(value)
        self.treeWidget.updateGeometries()



if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    gui = TheUI()
    gui.show()
    app.exec_()
Shuman
  • 3,914
  • 8
  • 42
  • 65
  • I think your should use QItemDelegate. If you want to display custom dynamic content or implement a custom editor widget, use QTreeView and subclass QItemDelegate instead. Ref: http://pyqt.sourceforge.net/Docs/PyQt4/qtreewidget.html#setItemWidget – Bandhit Suksiri Aug 13 '14 at 18:18
  • @Kitsune yes i considered using QTreeView at the beginning, but the user requests the 'editors' always visible and interactable, so then i will need to call openPersistentEditor function on the treeview, which is not recommended, and would also need to call it whenever i delete a row or make changes to the model ( or when the view refreshes all the editors are closed.) – Shuman Aug 14 '14 at 00:44
  • Aaaaaaaa, but your can't move item widget with your using 'setItemWidget'. But, QItemDelegate can use paint event to "Dummy" widget. Please read my answer for detail. – Bandhit Suksiri Aug 14 '14 at 08:15

1 Answers1

2

1) How can i make the widget persist after dropping ?

Please use this to understand how to use QItemDelegate (running in Windows 7, Python 2.7, pyqt4):

import sys
import os
from PyQt4 import QtCore, QtGui
from functools import partial

class QCustomDelegate (QtGui.QItemDelegate):
    def createEditor (self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            editorQWidget = QtGui.QPushButton(parentQWidget)
            self.connect(editorQWidget, QtCore.SIGNAL('released()'), partial(self.requestNewPath, indexQModelIndex))
            return editorQWidget            
        elif column in [1, 2]:
            editorQWidget = QtGui.QSpinBox(parentQWidget)
            editorQWidget.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
            editorQWidget.setMinimum(0)
            editorQWidget.setMaximum(2 ** 16)
            return editorQWidget
        else:
            return QtGui.QItemDelegate.createEditor(self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex)

    def setEditorData (self, editorQWidget, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
            editorQWidget.setText(textQString)
        elif column in [1, 2]:
            value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
            editorQWidget.setValue(value)
        else:
            QtGui.QItemDelegate.setEditorData(self, editorQWidget, indexQModelIndex)

    def setModelData (self, editorQWidget, modelQAbstractItemModel, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            textQString = editorQWidget.text()
            modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
        elif column in [1, 2]:
            value = editorQWidget.value()
            modelQAbstractItemModel.setData(indexQModelIndex, value, QtCore.Qt.EditRole)
        else:
            QtGui.QItemDelegate.setModelData(self, editorQWidget, modelQAbstractItemModel, indexQModelIndex)

    def updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column in [0, 1, 2]:
            editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
        else:
            QtGui.QItemDelegate.updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex)

    def requestNewPath (self, indexQModelIndex):
        self.emit(QtCore.SIGNAL('requestNewPath'), indexQModelIndex)

    def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
            foundIndexQModelIndex = indexQModelIndex
            while foundIndexQModelIndex.parent() != QtCore.QModelIndex():
                foundIndexQModelIndex = foundIndexQModelIndex.parent()
            buttonQStyleOptionButton = QtGui.QStyleOptionButton()
            buttonQStyleOptionButton.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
            buttonQStyleOptionButton.text = str(foundIndexQModelIndex.row() + 1) + ' : ' + os.path.basename(str(textQString))
            buttonQStyleOptionButton.state = QtGui.QStyle.State_Active
            QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, buttonQStyleOptionButton, painterQPainter)
        elif column in [1, 2]:
            value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
            textQStyleOptionViewItem = optionQStyleOptionViewItem
            textQStyleOptionViewItem.displayAlignment = QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
            currentQRect = QtCore.QRect(optionQStyleOptionViewItem.rect)
            currentQRect.setWidth(currentQRect.width() - 22)
            self.drawDisplay(painterQPainter, textQStyleOptionViewItem, currentQRect, QtCore.QString(str(value)));
            spinBoxQStyleOptionSpinBox = QtGui.QStyleOptionSpinBox()
            spinBoxQStyleOptionSpinBox.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
            QtGui.QApplication.style().drawComplexControl(QtGui.QStyle.CC_SpinBox, spinBoxQStyleOptionSpinBox, painterQPainter)
        else:
            QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)

class QCustomTreeWidget (QtGui.QTreeWidget):
    def __init__(self, parent = None):
        super(QCustomTreeWidget, self).__init__(parent)
        self.setDragEnabled(True)
        self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.setColumnCount(3)
        self.setHeaderLabels(('script', 'chunksize', 'mem'))
        for i in range(self.columnCount()):
            self.headerItem().setTextAlignment(i, QtCore.Qt.AlignHCenter)
        self.header().setStretchLastSection(False)
        self.header().setResizeMode(0, QtGui.QHeaderView.Stretch)
        self.setIndentation(60)
        self.setColumnWidth(0, 200)
        myQCustomDelegate = QCustomDelegate()
        self.setItemDelegate(myQCustomDelegate)
        self.connect(myQCustomDelegate, QtCore.SIGNAL('requestNewPath'), self.getNewPath)

    def addMenu (self, script = 'echo path_to_script', chunksize = 1, mem = 200, parentQTreeWidgetItem = None):
        if parentQTreeWidgetItem == None:
            parentQTreeWidgetItem = self.invisibleRootItem()
        currentQTreeWidgetItem = QtGui.QTreeWidgetItem(parentQTreeWidgetItem)
        currentQTreeWidgetItem.setData(0, QtCore.Qt.EditRole, script)
        currentQTreeWidgetItem.setData(1, QtCore.Qt.EditRole, chunksize)
        currentQTreeWidgetItem.setData(2, QtCore.Qt.EditRole, mem)
        currentQTreeWidgetItem.setFlags(currentQTreeWidgetItem.flags() | QtCore.Qt.ItemIsEditable)
        for i in range(self.columnCount()):
            currentQSize = currentQTreeWidgetItem.sizeHint(i)
            currentQTreeWidgetItem.setSizeHint(i, QtCore.QSize(currentQSize.width(), currentQSize.height() + 30))
        currentQTreeWidgetItem.setExpanded(True)
        return currentQTreeWidgetItem

    def getNewPath (self, indexQModelIndex):
        currentQTreeWidgetItem = self.itemFromIndex(indexQModelIndex)
        pathQString = QtGui.QFileDialog.getOpenFileName (
            self, 'Select Script file', '', '.py Files (*.py);;Executable Files (*)')
        if not pathQString.isEmpty():
            currentQTreeWidgetItem.setData(indexQModelIndex.column(), QtCore.Qt.EditRole, pathQString)

class QCustomQDialog (QtGui.QDialog):
    def __init__ (self, parent = None):
        super(QCustomQDialog, self).__init__(parent)
        self.myQCustomTreeWidget = QCustomTreeWidget(self)
        self.addQPushButton = QtGui.QPushButton('Add', self)
        self.connect(self.addQPushButton, QtCore.SIGNAL('released()'), self.myQCustomTreeWidget.addMenu)
        self.cssQPlainTextEdit = QtGui.QPlainTextEdit(self)
        self.connect(self.cssQPlainTextEdit, QtCore.SIGNAL('textChanged()'), self.updateCss)
        self.rootDecorationCBQCheckBox = QtGui.QCheckBox('Root is decorated')
        self.connect(self.rootDecorationCBQCheckBox, QtCore.SIGNAL('stateChanged(int)'), self.updateRootDecorated)
        self.updateRootDecorated(self.rootDecorationCBQCheckBox.checkState())
        self.indentationQSlider = QtGui.QSlider(self)
        self.indentationQSlider.setOrientation(QtCore.Qt.Horizontal)
        self.indentationQSlider.setRange(0, 100)
        self.indentationQSlider.setValue(20)
        self.connect(self.indentationQSlider, QtCore.SIGNAL('valueChanged(int)'), self.alterIndentation)
        self.alterIndentation(self.indentationQSlider.value())
        self.layoutQVBoxLayout = QtGui.QVBoxLayout()
        self.layoutQVBoxLayout.addWidget(self.myQCustomTreeWidget)
        self.layoutQVBoxLayout.addWidget(self.addQPushButton)
        self.layoutQVBoxLayout.addWidget(self.cssQPlainTextEdit)
        self.downMenuQHBoxLayout = QtGui.QHBoxLayout()
        self.downMenuQHBoxLayout.addWidget(self.rootDecorationCBQCheckBox)
        self.downMenuQHBoxLayout.addWidget(self.indentationQSlider)
        self.layoutQVBoxLayout.addLayout(self.downMenuQHBoxLayout)
        self.layoutQVBoxLayout.setStretchFactor(self.myQCustomTreeWidget, 1)
        self.setLayout(self.layoutQVBoxLayout)
        self.resize(480, 640)
        _ = self.myQCustomTreeWidget.addMenu()
        _ = self.myQCustomTreeWidget.addMenu()
        currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu()
        self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
        self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
        currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu()
        currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
        currentQTreeWidgetItem = self.myQCustomTreeWidget.addMenu(parentQTreeWidgetItem = currentQTreeWidgetItem)
        _ = self.myQCustomTreeWidget.addMenu()

    def updateCss (self):
        self.myQCustomTreeWidget.setStyleSheet(self.cssQPlainTextEdit.toPlainText())

    def alterIndentation (self, value):
        self.myQCustomTreeWidget.setIndentation(value)
        self.myQCustomTreeWidget.updateGeometries()

    def updateRootDecorated (self, state):
        if state == QtCore.Qt.Checked:
            self.myQCustomTreeWidget.setRootIsDecorated(True)
        else:
            self.myQCustomTreeWidget.setRootIsDecorated(False)
        self.myQCustomTreeWidget.updateGeometries()

app = QtGui.QApplication([])
myQCustomQDialog = QCustomQDialog()
myQCustomQDialog.show()
sys.exit(app.exec_())

You are not the only one who has experienced this problem. I strongly recommend using QItemDelegate.

The document says:

If you want to display custom dynamic content or implement a custom editor widget, use QTreeView and subclass QItemDelegate instead.

And (user ? or) you want 'editors' always visible. It can do it in QItemDelegate. But in class QItemDelegate, implements QItemDelegate.paint (self, QPainter painter, QStyleOptionViewItem option, QModelIndex index) (reference in later). And other property 'createEditor', 'setEditorData', etc.

Example for implementing this class:

import sys
from PyQt4 import QtCore, QtGui
from functools import partial

class QCustomDelegate (QtGui.QItemDelegate):
    def createEditor (self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 1:
            editorQWidget = QtGui.QSpinBox(parentQWidget)
            editorQWidget.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
            editorQWidget.setMinimum(0)
            editorQWidget.setMaximum(100)
            return editorQWidget
        elif column == 2:
            editorQWidget = QtGui.QLineEdit(parentQWidget)
            editorQWidget.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
            return editorQWidget
        elif column == 3:
            editorQWidget = QtGui.QPushButton(parentQWidget)
            return editorQWidget            
        else:
            return QtGui.QItemDelegate.createEditor(self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex)

    def setEditorData (self, editorQWidget, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 1:
            value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
            editorQWidget.setValue(value)
        elif column == 2:
            textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
            editorQWidget.setText(textQString)
        elif column == 3:
            textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
            self.connect(editorQWidget, QtCore.SIGNAL('released()'), partial(self.requestNewPath, indexQModelIndex))
            editorQWidget.setText(textQString)
        else:
            QtGui.QItemDelegate.setEditorData(self, editorQWidget, indexQModelIndex)

    def setModelData (self, editorQWidget, modelQAbstractItemModel, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 1:
            value = editorQWidget.value()
            modelQAbstractItemModel.setData(indexQModelIndex, value, QtCore.Qt.EditRole)
        elif column == 2:
            textQString = editorQWidget.text()
            modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
        elif column == 3:
            textQString = editorQWidget.text()
            modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
        else:
            QtGui.QItemDelegate.setModelData(self, editorQWidget, modelQAbstractItemModel, indexQModelIndex)

    def updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 1:
            editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
        elif column == 2:
            editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
        elif column == 3:
            editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
        else:
            QtGui.QItemDelegate.updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex)

    def requestNewPath (self, indexQModelIndex):
        self.emit(QtCore.SIGNAL('requestNewPath'), indexQModelIndex)

    def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 1:
            value, _ = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toInt()
            textQStyleOptionViewItem = optionQStyleOptionViewItem
            textQStyleOptionViewItem.displayAlignment = QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
            currentQRect = QtCore.QRect(optionQStyleOptionViewItem.rect)
            currentQRect.setWidth(currentQRect.width() - 22)
            self.drawDisplay(painterQPainter, textQStyleOptionViewItem, currentQRect, QtCore.QString(str(value)));
            spinBoxQStyleOptionSpinBox = QtGui.QStyleOptionSpinBox()
            spinBoxQStyleOptionSpinBox.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
            QtGui.QApplication.style().drawComplexControl(QtGui.QStyle.CC_SpinBox, spinBoxQStyleOptionSpinBox, painterQPainter)
        elif column == 2:
            textQStyleOptionViewItem = optionQStyleOptionViewItem
            textQStyleOptionViewItem.displayAlignment = QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
            QtGui.QItemDelegate.paint(self, painterQPainter, textQStyleOptionViewItem, indexQModelIndex)
        elif column == 3:
            textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
            buttonQStyleOptionButton = QtGui.QStyleOptionButton()
            buttonQStyleOptionButton.rect = QtCore.QRect(optionQStyleOptionViewItem.rect)
            buttonQStyleOptionButton.text = textQString
            buttonQStyleOptionButton.state = QtGui.QStyle.State_Active
            QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, buttonQStyleOptionButton, painterQPainter)
        else:
            QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)

class QCustomTreeWidget (QtGui.QTreeWidget):
    def __init__(self, parent = None):
        super(QCustomTreeWidget, self).__init__(parent)
        self.setDragEnabled(True)
        self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.setColumnCount(4)
        myQCustomDelegate = QCustomDelegate()
        self.setItemDelegate(myQCustomDelegate)
        self.connect(myQCustomDelegate, QtCore.SIGNAL('requestNewPath'), self.getNewPath)

    def addMenu (self, title, value, text, path, parentQTreeWidgetItem = None):
        if parentQTreeWidgetItem == None:
            parentQTreeWidgetItem = self.invisibleRootItem()
        currentQTreeWidgetItem = QtGui.QTreeWidgetItem(parentQTreeWidgetItem)
        currentQTreeWidgetItem.setData(0, QtCore.Qt.EditRole, title)
        currentQTreeWidgetItem.setData(1, QtCore.Qt.EditRole, value)
        currentQTreeWidgetItem.setData(2, QtCore.Qt.EditRole, text)
        currentQTreeWidgetItem.setData(3, QtCore.Qt.EditRole, path)
        currentQTreeWidgetItem.setFlags(currentQTreeWidgetItem.flags() | QtCore.Qt.ItemIsEditable)
        for i in range(self.columnCount()):
            currentQSize = currentQTreeWidgetItem.sizeHint(i)
            currentQTreeWidgetItem.setSizeHint(i, QtCore.QSize(currentQSize.width(), currentQSize.height() + 40))

    def getNewPath (self, indexQModelIndex):
        currentQTreeWidgetItem = self.itemFromIndex(indexQModelIndex)
        pathQStringList = QtGui.QFileDialog.getOpenFileNames()
        if pathQStringList.count() > 0:
            textQString = pathQStringList.first()
            currentQTreeWidgetItem.setData(indexQModelIndex.column(), QtCore.Qt.EditRole, textQString)

class QCustomQWidget (QtGui.QWidget):
    def __init__ (self, parent = None):
        super(QCustomQWidget, self).__init__(parent)
        self.myQCustomTreeWidget = QCustomTreeWidget(self)
        self.allQHBoxLayout = QtGui.QHBoxLayout()
        self.allQHBoxLayout.addWidget(self.myQCustomTreeWidget)
        self.setLayout(self.allQHBoxLayout)
        self.myQCustomTreeWidget.addMenu('1', 10, 'A', 'home/Meyoko/Desktop')
        self.myQCustomTreeWidget.addMenu('4', 14, 'B', 'home/Kitsune/Desktop')
        self.myQCustomTreeWidget.addMenu('7', 17, 'C', 'home/Elbert/Desktop')

app = QtGui.QApplication([])
myQCustomQWidget = QCustomQWidget()
myQCustomQWidget.show()
sys.exit(app.exec_())

Spin Box Delegate Example (C++)

QItemDelegate

Jamal
  • 763
  • 7
  • 22
  • 32
Bandhit Suksiri
  • 3,390
  • 1
  • 18
  • 20