Python:如何在PyQt中跟踪从一个ListWidget拖放到另一个的ListItem
这里有两个可以拖放的列表控件(这个例子是从之前的帖子中拿来的)。当发生放置事件时,会调用 droppedOnA(arg) 和 droppedOnA(arg) 这两个方法。从对话框外部(比如从文件浏览器)拖放到列表控件上是可以正常工作的。但是,从一个列表控件拖放到另一个列表控件就不行了。因为没有办法追踪到底放置了哪些项目,因为 droppedOnA(arg) 和 droppedOnA(arg) 这两个方法没有接收到任何参数(这和从对话框外部拖放时的情况不同)。在我开始用一些复杂的方法来解决这个问题之前,我想确认一下是否还有其他的解决办法。有没有呢?
from PyQt4 import QtGui, QtCore
import sys, os
class MyClassItem(QtGui.QListWidgetItem):
def __init__(self, parent=None):
super(QtGui.QListWidgetItem, self).__init__(parent)
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)
self.emit(QtCore.SIGNAL("dropped"))
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)
self.listWidgetB = ThumbListWidget(self)
for i in range(3):
listItemAInstance=MyClassItem()
name='A'+'%04d'%i
listItemAInstance.setText(name)
listItemAInstance.setBackgroundColor(QtCore.Qt.darkGray)
if i%2: listItemAInstance.setBackgroundColor(QtCore.Qt.gray)
icon=self.getIcon(name)
listItemAInstance.setIcon( icon )
self.listWidgetA.addItem(listItemAInstance)
listItemBInstance=MyClassItem()
name='B'+'%04d'%i
listItemBInstance.setText(name)
icon=self.getIcon(name)
listItemBInstance.setIcon( icon )
if i%2: listItemBInstance.setBackgroundColor(QtCore.Qt.lightGray)
self.listWidgetB.addItem(listItemBInstance)
myBoxLayout.addWidget(self.listWidgetA)
myBoxLayout.addWidget(self.listWidgetB)
self.connect(self.listWidgetA, QtCore.SIGNAL("dropped"), self.droppedOnA)
self.connect(self.listWidgetB, QtCore.SIGNAL("dropped"), self.droppedOnB)
Button_01 = QtGui.QPushButton("Print Dropped Items")
Button_01.clicked.connect(self.printWhatItemsWereDropped)
myBoxLayout.addWidget(Button_01)
def printWhatItemsWereDropped(self):
print "List of items dropped: "
def getThumbPath(self, name):
thumb_dirpath=os.path.expanduser("~")+'/thumbs/' +name+'/'+name+'.jpg'
return thumb_dirpath
def getIcon(self, name):
thumbpath=self.getThumbPath(name)
if not thumbpath: return
color='black'
if os.path.exists( os.path.dirname( thumbpath ) ) == False: os.makedirs( os.path.dirname( thumbpath ) )
img = QtGui.QImage(64, 64, QtGui.QImage.Format_RGB32)
img.fill(QtGui.QColor(96,96,96))
painter = QtGui.QPainter(img)
font = painter.font()
font.setBold(True)
font.setPointSize(48)
filename, fileExtension = os.path.splitext( os.path.basename( thumbpath ) )
text=filename.upper()
font.setPointSize(18)
painter.setPen(QtGui.QColor(color))
painter.setFont(font)
painter.drawText(img.rect(), QtCore.Qt.AlignCenter, text)
painter.end()
img.save(thumbpath, 'JPG')
icon = QtGui.QIcon( thumbpath )
pixmap = icon.pixmap(64, 64)
icon = QtGui.QIcon(pixmap)
return icon
def droppedOnA(self, arg=None):
print '\n\t droppedOnA', arg
def droppedOnB(self, arg=None):
print '\n\t droppedOnB', arg
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog_1 = Dialog_01()
dialog_1.show()
dialog_1.resize(720,480)
sys.exit(app.exec_())
1 个回答
2
我之前在一个回答的评论里提到过怎么做这个。不过无论如何,这里有一个稍微简单粗糙的实现,它会打印出源列表控件的名称,后面跟着被放下的索引。
class ThumbListWidget(QtGui.QListWidget):
_drag_info = []
def __init__(self, type, name, parent=None):
super(ThumbListWidget, self).__init__(parent)
self.setObjectName(name)
...
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 dropEvent(self, event):
if event.mimeData().hasUrls():
...
elif self._drag_info:
event.setDropAction(QtCore.Qt.MoveAction)
super(ThumbListWidget, self).dropEvent(event)
self.emit(QtCore.SIGNAL("dropped"), list(self._drag_info))
...
self.listWidgetA = ThumbListWidget(self, 'A')
self.listWidgetB = ThumbListWidget(self, 'B')