pyqt QTreeWidget setItemWidget在拖放后消失

时间:2010-03-04 22:30:56

标签: python user-interface qt pyqt qtreewidget

我正在尝试使用QTreeWidget.setItemWidget()

在重新显示(拖放)之后将小部件放入QTreeWidgetItem中

但是,如果编译以下代码,结果是QTreeWidgetItem内的窗口小部件消失了。 知道为什么吗?什么代码可以解决这个问题(我想用小部件重新填充QTreeWidgetItem?)

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


class InlineEditor (QWidget):
    _MUTE = 'MUTE'

    def __init__ (self, parent):
        QWidget.__init__ (self, parent)

        self.setAutoFillBackground (True)
        lo = QHBoxLayout()
        lo.setSpacing(4)

        self._cbFoo = QComboBox()
        for x in ["ABC", "DEF", "GHI", "JKL"]:
            self._cbFoo.addItem(x)

        self._leBar = QLineEdit('', self)
        lo.addWidget (self._cbFoo, 3)
        lo.addSpacing (5)
        lo.addWidget (QLabel ( 'Bar:'))
        lo.addWidget (self._leBar, 3)
        lo.addStretch (5)
        self.setLayout (lo)

class Form (QDialog):
    def __init__(self,parent=None):
        QDialog.__init__(self, parent)

        grid = QGridLayout ()
        tree = QTreeWidget ()

        # Here is the issue?
        tree.setDragDropMode(QAbstractItemView.InternalMove)

        tree.setColumnCount(3)

        for n in range (2):
            i = QTreeWidgetItem (tree) # create QTreeWidget the sub i
            i.setText (0, "first" + str (n)) # set the text of the first 0
            i.setText (1, "second")
            for m in range (2):
                j = QTreeWidgetItem(i)
                j.setText (0, "child first" + str (m))

        #b1 = QCheckBox("push me 0", tree) # this wont work w/ drag by itself either
        #tree.setItemWidget (tree.topLevelItem(0).child(1), 1, b1)

        item = InlineEditor(tree) # deal with a combination of multiple controls
        tree.setItemWidget(tree.topLevelItem(0).child(1), 1, item)

        grid.addWidget (tree)
        self.setLayout (grid)

app = QApplication ([])
form = Form ()
form.show ()
app.exec_ ()

2 个答案:

答案 0 :(得分:2)

设法通过编写我自己的treeDropEvent来获得相对“工作”的修复...但是如果有人有更优雅的解决方案,请随时分享。下面的代码将解决其他任何人在树中使用setItemWidgets进行拖放操作的麻烦,欢呼。

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

class InlineEditor (QWidget):
    _MUTE = 'MUTE'

    def __init__ (self, parent):
        QWidget.__init__ (self, parent)

        self.setAutoFillBackground (True)
        lo = QHBoxLayout()
        lo.setSpacing(4)

        self._cbFoo = QComboBox()
        for x in ["ABC", "DEF", "GHI", "JKL"]:
            self._cbFoo.addItem(x)

        self._leBar = QLineEdit('', self)
        lo.addWidget (self._cbFoo, 3)
        lo.addSpacing (5)
        lo.addWidget (QLabel ( 'Bar:'))
        lo.addWidget (self._leBar, 3)
        lo.addStretch (5)
        self.setLayout (lo)

class Tree(QTreeWidget):
    def __init__(self, parent=None):
        QTreeWidget.__init__(self, parent)

        # Here is the issue?
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.installEventFilter(self)
        self.setColumnCount(3)
        self.dropEvent = self.treeDropEvent

        for n in range (2):
            i = QTreeWidgetItem (self) # create QTreeWidget the sub i
            i.setText (0, "first" + str (n)) # set the text of the first 0
            i.setText (1, "second")
            for m in range (2):
                j = QTreeWidgetItem(i)
                j.setText (0, "child first" + str (m))

        self.item = InlineEditor(self) # deal with a combination of multiple controls
        self.setItemWidget(self.topLevelItem(0).child(1), 1, self.item)

    def treeDropEvent(self, event):
        dragItem = self.currentItem()

        QTreeWidget.dropEvent(self, event)
        # rebuild widget (grabbing it doesnt seem to work from self.itemWidget?)
        self.item = InlineEditor(self) 
        self.setItemWidget(dragItem, 1, self.item)

class Form (QDialog):
    def __init__(self,parent=None):
        QDialog.__init__(self, parent)
    grid = QGridLayout ()
    tree = Tree ()
    grid.addWidget (tree)
    self.setLayout (grid)

app = QApplication ([])
form = Form ()
form.show ()
app.exec_ ()

答案 1 :(得分:0)

我很想知道为什么,它也发生在我身上。

对于itemWidget,似乎“基础C / C ++对象已被删除”。无论如何,当我在小部件消失后再次尝试setItemWidget()时,我会得到什么,希望能解决它。

我放入了一个事件,当QTreeWidgetItem被删除时被调用但是它似乎一旦被删除就被删除

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


class InlineEditor (QWidget):
    _MUTE = 'MUTE'

    def __init__ (self, parent):
        QWidget.__init__ (self, parent)

        self.setAutoFillBackground (True)
        lo = QHBoxLayout()
        lo.setSpacing(4)

        self._cbFoo = QComboBox()
        for x in ["ABC", "DEF", "GHI", "JKL"]:
            self._cbFoo.addItem(x)

        self._leBar = QLineEdit('', self)
        lo.addWidget (self._cbFoo, 3)
        lo.addSpacing (5)
        lo.addWidget (QLabel ( 'Bar:'))
        lo.addWidget (self._leBar, 3)
        lo.addStretch (5)
        self.setLayout (lo)

class Tree(QTreeWidget):
    def __init__(self, parent=None):
        QTreeWidget.__init__(self, parent)

        # Here is the issue?
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.installEventFilter(self)
        self.setColumnCount(3)

        for n in range (2):
            i = QTreeWidgetItem (self) # create QTreeWidget the sub i
            i.setText (0, "first" + str (n)) # set the text of the first 0
            i.setText (1, "second")
            for m in range (2):
                j = QTreeWidgetItem(i)
                j.setText (0, "child first" + str (m))

        #b1 = QCheckBox("push me 0", tree) # this wont work w/ drag by itself either
        #tree.setItemWidget (tree.topLevelItem(0).child(1), 1, b1)

        self.item = InlineEditor(self) # deal with a combination of multiple controls
        self.setItemWidget(self.topLevelItem(0).child(1), 1, self.item)

    def eventFilter(self, sender, event):
        if event.type() == QEvent.ChildRemoved:
            print self.item._cbFoo # looks like this remains
            print self.item._cbFoo.currentText() # CRASH! but the data is gone 
            #self.setItemWidget(self.topLevelItem(0).child(1), 1, self.item)
        return False


class Form (QDialog):
    def __init__(self,parent=None):
        QDialog.__init__(self, parent)

        grid = QGridLayout ()
        tree = Tree ()

        grid.addWidget (tree)
        self.setLayout (grid)

app = QApplication ([])
form = Form ()
form.show ()
app.exec_ ()