有两个QListWidgets。使用setData(QtCore.Qt.UserRole, myClassInstA)
为每个列表项分配了MyClass()的实例。
点击较低的QListWidget的listItem打印出一个点击的listItem数据,使用以下方法检索:
.data(QtCore.Qt.UserRole).toPyObject()
从顶部QListWidget拖放到下方的任何itemA显示无数据。 有趣的是,点击相同的项目打印有一个数据。我想知道是否有可能在dropsOnB()函数中检索存储在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 :(得分:0)
最终目标是在将itemA删除到listWidgetB之后,将 MyClassA 的实例数据 - 对象(附加到itemA)替换为 MyClassB 。
当itemA被放到目标listWidgetB上时,itemA到达时没有存储数据。如果您尝试使用itemA.data(QtCore.Qt.UserRole).toPyObject()检索它,则返回None(如果在droppedOnB()内部完成 - 首先触发onDrop事件的方法)。
尝试分配,重新分配数据到刚删除的listItem ...甚至删除它会导致以后出现各种意外。我正在使用.setHidden(True)。
这些是步骤:
这是一个功能代码。 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_())