【问题标题】:pyqt QTreeWidget setItemWidget dissapears after drag/droppyqt QTreeWidget setItemWidget在拖放后消失
【发布时间】:2010-03-04 22:30:55
【问题描述】:

我正在尝试使用 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_ ()

【问题讨论】:

    标签: python user-interface qt pyqt qtreewidget


    【解决方案1】:

    通过编写我自己的 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_ ()
    

    【讨论】:

      【解决方案2】:

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

      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_ ()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-15
        • 2021-08-07
        • 2014-01-04
        • 1970-01-01
        • 2017-05-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多