Dropped customised QWidget item disappears in the QListWidget after internal drag/drop Pyside6 Qt for Python
-
I have adopted the code available on Drag'N'Drop custom widget items between QListWidgets to work with PySide6, after few modifications I have managed to run the code and it works as it should.
But there is one bug or flaw with this code. If an item inside a QListWidget drags and drops over another item in the same QListWidget object the items starts to disappear behind each other or get stacked over each other or sometimes being shown as a blank item. Like below
I am not sure what is wrong or missing with the implemented code that causes the issue.
In addition I would like to disable Copying while Drag and Dropby all means, if the user holds the CTRL button while dragging+dropping internally the flash symbol changes to changes to + symbol and items are added to the list.
This feature should get disabled and I do not know how to do it, if it is not possible to disable the copy feature while dropping I would like to know if there is any workaround available, since no more than one of each item should exist in either of QWidgetList objects [listWidgetA & listWidgetB] no duplicates of any items is allowed in both lists.
To summarise I would like following issues to get solved.
-
The flaw or issue with disappearing or stacking items while dragging and dropping the items in the same list.
-
The possibility of disabling copying the items while holding CTRL key while dragging and dropping or suggestion for a workaround that prevents the items to get copied in the same list or other list.
Below I have enclosed the faulty code.
from PySide6 import QtGui, QtCore, QtWidgets import sys, os, pathlib class ThumbListWidget(QtWidgets.QListWidget): def __init__(self, type, parent=None): super(ThumbListWidget, self).__init__(parent) self.setIconSize(QtCore.QSize(124, 124)) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) self.setDefaultDropAction(QtCore.Qt.MoveAction) self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.setAcceptDrops(True) self.model().rowsInserted.connect( self.handleRowsInserted, QtCore.Qt.QueuedConnection) def handleRowsInserted(self, parent, first, last): print(f"first:{first} last:{last} parent:{parent}") 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(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.listItems = {} myQWidget = QtWidgets.QWidget() myBoxLayout = QtWidgets.QHBoxLayout() myQWidget.setLayout(myBoxLayout) self.setCentralWidget(myQWidget) self.myQListWidget = ThumbListWidget(self) myBoxLayout.addWidget(self.myQListWidget) images_files_dir = pathlib.Path(__file__).parent.absolute().joinpath("custom_qlistwidget") for data in [ ('No.1', 'Meyoko', pathlib.Path(images_files_dir).joinpath('among-us-small-green.png')), ('No.2', 'Nyaruko', pathlib.Path(images_files_dir).joinpath('among-us-small-yellow.png')), ('No.3', 'Louise', pathlib.Path(images_files_dir).joinpath('among-us-small-red.png'))]: myQListWidgetItem = QtWidgets.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(QtWidgets.QWidget): def __init__(self, parent=None): # super(QCustomQWidget, self).__init__(parent) super().__init__(parent) self.textQVBoxLayout = QtWidgets.QVBoxLayout() self.textUpQLabel = QtWidgets.QLabel() self.textDownQLabel = QtWidgets.QLabel() self.textQVBoxLayout.addWidget(self.textUpQLabel) self.textQVBoxLayout.addWidget(self.textDownQLabel) self.allQHBoxLayout = QtWidgets.QHBoxLayout() self.iconQLabel = QtWidgets.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 = QtWidgets.QApplication(sys.argv) dialog_1 = Dialog_01() dialog_1.show() dialog_1.resize(480, 320) app.exec()
-
-
Hi and welcome to devnet,
For the actions, you need to reimplement the supportedDropActions and return only what you want to allow.
As for your custom widget creation, from the looks of it, you should rather implement a custom QStyledItemDelegate.
In any case, you should check the condition parameters and their values.
-
Hi and welcome to devnet,
For the actions, you need to reimplement the supportedDropActions and return only what you want to allow.
As for your custom widget creation, from the looks of it, you should rather implement a custom QStyledItemDelegate.
In any case, you should check the condition parameters and their values.
-
You seem to have an image and two lines of text.
Implementing the paintEvent of the delegate to show them would be way lighter on resources.