PySide6 problème mise à jour de l'affichage d'un QListWidget
Bonjour à tous,
j'ai fait une petite appli permettant de manipuler des fichiers pdf.
Je passe par une interface graphique faite avec PySide6, dans laquelle j'ai un QListWidget, permettant de glisser/déposer les fichiers.
Je peux aussi cliquer sur un bouton "Sélectionner les fichiers" ouvrant un QFileDialog et je sélectionne mes fichiers.
Et en dessous, 2 radio button permettant de modifier l'affichage dans le QListWidget.
Le 1er radio button permet d'afficher uniquement le nom du fichier, et le deuxième permet d'afficher le chemin complet.
J'ai aussi un bouton 'Effacer la sélection" qui permet de vider le QListWidget.
La cas qui ne fonctionne pas:
Je fais un drag&drop de 2 fichiers pdf, je peux changer l'affichage correctement en cliquant indépendamment sur chaque radio button. Si je clique sur le bouton "Effacer la sélection", et que je refais un drag&&drop avec des pdf, ils s'affichent bien, mais si je clique maintenant sur 1 des 2 radio button, tout disparait… Je n'arrive pas à comprendre pourquoi…
Lien Github: https://github.com/RIVIEREDavid/Merge_and_rename_pdfs.git
Merci d'avance pour votre aide!!
Bonsoir David !
Alors le problème c'est que tu déclares deux listes file_paths pour gérer tes chemins, une variable dans ta fenêtre, et une autre dans ton ListWidget.
Du coup tu ne manipules pas les mêmes listes à chaque fois et c'est ça qui crée le problème (je n'ai pas investigué plus loin pourquoi ça aboutissait sur ce problème, mais en enlevant une des deux listes, ça résoud le problème 😄).
Voici le script fonctionnel (j'ai enlevé tout le superflu pour me concentrer uniquement sur ce problème) :
import sys
import shutil
import tempfile
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QLabel, QPushButton, QFileDialog, QListWidget, QWidget, QAbstractItemView, QMessageBox, QRadioButton, QMenu
from PySide6.QtGui import Qt
from PySide6.QtCore import QMimeData
from pathlib import Path
class ListBoxWidget(QListWidget):
def __init__(self, parent): # Ici je défini juste un paramètre parent
super().__init__()
self.setAcceptDrops(True)
self.resize(600, 600)
self.setDragDropMode(QAbstractItemView.InternalMove) # type: ignore
self.parent = parent # Je le stock dans cette variable
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
super().dragEnterEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
for url in event.mimeData().urls():
file_path = url.toLocalFile()
if file_path.endswith(".pdf") or file_path.endswith(".PDF"):
self.addItem(file_path)
# Ici j'accède à la variable file_paths du parent (de la fenêtre MainWindow)
self.parent.file_paths.append(file_path)
print(self.parent.file_paths)
else:
super().dropEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("Fusion / Split de fichiers PDF")
self.setMinimumSize(400, 300)
self.setWindowFlag(Qt.WindowStaysOnTopHint, True) # type: ignore
layout = QVBoxLayout()
label = QLabel("Glissez-déposez les fichiers PDF ici")
label.setAlignment(Qt.AlignCenter) # type: ignore
layout.addWidget(label)
self.file_paths = []
# Lors de la création de l'instance de la liste, je passe l'instance de la fenêtre au paramètre parent
self.list_widget = ListBoxWidget(parent=self) # passer en paramètres merge_button et split_button
self.list_widget.setDragDropMode(QAbstractItemView.InternalMove) # type: ignore
layout.addWidget(self.list_widget)
self.clear_button = QPushButton("Effacer la sélection")
self.clear_button.clicked.connect(self.clear_list)
layout.addWidget(self.clear_button)
self.rb1 = QRadioButton("Nom du fichier")
self.rb1.toggled.connect(self.updateListDisplay)
layout.addWidget(self.rb1)
self.rb2 = QRadioButton("Chemin complet")
self.rb2.toggled.connect(self.updateListDisplay)
layout.addWidget(self.rb2)
central_widget = QWidget()
central_widget.setLayout(layout)
self.setCentralWidget(central_widget)
def clear_list(self):
self.list_widget.clear()
self.file_paths = []
print(self.file_paths)
def updateListDisplay(self):
print(self.file_paths)
show_full_path = self.rb2.isChecked()
self.list_widget.clear()
if show_full_path:
self.list_widget.addItems(self.file_paths)
else:
self.list_widget.addItems([Path(file_path).name for file_path in self.file_paths])
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
Je t'ai mis des commentaires aux endroits importants.
En gros je passe l'instance de MainWindow à ton ListWidget dans le paramètre parent. Et comme ça dans ton ListWidget tu peux accéder à la liste définie dans MainWindow (self.file_paths) et la manipuler directement dans le cas du DropEvent pour tout remettre à jour :)
Voilà, j'espère que les explications sont claires, n'hésite pas si c'est encore un peu confus.
À très vite !
Salut!
Super merci de vos retours, en effet la fonctionnalité drag&drop fonctionne bien, et c'est beaucoup plus clair. Il faut maintenant que je réimplante mes boutons "Fusionner les fichiers (plusieurs fichiers requis)" et "Splitter le fichier (un seul fichier requis)", ainsi que leurs fonctionnalités respectives. Et aussi l'option qui permet de contourner le drag&drop avec un bouton "Sélectionner les fichiers" permettant d'ouvrir un QFileDialog. Dans la description de l'appli je n'en ai pas parlé effectivement, donc pas mal de bouts de codes pouvaient paraitre superflus (désolé pour la confusion).
Je galère à faire fonctionner les 2 méthodes simultanément, le drag&drop en même temps que la sélection de fichiers par QFileDialog...
Je réssaye d'arranger tout ça dès que je peux.
Bonne soirée!
Inscris-toi
(c'est gratuit !)
Tu dois créer un compte pour participer aux discussions.
Créer un compte