繁体   English   中英

PyQt:如何在dropEvent上获取QListWidget的listItem .data()

[英]PyQt: How to get QListWidget's listItem .data() on dropEvent

有两个QListWidgets。 使用setData(QtCore.Qt.UserRole, myClassInstA)为每个列表项分配MyClass()的实例。

单击较低的QListWidget的listItem将打印出使用以下方法检索的单击的listItem数据:

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

从顶部QListWidget拖放到底部的任何itemA均显示None。 有趣的是,单击同一项目会打印出一个数据。 我想知道是否有可能在dropOnB()函数中检索存储在listItem中的数据(因此dropOnB()能够打印出存储在项目中的数据)。


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

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

将itemA放到目标listWidgetB上时,iteA到达时未存储任何数据。 如果尝试使用itemA.data(QtCore.Qt.UserRole).toPyObject()检索它,则返回None(如果在dropOnB()内完成-一个方法触发第一个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_())

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM