Résolue

PySide6 problème mise à jour de l'affichage d'un QListWidget

# Fichiers # Interface graphique # PySide

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!!

Hello,

Salut David je ne suis pas sûr car je ne peux pas tester les scripts pyside sur ma machine mais ta méthode updateListDisplay devrait peut être être appelée à chaque nouveaux drag and drop non ? Là il me semble que ce n'est pas le cas.

Thibault houdon

Mentor

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!

Thibault houdon

Mentor

C'est une bonne feuille de route :)

Bonne soirée de même et n'hésite pas si tu as d'autres questions !

Inscris-toi

(c'est gratuit !)

Inscris-toi

Tu dois créer un compte pour participer aux discussions.

Créer un compte

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.