在QListWidgets之间拖放自定义小部件项目 [英] Drag'N'Drop custom widget items between QListWidgets
问题描述
我目前正在使用Python程序工作,我想通过拖放将项目从一个QListWidget移至另一个。
i am currently working on a Python program, where i want to move items from one QListWidget to another with Drag and Drop.
我阅读了线程,并按照说明实施了拖放。它与标准QListWidgetItems一起使用。
问题是,我想在QListWidgetItems内部执行此自定义小部件,如此处,将一个图标和几行存储到1个QListWidgetItem中。
i read this thread, and implemented the Drag and Drop as described. It works with standard QListWidgetItems. The Problem is, i wanna do this custom widgets inside the QListWidgetItems, as described here, to store an icon and several lines into 1 QListWidgetItem.
因此,当我现在将一个项目拖放到另一个列表中时,它是空的,因为它似乎只是为了移动/复制不带ItemWidget的QListWidgetItem。
So when i now drag and drop an item into another list, it is empty, because it seems just to move/copy the QListWidgetItem without its ItemWidget.
这里有一个示例代码:
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):
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.myQListWidget = ThumbListWidget(self)
myBoxLayout.addWidget(self.myQListWidget)
for index, name, icon in [
('No.1', 'Meyoko', 'icon.png'),
('No.2', 'Nyaruko', 'icon.png'),
('No.3', 'Louise', 'icon.png')]:
# Create QCustomQWidget
myQCustomQWidget = QCustomQWidget()
myQCustomQWidget.setTextUp(index)
myQCustomQWidget.setTextDown(name)
myQCustomQWidget.setIcon(icon)
# Create QListWidgetItem
myQListWidgetItem = QtGui.QListWidgetItem(self.myQListWidget)
# Set size hint
myQListWidgetItem.setSizeHint(myQCustomQWidget.sizeHint())
# Add QListWidgetItem into QListWidget
self.myQListWidget.addItem(myQListWidgetItem)
self.myQListWidget.setItemWidget(myQListWidgetItem, myQCustomQWidget)
self.listWidgetB = ThumbListWidget(self)
myBoxLayout.addWidget(self.listWidgetB)
class QCustomQWidget (QtGui.QWidget):
def __init__ (self, parent = None):
super(QCustomQWidget, self).__init__(parent)
self.textQVBoxLayout = QtGui.QVBoxLayout()
self.textUpQLabel = QtGui.QLabel()
self.textDownQLabel = QtGui.QLabel()
self.textQVBoxLayout.addWidget(self.textUpQLabel)
self.textQVBoxLayout.addWidget(self.textDownQLabel)
self.allQHBoxLayout = QtGui.QHBoxLayout()
self.iconQLabel = QtGui.QLabel()
self.allQHBoxLayout.addWidget(self.iconQLabel, 0)
self.allQHBoxLayout.addLayout(self.textQVBoxLayout, 1)
self.setLayout(self.allQHBoxLayout)
# setStyleSheet
self.textUpQLabel.setStyleSheet('''
color: rgb(0, 0, 255);
''')
self.textDownQLabel.setStyleSheet('''
color: rgb(255, 0, 0);
''')
def setTextUp (self, text):
self.textUpQLabel.setText(text)
def setTextDown (self, text):
self.textDownQLabel.setText(text)
def setIcon (self, imagePath):
self.iconQLabel.setPixmap(QtGui.QPixmap(imagePath))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog_1 = Dialog_01()
dialog_1.show()
dialog_1.resize(480,320)
sys.exit(app.exec_())
所以基本问题是:我如何转移物品
So the basic question is: How can i transfer the items ItemWidget while using drag and drop.
使用QListView这样的东西会更好吗?
Would it maybe be better to use a QListView for something like this?
推荐答案
如问题注释中所述,无法序列化小部件,因此无法通过拖放。但是,您可以使用项目的 setData
方法存储重新创建该项目的小部件所需的数据。这将实现起来简单得多,因为您可以使用list-widget模型的 rowsInserted
信号在每次插入项目时自动添加新的小部件。
As stated in the comments to the question, there is no way to serialize a widget, so it cannot be transferred via drag and drop. However, you can use an item's setData
method to store the data that is needed to re-create the item's widget. This will be far simpler to implement, because you can then use the rowsInserted
signal of the list-widget's model to automatically add a new widget every time an item is inserted.
下面显示的脚本实现了这一点,并且可以处理与每个列表小部件之间的多个项目的拖放操作。请注意,不再需要拖放事件方法,也不再需要显式设置自定义窗口小部件。
The script shown below implements that, and can handle dragging and dropping multiple items to and from each list-widget. Note that the drag/drop *event methods are no longer needed, and you no longer need to explicitly set the custom widgets.
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.setDefaultDropAction(QtCore.Qt.MoveAction)
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.setAcceptDrops(True)
self.model().rowsInserted.connect(
self.handleRowsInserted, QtCore.Qt.QueuedConnection)
def handleRowsInserted(self, parent, first, last):
for index in range(first, last + 1):
item = self.item(index)
if item is not None and self.itemWidget(item) is None:
index, name, icon = item.data(QtCore.Qt.UserRole)
widget = QCustomQWidget()
widget.setTextUp(index)
widget.setTextDown(name)
widget.setIcon(icon)
item.setSizeHint(widget.sizeHint())
self.setItemWidget(item, widget)
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.myQListWidget = ThumbListWidget(self)
myBoxLayout.addWidget(self.myQListWidget)
for data in [
('No.1', 'Meyoko', 'icon.png'),
('No.2', 'Nyaruko', 'icon.png'),
('No.3', 'Louise', 'icon.png')]:
myQListWidgetItem = QtGui.QListWidgetItem(self.myQListWidget)
# store the data needed to create/re-create the custom widget
myQListWidgetItem.setData(QtCore.Qt.UserRole, data)
self.myQListWidget.addItem(myQListWidgetItem)
self.listWidgetB = ThumbListWidget(self)
myBoxLayout.addWidget(self.listWidgetB)
class QCustomQWidget (QtGui.QWidget):
def __init__ (self, parent = None):
super(QCustomQWidget, self).__init__(parent)
self.textQVBoxLayout = QtGui.QVBoxLayout()
self.textUpQLabel = QtGui.QLabel()
self.textDownQLabel = QtGui.QLabel()
self.textQVBoxLayout.addWidget(self.textUpQLabel)
self.textQVBoxLayout.addWidget(self.textDownQLabel)
self.allQHBoxLayout = QtGui.QHBoxLayout()
self.iconQLabel = QtGui.QLabel()
self.allQHBoxLayout.addWidget(self.iconQLabel, 0)
self.allQHBoxLayout.addLayout(self.textQVBoxLayout, 1)
self.setLayout(self.allQHBoxLayout)
# setStyleSheet
self.textUpQLabel.setStyleSheet('''
color: rgb(0, 0, 255);
''')
self.textDownQLabel.setStyleSheet('''
color: rgb(255, 0, 0);
''')
def setTextUp (self, text):
self.textUpQLabel.setText(text)
def setTextDown (self, text):
self.textDownQLabel.setText(text)
def setIcon (self, imagePath):
self.iconQLabel.setPixmap(QtGui.QPixmap(imagePath))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog_1 = Dialog_01()
dialog_1.show()
dialog_1.resize(480,320)
app.exec_()
这篇关于在QListWidgets之间拖放自定义小部件项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!