2014-04-11 20 views
0

有两个QListWidgets。每个列表项都使用setData(QtCore.Qt.UserRole, myClassInstA)分配给MyClass()的实例。PyQt的:如何获得QListWidget的的listItem。数据()上dropEvent

点击低级QListWidget的的listItem打印出使用检索到的点击的listItem的数据:

.data(QtCore.Qt.UserRole).toPyObject() 

在任何意达拖动并从顶部QListWidget滴到下部示出无数据。 有趣的是,点击相同的项目打印有一个数据。我想知道是否有可能在droppedOnB()函数中检索存储在listItem中的数据(因此droppedOnB()能够打印出存储在项目中的数据)。


from PyQt4 import QtGui, QtCore 
import sys, os 

class MyClass(object): 
     def __init__(self): 
      super(MyClass, self).__init__()    

class ThumbListWidget(QtGui.QListWidget): 
    _drag_info = [] 
    def __init__(self, type, name, parent=None): 
     super(ThumbListWidget, self).__init__(parent) 
     self.setObjectName(name) 
     self.setIconSize(QtCore.QSize(124, 124)) 
     self.setDragDropMode(QtGui.QAbstractItemView.DragDrop) 
     self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) 
     self.setAcceptDrops(True) 
     self._dropping = False 

    def startDrag(self, actions): 
     self._drag_info[:] = [str(self.objectName())] 
     for item in self.selectedItems(): 
      self._drag_info.append(self.row(item)) 
     super(ThumbListWidget, self).startDrag(actions) 

    def dragEnterEvent(self, event): 
     if event.mimeData().hasUrls(): 
      event.accept() 
     else: 
      super(ThumbListWidget, self).dragEnterEvent(event) 

    def dragMoveEvent(self, event): 
     if event.mimeData().hasUrls(): 
      event.setDropAction(QtCore.Qt.CopyAction) 
      event.accept() 
     else: 
      super(ThumbListWidget, self).dragMoveEvent(event) 

    def dropEvent(self, event): 
     if event.mimeData().hasUrls(): 
      event.setDropAction(QtCore.Qt.CopyAction) 
      event.accept() 
      links = [] 
      for url in event.mimeData().urls(): 
       links.append(str(url.toLocalFile())) 
      self.emit(QtCore.SIGNAL("dropped"), links) 
     else: 
      # event.setDropAction(QtCore.Qt.MoveAction) 
      self._dropping = True 
      super(ThumbListWidget, self).dropEvent(event) 
      self._dropping = False 

    def rowsInserted(self, parent, start, end): 
     if self._dropping: 
      self._drag_info.append((start, end)) 
      self.emit(QtCore.SIGNAL("dropped"), self._drag_info) 
     super(ThumbListWidget, self).rowsInserted(parent, start, end) 


class Dialog_01(QtGui.QMainWindow): 
    def __init__(self): 
     super(QtGui.QMainWindow,self).__init__() 
     self.listItems={} 

     myQWidget = QtGui.QWidget() 
     myBoxLayout = QtGui.QVBoxLayout() 
     myQWidget.setLayout(myBoxLayout) 
     self.setCentralWidget(myQWidget) 

     self.listWidgetA = ThumbListWidget(self, 'MainTree') 
     self.listWidgetB = ThumbListWidget(self, 'SecondaryTree') 
     self.listWidgetB.setDragDropMode(QtGui.QAbstractItemView.DropOnly) 

     for i in range(7): 
      listItemA=QtGui.QListWidgetItem() 
      listItemA.setText('A'+'%04d'%i) 
      self.listWidgetA.addItem(listItemA) 

      myClassInstA=MyClass() 
      listItemA.setData(QtCore.Qt.UserRole, myClassInstA) 

      listItemB=QtGui.QListWidgetItem() 
      listItemB.setText('B'+'%04d'%i) 
      self.listWidgetB.addItem(listItemB) 

      myClassInstB=MyClass() 
      listItemB.setData(QtCore.Qt.UserRole, myClassInstB) 

     myBoxLayout.addWidget(self.listWidgetA)  

     myBoxLayout.addWidget(self.listWidgetB) 
     self.connect(self.listWidgetB, QtCore.SIGNAL("dropped"), self.droppedOnB) 
     self.listWidgetB.clicked.connect(self.itemClicked) 


    def droppedOnB(self, dropped_list): 
     print '\n\t droppedOnB()', dropped_list, dropped_list[-1] 

     destIndexes=dropped_list[-1] 
     for index in range(destIndexes[0],destIndexes[-1]+1): 
      dropedItem=self.listWidgetB.item(index) 
      modelIndex=self.listWidgetB.indexFromItem(dropedItem) 
      dataObject = modelIndex.data(QtCore.Qt.UserRole).toPyObject() 
      print '\n\t\t droppedOnB()', type(modelIndex), type(dataObject) 

    def itemClicked(self, modelIndex):  
     dataObject = modelIndex.data(QtCore.Qt.UserRole).toPyObject() 
     print 'itemClicked(): ' ,type(modelIndex), type(dataObject) 


if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    dialog_1 = Dialog_01() 
    dialog_1.show() 
    dialog_1.resize(720,480) 
    sys.exit(app.exec_()) 

回答

0

的最终目标是与MyClassB取代MyClassA的实例数据 -object(连接到意达)意达滴到listWidgetB之后。

当itemA被放到目的地listWidgetB时,itemA到达时没有存储数据。如果尝试使用itemA.data(QtCore.Qt.UserRole).toPyObject()检索它,则返回None(如果在droppedOnB()内执行 - 首先触发onDrop事件的方法)。

试图分配,重新分配一个数据,只是丢弃listItem ...甚至删除它会导致所有类型的惊喜后。我正在使用.setHidden(True)。

这些步骤如下:

  1. 获取源的listItem及其数据。
  2. 获取目的地(放下)项目并隐藏它。
  3. 声明MyClassB()实例
  4. 创建新的列表项。使用.setData(QtCore.Qt.UserRole,myClassInstB)将上一步创建的MyClassB()实例对象创建为listItem
  5. 将新的listItem添加到ListWidget。

这里是一个功能代码。 itemA再一次在创建时分配ClassA的一个实例。 将itemA拖放到listWidgetB后,被放置的项目被隐藏,并被分配了classB实例的另一个项目“替换”。

from PyQt4 import QtGui, QtCore 
import sys, os, copy 

class MyClassA(object): 
     def __init__(self): 
      super(MyClassA, self).__init__()    

class MyClassB(object): 
     def __init__(self): 
      super(MyClassB, self).__init__() 
      self.DataObjectCopy=None 

class ThumbListWidget(QtGui.QListWidget): 
    _drag_info = [] 
    def __init__(self, type, name, parent=None): 
     super(ThumbListWidget, self).__init__(parent) 
     self.setObjectName(name) 
     self.setIconSize(QtCore.QSize(124, 124)) 
     self.setDragDropMode(QtGui.QAbstractItemView.DragDrop) 
     self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) 
     self.setAcceptDrops(True) 
     self._dropping = False 

    def startDrag(self, actions): 
     self._drag_info[:] = [str(self.objectName())] 
     for item in self.selectedItems(): 
      self._drag_info.append(self.row(item)) 
     super(ThumbListWidget, self).startDrag(actions) 

    def dragEnterEvent(self, event): 
     if event.mimeData().hasUrls(): 
      event.accept() 
     else: 
      super(ThumbListWidget, self).dragEnterEvent(event) 

    def dragMoveEvent(self, event): 
     if event.mimeData().hasUrls(): 
      event.setDropAction(QtCore.Qt.CopyAction) 
      event.accept() 
     else: 
      super(ThumbListWidget, self).dragMoveEvent(event) 

    def dropEvent(self, event): 
     if event.mimeData().hasUrls(): 
      event.setDropAction(QtCore.Qt.CopyAction) 
      event.accept() 
      links = [] 
      for url in event.mimeData().urls(): 
       links.append(str(url.toLocalFile())) 
      self.emit(QtCore.SIGNAL("dropped"), links) 
     else: 
      # event.setDropAction(QtCore.Qt.MoveAction) 
      self._dropping = True 
      super(ThumbListWidget, self).dropEvent(event) 
      self._dropping = False 

    def rowsInserted(self, parent, start, end): 
     if self._dropping: 
      self._drag_info.append((start, end)) 
      self.emit(QtCore.SIGNAL("dropped"), self._drag_info) 
     super(ThumbListWidget, self).rowsInserted(parent, start, end) 


class Dialog_01(QtGui.QMainWindow): 
    def __init__(self): 
     super(QtGui.QMainWindow,self).__init__() 
     self.listItems={} 

     myQWidget = QtGui.QWidget() 
     myBoxLayout = QtGui.QVBoxLayout() 
     myQWidget.setLayout(myBoxLayout) 
     self.setCentralWidget(myQWidget) 

     self.listWidgetA = ThumbListWidget(self, 'MainTree') 
     self.listWidgetB = ThumbListWidget(self, 'SecondaryTree') 
     self.listWidgetB.setDragDropMode(QtGui.QAbstractItemView.DropOnly) 

     for i in range(3): 
      listItemA=QtGui.QListWidgetItem() 
      listItemA.setText('A'+'%04d'%i) 
      self.listWidgetA.addItem(listItemA) 

      myClassInstA=MyClassA() 
      listItemA.setData(QtCore.Qt.UserRole, myClassInstA) 

      listItemB=QtGui.QListWidgetItem() 
      listItemB.setText('B'+'%04d'%i) 
      self.listWidgetB.addItem(listItemB) 

      myClassInstB=MyClassB() 
      listItemB.setData(QtCore.Qt.UserRole, myClassInstB) 

     myBoxLayout.addWidget(self.listWidgetA)  

     myBoxLayout.addWidget(self.listWidgetB) 
     self.connect(self.listWidgetB, QtCore.SIGNAL("dropped"), self.droppedOnB) 
     self.listWidgetB.clicked.connect(self.itemClicked) 


    def droppedOnB(self, dropped_list): 
     if not dropped_list or len(dropped_list)<3: return  

     srcIndexes=dropped_list[1:-1] 
     destIndexes=dropped_list[-1] 

     # build a list of corresponding src-to-dest indexes sets 
     itemsIndxes=[] 
     i=0 
     for num in range(destIndexes[0], destIndexes[-1]+1): 
      itemsIndxes.append((srcIndexes[i], num)) 
      i+=1 

     print '\n\t droppedOnB(): dropped_list =',dropped_list,'; srcIndexes =',srcIndexes,'; destIndexes =',destIndexes, '; itemsIndxes =',itemsIndxes 

     for indexSet in itemsIndxes: 
      srcNum = indexSet[0] 
      destIndxNum = indexSet[-1] 

      # Get source listItem's data object 
      srcItem=self.listWidgetA.item(srcNum) 
      if not srcItem: continue 
      srcItemData = srcItem.data(QtCore.Qt.UserRole) 
      if not srcItemData: continue 
      srcItemDataObject=srcItemData.toPyObject() 
      if not srcItemDataObject: continue 
      # make a deepcopy of src data object 
      itemDataObject_copy=copy.deepcopy(srcItemDataObject) 

      # get dropped item 
      droppedItem=self.listWidgetB.item(destIndxNum) 
      # hide dropped item since removing it results to mess 
      droppedItem.setHidden(True) 
      # declare new ClassB instance 
      myClassInstB=MyClassB() 
      myClassInstB.DataObjectCopy=itemDataObject_copy 

      # create a new listItem 
      newListItem=QtGui.QListWidgetItem() 
      newListItem.setData(QtCore.Qt.UserRole, myClassInstB) 
      newListItem.setText(srcItem.text()) 
      self.listWidgetB.blockSignals(True) 
      self.listWidgetB.addItem(newListItem) 
      self.listWidgetB.blockSignals(False) 


    def itemClicked(self, modelIndex):  
     dataObject = modelIndex.data(QtCore.Qt.UserRole).toPyObject() 
     print 'itemClicked(): instance type:', type(dataObject) 


if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    dialog_1 = Dialog_01() 
    dialog_1.show() 
    dialog_1.resize(720,480) 
    sys.exit(app.exec_())