Déplacer des items à l'intérieur d'un QListWidget custom (PySide6)
Salut!
J'ai une petite app permettant de glisser-déposer des fichiers (ou url) dans un Qlist Widget. En revanche , j'aimerais pouvoir déplacer les items de la liste avec QAbstractItemView.InternalMove
Voici le code complet:
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QListWidget, QListWidgetItem, QPushButton, QAbstractItemView
from PySide6.QtCore import Qt, QUrl
class ListBoxWidget(QListWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAcceptDrops(True)
self.resize(600, 600)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else:
event.ignore()
def dragMoveEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
else:
event.ignore()
def dropEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
links = []
for url in event.mimeData().urls():
if url.isLocalFile():
links.append(str(url.toLocalFile()))
else:
links.append(str(url.toString()))
self.addItems(links)
else:
event.ignore()
class MyApp(QMainWindow):
def __init__(self):
super().__init__()
self.resize(1200, 600)
self.listbox_view = ListBoxWidget(self)
self.listbox_view.setDragDropMode(QAbstractItemView.InternalMove)
self.btn = QPushButton("Get Value", self)
self.btn.setGeometry(850, 400, 200, 50)
self.btn.clicked.connect(lambda: print(self.getSelectedItem()))
def getSelectedItem(self):
item = QListWidgetItem(self.listbox_view.currentItem())
return item.text()
app = QApplication(sys.argv)
win = MyApp()
win.show()
sys.exit(app.exec())
Je cherche depuis quelque temps mais je n'arrive pas à faire bouger les items du QListWidget...!
Merci d'avance!
Salut David et désolé pour le délai de réponse !
Il y a pas mal de petites choses ici qui posent problème.
Voici déjà le code qui fonctionne et je t'explique tout en détail après :
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QListWidget, QListWidgetItem, QPushButton, QAbstractItemView
from PySide6.QtCore import Qt, QUrl
class ListBoxWidget(QListWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAcceptDrops(True)
self.resize(600, 600)
self.setDragDropMode(QAbstractItemView.InternalMove)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
super().dragEnterEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
links = []
for url in event.mimeData().urls():
if url.isLocalFile():
links.append(str(url.toLocalFile()))
else:
links.append(str(url.toString()))
self.addItems(links)
else:
super().dropEvent(event)
class MyApp(QMainWindow):
def __init__(self):
super().__init__()
self.resize(1200, 600)
self.listbox_view = ListBoxWidget(self)
self.btn = QPushButton("Get Value", self)
self.btn.setGeometry(850, 400, 200, 50)
self.btn.clicked.connect(lambda: print(self.getSelectedItem()))
def getSelectedItem(self):
item = self.listbox_view.currentItem()
if item: # Added check if any item is selected
return item.text()
app = QApplication(sys.argv)
win = MyApp()
win.show()
sys.exit(app.exec())
Déjà, j'ai déplacé self.setDragDropMode(QAbstractItemView.InternalMove) directement dans le __init__ de ta liste, c'est mieux de le mettre ici plutôt que dans la classe de ta fenêtre (comme ça si tu déplaces ton ListWidget ailleurs ou le réutilise, le comportement suivra avec).
J'ai enlevé le dragMoveEvent, dans ce cas-ci tu n'en as pas besoin puisque ce qui t'intéresse c'est uniquement le drop (quand on dépose les items) ou quand on commence à les déplacer. Mais le déplacement en tant que tel n'a pas d'intérêt pour toi donc on laisse le comportement par défaut.
Et pour finir, dans la méthode dropEvent, une fois déposé, tes éléments n'ont plus d'url associé, du coup dans le else il faut faire appel au comportement par défaut du drop en utilisant super (super().dropEvent(event)). Ça permet de garder la fonctionnalité de déplacement interne dans ta liste une fois les éléments déposés. Dans ton cas tu utilisais event.ignore() donc le mouvement à l'intérieur de la liste était prohibé une fois les éléments déposés dans cette dernière.
J'espère que c'est plus clair avec ces explications :)
Salut Thibault,
Pas de problème!
Un grand merci pour ces explications! Tout ça est beaucoup plus clair maintenant.
En effet mettre self.setDragDropMode(QAbstractItemView.InternalMove) dans le __init__ est beaucoup mieux.
et aussi event.ignore() pas adapté...
Super en tout cas, ça me débloque
Inscris-toi
(c'est gratuit !)
Tu dois créer un compte pour participer aux discussions.
Créer un compte