IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

QFileDialog personnalisée widgets


Sujet :

PyQt Python

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Points : 72
    Points
    72
    Par défaut QFileDialog personnalisée widgets
    Bonjour,

    je cherche à intégrer une QFileDialog en permanence ouverte dans une QMainWindow.
    L'intégration se fait très bien mais je n'ai pas besoin des boutons par défaut dedans ("open" et "cancel") ni des champs associés (nom et types de fichier à travers deux labels et 2 lignes de champ texte).
    En fait ces deux choses là (types fichiers et noms) sont gérés plus tard dans l'appli et je souhaite juste pouvoir naviguer dans les arborescences en récupérant des path si un dossier est sélectionné et qu'un QPushButton (externe au Qfiledialog) est cliqué.

    est-il possible d'avoir accès à ces widgets "intégrés" à la Qfiledialog (à savoir les Qpushbutton, les labels et les QLine Edit je suppose) et les forcer à être invisible?
    Ou faut il que je m'embarque dans un personnalisation d'un Widget embarquant un QTextEdit et un QTreeview paramétrés avec les clics event?

    merci pour vos conseils!

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Tu auras plus facile d'implémenter un QTreeView d'après moi.

    Ici tu as un exemple complet:
    https://bazaar.launchpad.net/~vincen...ilesbrowser.py

    Les signaux renvoient vers des méthodes situées dans l'application, donc faut adapter bien sur.

  3. #3
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Si tu veux beaucoup de changements, je suis d'accord avec VinsS: ce sera plus simple de construire ton propre widget composite.

    Mais il est tout de même possible de faire ce que tu proposes. En voici la logique:

    - par défaut, le QFileDialog utilise en fait celui de l'OS, et on ne peut pas le modifier. Il faut donc demander à Qt de ne pas le prendre. On fait ça avec l'option QFileDialog.DontUseNativeDialog.

    - le QFiledialog de Qt est un widget composite construit avec les widgets de la bibliothèque Qt: QlineEdit, QPushButton, QTreeView, QLabel, ... Il faut donc chercher (et trouver) le widget dont on veut modifier le comportement avec les méthodes "findChild" et "findChildren" et faire des tests pour vérifier qu'on a bien trouvé le bon. Il faut tâtonner un peu...

    - une fois trouvé le bon widget à modifier, il ne faut pas seulement modifier son apparence comme souhaité, mais souvent modifier son comportement, et ce n'est pas le plus facile. Par exemple, si je sélectionne plusieurs éléments et que je les désélectionne tous, le QFileDialog modifié ne doit rien renvoyer!

    Pour te donner un exemple concret, voici ce que j'ai déjà fait pour un de mes programmes.

    Pour un programme perso de lecture de mp3, je voulais pouvoir sélectionner plusieurs fichiers ET plusieurs répertoires et les renvoyer dans l'ordre de la sélection. Une sorte de "playlist", dans laquelle chaque répertoire représentant une sorte de CD est remplacé ultérieurement par son contenu en fichiers mp3 triés par ordre alphanumérique. Et ça, ce n'est pas prévu dans la bibliothèque Qt. Il a donc fallu que je fasse ce que je viens de dire, et voilà le code que ça donne. Regarde bien comment j'ai procédé aux modifications (il y a pas mal de commentaires). Je mets ça dans un fichier "selectiondisque.py" qu'il ne me reste plus qu'à importer dans le programme utilisateur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    """
    Permet de sélectionner plusieurs fichiers et dossiers en conservant l'ordre 
    des sélections
    N'utilise pas la fenêtre de sélection de l'OS 
    """
     
    from PyQt5.QtCore import (pyqtSlot, QEvent)
     
    from PyQt5.QtWidgets import (QFileDialog, QTreeView, QFileSystemModel, 
        QAbstractItemView, QPushButton, QDialog, QLineEdit, QLabel)
     
    ##############################################################################
    class SelectionFichiersDossiers(QFileDialog):
        """Une fenêtre de dialogue pour sélection de fichiers et de répertoires
        """
     
        #=========================================================================
        def __init__(self, parent=None, 
                           titre='Sélectionnez fichiers et répertoires', 
                           dossier='.', 
                           filtre="Tous les fichiers (*)"):
            super().__init__(parent, titre, dossier, filtre)
     
            # n'utilise pas la fenêtre de dialogue de l'OS
            self.setOptions(self.Options() | QFileDialog.DontUseNativeDialog)
            # sélection pour ouvrir et non enregistrer
            self.setAcceptMode(QFileDialog.AcceptOpen)
            # affiche en même temps les répertoires et les fichiers
            self.setFileMode(QFileDialog.Directory)
            # aucune modification acceptée sur le disque
            self.setOptions(self.Options() | QFileDialog.ReadOnly)
            # affiche le filtre de sélection des fichiers sans ses détails 
            self.setOptions(self.Options() | QFileDialog.HideNameFilterDetails)
     
            # change le comportement des sélections dans l'arborescence
            self.treeView = self.findChild(QTreeView)
            if isinstance(self.treeView.model(), QFileSystemModel):
                # affiche l'arborescence du disque
                self.treeView.setRootIsDecorated(True)
                self.treeView.setItemsExpandable(True)
                # définit le type de sélection
                self.treeView.setSelectionMode(QAbstractItemView.ExtendedSelection)
                # méthode à lancer à chaque sélection (active/désactive le bouton)
                self.treeView.selectionModel().selectionChanged.connect(self.miseajour)
     
            # change le comportement du bouton de fin de sélection
            for bouton in self.findChildren(QPushButton):
                if bouton.text().strip().lower().replace("&", "") in ['choose', 'choisir']:
                    bouton.clicked.disconnect() # suppression ancien lien
                    bouton.clicked.connect(self.findeselection) # nouveau lien
                    bouton.installEventFilter(self) # met en place le eventFilter
                    bouton.setEnabled(False) # désactivé avant 1ère sélection
                    self.bouton = bouton
                    break # le bon bouton a été choisi
     
            # trouver l'adresse de la ligne d'édition
            edits = self.findChildren(QLineEdit)
            for edit in edits:
                if edit.objectName() == "fileNameEdit":
                    self.edit = edit
                    break
     
            # changer le titre de la ligne d'édition des fichiers/dossiers
            labels = self.findChildren(QLabel)
            for label in labels:
                if label.objectName() == "fileNameLabel":
                    if "directory" in label.text().lower(): # version anglaise
                        label.setText("Files/folders :")
                    elif "dossier" in label.text().lower(): # version française
                        label.setText("Fichiers/dossiers :")
                    break
     
        #=========================================================================
        @pyqtSlot("QObject", "QEvent")
        def eventFilter(self, watched, event):
            """évènement concernant le bouton lors d'un changement de sélection
            """
            if event.type() == QEvent.EnabledChange:
                if not watched.isEnabled():
                    if isinstance(self.treeView.model(), QFileSystemModel):
                        if len(self.treeView.selectionModel().selectedIndexes()) > 0:
                            watched.setEnabled(True) # active le bouton
     
            return super().eventFilter(watched, event)
     
        #=========================================================================
        @pyqtSlot("QItemSelection", "QItemSelection")
        def miseajour(self, _sel, _desel):
            """lancé à chaque nouvelle sélection de fichier ou de répertoire
               active/désactive le bouton selon la présence/absence d'une sélection
            """
            if isinstance(self.treeView.model(), QFileSystemModel):
                if len(self.treeView.selectionModel().selectedIndexes()) > 0:
                    # activetion du bouton quand il y a au moins une sélection
                    self.bouton.setEnabled(True)
                else:
                    # désactivation du bouton quand il n'y a aucune sélection
                    self.bouton.setEnabled(False)
     
                    # effacement de la ligne d'édition
                    self.edit.clear()
     
        #=========================================================================
        @pyqtSlot(bool)
        def findeselection(self, _check=False):
            """lancé par le bouton de fin de sélection
               termine la boucle locale et ferme la fenêtre de dialogue
               en retournant l'acceptation de la sélection 
            """
            self.done(QDialog.Accepted)
     
    ##############################################################################
    def selectionfichiersdossiers(parent=None, 
                                  titre="Sélection fichers et dossiers ", 
                                  dossier=".", 
                                  filtre="tous les fichiers (*)"):
        """fonction qui lance la fenêtre de dialogue pour sélectionner à la fois 
           des fichiers et des dossiers, et en retourne la liste
           - titre: le titre de la fenêtre de dialogue
           - dossier: le répertoire racine de la recherche
           - filtre: chaine de car. donnant les motifs "wildcard" à afficher
               exemple: "Musique (*.mp3 *.flac *.wma);; Tous les fichiers (*)"
        """
        dialogue = SelectionFichiersDossiers(parent, titre, dossier, filtre)
        print()
        if dialogue.exec_() == QDialog.Accepted:
            return dialogue.selectedFiles() # liste des fichiers et dossiers
        else:
            return [] # sortie du dialogue sans sélection
    Et voilà un petit code de test pour utiliser la fonction définie "selectionfichiersdossiers(...)":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    import sys
     
    # importe le dialogue pour sélectionner les morceaux de la playlist
    from selectiondisque import selectionfichiersdossiers
     
    # bibliothèque PyQt5
    from PyQt5.QtWidgets import QApplication
     
    ##############################################################################
    if __name__ == "__main__":
     
        # lance la bibliothèque graphique
        app = QApplication(sys.argv)
     
        # définit les données de recherche    
        titre = "Sélectionnez des musiques"
        repertoire = r"monrepertoiredemusique" # mettre le bon répertoire des musiques!
        motifs = "*.mp3;*.flac;*.wma"
        filtre = "Musique (" + motifs.replace(";", " ") + ");; Tous les fichiers (*)"
     
        # lance la recherche des sélections
        selections = selectionfichiersdossiers(None, titre, repertoire, filtre)
     
        # affiche les sélections réalisées
        for selection in selections:
            print(selection)
    Bon courage!
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  4. #4
    Membre régulier
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Points : 72
    Points
    72
    Par défaut
    Bonjour,
    merci pour vos réponses! je vais me pencher sur les deux alternatives :-)
    pour le fun!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Android] Widget calendrier personnalisable
    Par declencher dans le forum Mon application mobile
    Réponses: 5
    Dernier message: 19/12/2020, 10h19
  2. Afficher une QFileDialog comme widget
    Par hizoka dans le forum PyQt
    Réponses: 5
    Dernier message: 20/11/2014, 10h08
  3. Réponses: 6
    Dernier message: 13/02/2013, 17h45
  4. Personnalisation du widget Accordéon
    Par figueline dans le forum Dreamweaver
    Réponses: 1
    Dernier message: 29/01/2010, 14h41
  5. [VB6] [UserControl] Évènements personnalisés
    Par Frankywinky dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 27/05/2003, 17h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo