Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从一个QListWidget拖放到另一个_Python_Pyqt4_Qlistwidget - Fatal编程技术网

Python 如何从一个QListWidget拖放到另一个

Python 如何从一个QListWidget拖放到另一个,python,pyqt4,qlistwidget,Python,Pyqt4,Qlistwidget,在同一个对话框窗口中有两个QListWidget。这两个系统都启用了DragDrop功能。如果我将一个文件拖放到两个ListWidges中的任何一个,程序会识别它并打印出所拖放文件的列表。但是除了拖放文件之外,我希望能够将列表小部件项从一个拖放到另一个。如果我拖动ListItems,则会触发拖放事件。但它无法识别哪些项目被丢到了小部件上。下面是示例代码。目标是将列表项从一个ListWidget拖放到另一个ListWidget import sys, os from PyQt4 import Qt

在同一个对话框窗口中有两个QListWidget。这两个系统都启用了DragDrop功能。如果我将一个文件拖放到两个ListWidges中的任何一个,程序会识别它并打印出所拖放文件的列表。但是除了拖放文件之外,我希望能够将列表小部件项从一个拖放到另一个。如果我拖动ListItems,则会触发拖放事件。但它无法识别哪些项目被丢到了小部件上。下面是示例代码。目标是将列表项从一个ListWidget拖放到另一个ListWidget

import sys, os
from PyQt4 import QtCore, QtGui   
class ThumbListWidget(QtGui.QListWidget):
    def __init__(self, type, parent=None):
        super(ThumbListWidget, self).__init__(parent)
        self.setAcceptDrops(True)
        self.setIconSize(QtCore.QSize(124, 124))

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

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

    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.ignore()


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)
        for i in range(12): 
            QtGui.QListWidgetItem( 'Item '+str(i), self.listWidgetA )
        myBoxLayout.addWidget(self.listWidgetA)

        self.listWidgetB = ThumbListWidget(self)
        myBoxLayout.addWidget(self.listWidgetB)   

        self.listWidgetA.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.listWidgetA.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.connect(self.listWidgetA, QtCore.SIGNAL("dropped"), self.items_dropped)
        self.listWidgetA.currentItemChanged.connect(self.item_clicked)

        self.listWidgetB.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.listWidgetB.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.connect(self.listWidgetB, QtCore.SIGNAL("dropped"), self.items_dropped)
        self.listWidgetB.currentItemChanged.connect(self.item_clicked)

    def items_dropped(self, arg):
        print arg

    def item_clicked(self, arg):
        print arg

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dialog_1 = Dialog_01()
    dialog_1.show()
    dialog_1.resize(480,320)
    sys.exit(app.exec_())
编辑#2 下面是完成这一切的代码。但没有办法追查掉了什么东西。droppedOnA()和droppedOnB()方法仍然不起作用


编辑#3 这是这次使用MIME将被删除项的对象传递给ListWidget的另一次尝试。不幸的是,cPickle拒绝接受抛出

TypeError:无法实例化或子分类sip.wrapper类型

为了解决这个问题,我将每个对象名转换为字符串,并将其与self.listItems={}dictionary一起用作检索列表项二进制对象的键。看起来效果不错。但在最后,当我几乎认为一切都已完成时,没有可见错误的ListWidget不会将删除的列表项添加到自身中。。。真奇怪

self.listWidgetB.addItem(droppedItemInstance)


假设您想要移动列表小部件项,您的子类应该如下所示(请注意,
setDragDropMode
setSelectionMode
已被移动到
\uuu init\uuuu
):


这是一个修改后的代码。它工作起来很有魅力!好极了

from PyQt4 import QtGui, QtCore
import sys, os

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

    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):
        print 'dropEvent', 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)
            super(ThumbListWidget, self).dropEvent(event)


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)
        for i in range(12): 
            QtGui.QListWidgetItem( 'Item '+str(i), self.listWidgetA )
        myBoxLayout.addWidget(self.listWidgetA)

        self.listWidgetB = ThumbListWidget(self)
        myBoxLayout.addWidget(self.listWidgetB)   

        self.connect(self.listWidgetA, QtCore.SIGNAL("dropped"), self.items_dropped)
        self.listWidgetA.currentItemChanged.connect(self.item_clicked)

        self.connect(self.listWidgetB, QtCore.SIGNAL("dropped"), self.items_dropped)
        self.listWidgetB.currentItemChanged.connect(self.item_clicked)

    def items_dropped(self, arg):
        print 'items_dropped', arg

    def item_clicked(self, arg):
        print arg

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

在实现Python 3风格的
super()
时,上面的代码对我来说不起作用

问题是继承的方法
dragmovevent
dragDropEvent
没有被子类中的新定义覆盖

因此,未调用
event.setDropAction(QtCore.Qt.MoveAction)
,小部件行为默认为
QtCore.Qt.CopyAction

我使用继承自
qabstractemview
类的
setDefaultDropAction()
方法解决了这个问题

以下是PyQt5和Python 3.7中的实现:

class NewDragDropWidget(QListWidget):

    def __init__(self):
        super().__init__()
        self.setIconSize(QtCore.QSize(124, 124))
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setDefaultDropAction(QtCore.Qt.MoveAction) # this was the magic line
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setAcceptDrops(True)

让我试试!谢谢很好!谢谢你!显然,奇迹发生了,因为有以下几行:event.setDropAction(QtCore.Qt.MoveAction)和super(ThumbListWidget,self)。dropEvent(event)我用注释掉的这些行运行代码。如果删除这些行,将取消删除操作以及对listWidget的项目分配。然而,我不能理解它的语法。如果您能澄清那里发生了什么,我将不胜感激……第一行确保项目被移动,而不是复制(这是错误)。第二行调用
dropEvent
的基类实现。一个
QListWidget
已经知道如何复制/移动它的项目,所以我们就让它做它自己的事情…PS:如果你注释掉所有的拖放方法,并转到
MoveAction
,你将以同样的行为结束。只是因为您出于其他原因重写了这些方法,才需要这些额外的行。
class ThumbListWidget(QtGui.QListWidget):
    def __init__(self, type, parent=None):
        super(ThumbListWidget, self).__init__(parent)
        self.setIconSize(QtCore.QSize(124, 124))
        self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.setAcceptDrops(True)

    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)
            super(ThumbListWidget, self).dropEvent(event)
from PyQt4 import QtGui, QtCore
import sys, os

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

    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):
        print 'dropEvent', 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)
            super(ThumbListWidget, self).dropEvent(event)


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)
        for i in range(12): 
            QtGui.QListWidgetItem( 'Item '+str(i), self.listWidgetA )
        myBoxLayout.addWidget(self.listWidgetA)

        self.listWidgetB = ThumbListWidget(self)
        myBoxLayout.addWidget(self.listWidgetB)   

        self.connect(self.listWidgetA, QtCore.SIGNAL("dropped"), self.items_dropped)
        self.listWidgetA.currentItemChanged.connect(self.item_clicked)

        self.connect(self.listWidgetB, QtCore.SIGNAL("dropped"), self.items_dropped)
        self.listWidgetB.currentItemChanged.connect(self.item_clicked)

    def items_dropped(self, arg):
        print 'items_dropped', arg

    def item_clicked(self, arg):
        print arg

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

    def __init__(self):
        super().__init__()
        self.setIconSize(QtCore.QSize(124, 124))
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setDefaultDropAction(QtCore.Qt.MoveAction) # this was the magic line
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setAcceptDrops(True)