拖放子类 QListWidgetItem [英] Drag and Drop of subclassed QListWidgetItem

查看:46
本文介绍了拖放子类 QListWidgetItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试为自定义 QListWidgetItem 实现拖放时遇到了一些问题.下面是一些示例代码:

from PyQt4 import QtGui, QtCore导入系统,操作系统类 MyListWidgetItem(QtGui.QListWidgetItem):def __init__(self, label, data, parent=None):super(QtGui.QListWidgetItem, self).__init__(label, parent=parent)self.data = 数据def GetData(self):返回 self.data类 MyListWidget(QtGui.QListWidget):def __init__(self, type, parent=None):super(MyListWidget, self).__init__(parent)self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)self.setAcceptDrops(True)self.viewport().setAcceptDrops(True)self.setDropIndicatorShown(True)def startDrag(self, supportedActions):拖动 = QtGui.QDrag(self)t = [i.GetData() for i in self.selectedItems()]mimeData = self.model().mimeData(self.selectedIndexes())mimeData.setText(str(t))drag.setMimeData(mimeData)如果drag.start(QtCore.Qt.MoveAction) == QtCore.Qt.MoveAction:对于 self.selectedItems() 中的项目:self.takeItem(self.row(item))def dragEnterEvent(self, event):如果 event.mimeData().hasUrls():事件.忽略()别的:事件.接受()def dragMoveEvent(self, event):如果 event.mimeData().hasUrls():事件.忽略()别的:事件.接受()def dropEvent(self, event):如果 event.mimeData().hasUrls():事件.忽略()if isinstance(event.source(), MyListWidget):event.setDropAction(QtCore.Qt.MoveAction)super(MyListWidget, self).dropEvent(event)别的:事件.忽略()def dropMimeData(self, index, mimedata, action):super(MyListWidget, self).dropMimeData(index, mimedata, action)返回真类测试(QtGui.QMainWindow):def __init__(self):super(QtGui.QMainWindow,self).__init__()myQWidget = QtGui.QWidget()myBoxLayout = QtGui.QVBoxLayout()myQWidget.setLayout(myBoxLayout)self.setCentralWidget(myQWidget)self.listWidgetA = MyListWidget(self)self.listWidgetB = MyListWidget(self)对于范围内的 i(5):listItemAInstance = MyListWidgetItem(str(i), i, parent=self.listWidgetA)myBoxLayout.addWidget(self.listWidgetA)myBoxLayout.addWidget(self.listWidgetB)如果 __name__ == '__main__':app = QtGui.QApplication(sys.argv)dialog_1 = 测试()dialog_1.show()dialog_1.resize(480,320)sys.exit(app.exec_())

我的自定义类 MyListWidgetItem 有一个数据"字段,它在我的实际程序中保存了一些与项目相关的信息.如果您运行代码并尝试将项目从顶部列表拖放到底部,一切正常,但是如果您随后尝试将它们带回顶部列表,则会出现此错误:

回溯(最近一次调用最后一次):文件C:\Users\Massi\Desktop\t.py",第 23 行,在 startDragt = [i.GetData() for i in self.selectedItems()]AttributeError: 'QListWidgetItem' 对象没有属性 'GetData'

很明显默认拖放行为忽略了列表项已被子类化,所以我想知道哪种情况最适合处理这种情况.任何帮助都非常感谢.提前致谢!

解决方案

如果你添加一些如下的调试信息,你会发现i"已经是 MyListWidgetItem,所以这应该不是问题.

>

 def startDrag(self, supportedActions):拖动 = QtGui.QDrag(self)# 添加以下2行调试信息对于 self.selectedItems() 中的项目:打印 item.__class__.__name__t = [i.GetData() for i in self.selectedItems() if hasattr(i, "GetData")]mimeData = self.model().mimeData(self.selectedIndexes())mimeData.setText(str(t))drag.setMimeData(mimeData)如果drag.start(QtCore.Qt.MoveAction) == QtCore.Qt.MoveAction:对于 self.selectedItems() 中的项目:self.takeItem(self.row(item))

输出是

MyListWidgetItem

问题是你不能将项目类型转换为MyListWidgetItem,因为python不支持类型转换,所以你需要使用反射机制来调用GetData()方法,我刚刚试过代码,它有效很好!

I'm encountering some poblems trying to implement drag and drop for a custom QListWidgetItem. Here is some example code:

from PyQt4 import QtGui, QtCore
import sys, os


class MyListWidgetItem(QtGui.QListWidgetItem):      
    def __init__(self, label, data, parent=None):
        super(QtGui.QListWidgetItem, self).__init__(label, parent=parent)
        self.data = data

    def GetData(self):
        return self.data

class MyListWidget(QtGui.QListWidget):
    def __init__(self, type, parent=None):
        super(MyListWidget, self).__init__(parent)
        self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.setAcceptDrops(True)
        self.viewport().setAcceptDrops(True)
        self.setDropIndicatorShown(True)

    def startDrag(self, supportedActions):
        drag = QtGui.QDrag(self)
        t = [i.GetData() for i in self.selectedItems()]
        mimeData = self.model().mimeData(self.selectedIndexes())
        mimeData.setText(str(t))
        drag.setMimeData(mimeData)
        if drag.start(QtCore.Qt.MoveAction) == QtCore.Qt.MoveAction:
            for item in self.selectedItems():
                self.takeItem(self.row(item))

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

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

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.ignore()
        if isinstance(event.source(), MyListWidget):
            event.setDropAction(QtCore.Qt.MoveAction)
            super(MyListWidget, self).dropEvent(event)
        else:
            event.ignore()

    def dropMimeData(self, index, mimedata, action):
        super(MyListWidget, self).dropMimeData(index, mimedata, action)
        return True

class Test(QtGui.QMainWindow):
    def __init__(self):
        super(QtGui.QMainWindow,self).__init__()
        myQWidget = QtGui.QWidget()
        myBoxLayout = QtGui.QVBoxLayout()
        myQWidget.setLayout(myBoxLayout)
        self.setCentralWidget(myQWidget)

        self.listWidgetA = MyListWidget(self)
        self.listWidgetB = MyListWidget(self)

        for i in range(5):
            listItemAInstance = MyListWidgetItem(str(i), i, parent=self.listWidgetA)

        myBoxLayout.addWidget(self.listWidgetA)      
        myBoxLayout.addWidget(self.listWidgetB)   

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

My custom class MyListWidgetItem has a 'data' field which in my real program holds some information related to the item. If you run the code and try to drag and drop items from the top list to the bottom one everything works, but if you then try to bring them back to the top list you get this error:

Traceback (most recent call last):
  File "C:\Users\Massi\Desktop\t.py", line 23, in startDrag
    t = [i.GetData() for i in self.selectedItems()]
AttributeError: 'QListWidgetItem' object has no attribute 'GetData'

It seems pretty clear that the default drag and drop behaviour ignores that the list items have been subclassed, so I wonder which is the best to deal with this situation. Any help is really appreciated. Thanks in advance!

解决方案

If you add some debug information like following, you could find out that the "i" is already the MyListWidgetItem, so this should not be the issue.

  def startDrag(self, supportedActions):
        drag = QtGui.QDrag(self)
        # add the following 2 line debug information
        for item in self.selectedItems():
            print item.__class__.__name__
        t = [i.GetData() for i in self.selectedItems() if hasattr(i, "GetData")]
        mimeData = self.model().mimeData(self.selectedIndexes())
        mimeData.setText(str(t))
        drag.setMimeData(mimeData)
        if drag.start(QtCore.Qt.MoveAction) == QtCore.Qt.MoveAction:
            for item in self.selectedItems():
                self.takeItem(self.row(item))

output is

MyListWidgetItem

The problem is that you can NOT cast the item type to MyListWidgetItem, as python doesn't support type cast, so you need to use reflect mechanism to call the GetData() method, I have just tried the code, it works fine !

这篇关于拖放子类 QListWidgetItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆