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 :

Configuration d'un QCompleter


Sujet :

PyQt Python

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2014
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 31
    Points : 30
    Points
    30
    Par défaut Configuration d'un QCompleter
    bonjour a tous,

    je bloque actuellement sur un probleme avec une lineEdit et un qcompleter.
    quand je tape dans ma lineEdit le début d'un mot, pas de probleme, par contre si les lettres tapé sont au milieu du terme recherché, ca ne ressort pas de résultat.
    exemple : je tape "a", j'ai pour résultat -amélie, -arnaud, mais pas jean-claude.
    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
            Data = cursor.execute("SELECT nom FROM proprietaire")
            listData = [unicode(i[0]) for i in Data] #création de la liste utilisé par la lineEdit
     
            self.lineEdit = LineEdit(parent=self.dockWidgetContents, completerContents=listData)
            self.verticalLayout_4.addWidget(self.lineEdit)
     
    class LineEdit(QtGui.QLineEdit):
        def __init__(self, parent, completerContents):
            super(LineEdit, self).__init__(parent)
     
            self.completerList = list()
            for content in completerContents:
                self.completerList.append(content)#Appends a new paragraph with text to the end of the text edit.
            self.completer = QtGui.QCompleter(self.completerList, self)
            self.completer.setCompletionMode(QtGui.QCompleter.PopupCompletion)#affiche une popup avec une liste de suggestion
            self.completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)#définit la sensibilité a la casse
            self.setCompleter(self.completer)
    j'ai consulté pas mal de site, beaucoup parle de recherche sur plusieurs mot ("chicken soup", "chilli peppers", "grilled chicken" par exemple, ch doit faire ressortir les trois termes et non les deux premiers)
    mais je n'ai pas trouvé le moyen de chercher par le "milieu" (ou la fin )

    j'espere que vous pourrez m'aider

  2. #2
    Expert éminent

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 298
    Points : 6 778
    Points
    6 778
    Par défaut
    Salut,

    Le QCompleter n'est pas conçu ainsi, il faudra que tu codes ça toi-même.

    Selon l'importance de la liste des mots existant, l'affichage du texte entré dans la lineEdit risque d'être hésitant. Tu devras sans doute limité la recherche sur un nombre minimum obligatoire de lettres, par exemple: ne rien faire avant trois lettres entrées.

  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,

    Je ne suis pas sûr d'avoir compris ce que tu cherches. Ce que je fais en général, c'est de faire selon une liste de chaine:

    - 1ère lettre tapée => liste restreinte aux chaines qui commencent par cette lettre
    - 2ème lettre tapée => liste restreinte aux chaines qui commencent par la lettre précédente + celle-ci
    - 3ème lettre tapée => liste restreinte aux chaines qui commencent par les 2 lettres précédentes + celle-ci
    - etc...

    Voilà un petit code qui fait ça (c'est en Python 3 mais ça devrait marcher en Python 2):

    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
    #! /usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 3, PyQt4
     
    import sys, os
    from PyQt4 import QtCore, QtGui
     
    prenoms = ["Aanor", "Aaricia", "Aaron", "Abbon", "Abby", "Abdel", "Abdon",
               "Abel", "Abélard", "Abélia", "Abella", "Abigaël", "Abondance",
               "Abraham", "Acace", "Achille", "Acmé", "Ada", "Adalard",
               "Adalbert", "Adalric", "Adalsinde", "Adam", "Adama", "Adélaïde",
               "Adélaïs", "Adélard", "Adèle", "Adelice", "Adélie", "Adelin",
               "Adelind", "Adeline", "Adelphe", "Adelphine", "Adeltrude",
               "Adémar", "Adénora", "Adine", "Adolphe", "Adon", "Adonis",
               "Adria", "Adrian", "Adriana", "Adriano", "Adrien", "Adrienne",
               "Adriette", "Adula", "Aedhan", "Aël", "Aëla", "Aélia", "Aëlig",
               "Aëlis", "Aelith", "Aëlred", "Aénor"]
     
    #############################################################################
    class Editcomp(QtGui.QLineEdit):
     
        def __init__(self, datas=(), parent=None):
            super(Editcomp, self).__init__(parent)
     
            completer = QtGui.QCompleter(self)
            self.setCompleter(completer)
     
            model = QtGui.QStringListModel(self)
            model.setStringList(datas)
            completer.setModel(model)
     
    #############################################################################
    class Fenetre(QtGui.QWidget):
     
        def __init__(self, parent=None):
            super(Fenetre, self).__init__(parent)
     
            self.edit = Editcomp(prenoms, self)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        fen = Fenetre()
        fen.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        fen.show()
        sys.exit(app.exec_())
    Si ce n'est pas ce que tu cherches, précise ta demande!
    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
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2014
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 31
    Points : 30
    Points
    30
    Par défaut
    Je ne suis pas sûr d'avoir compris ce que tu cherches. Ce que je fais en général, c'est de faire selon une liste de chaine:

    - 1ère lettre tapée => liste restreinte aux chaines qui commencent par cette lettre
    - 2ème lettre tapée => liste restreinte aux chaines qui commencent par la lettre précédente + celle-ci
    - 3ème lettre tapée => liste restreinte aux chaines qui commencent par les 2 lettres précédentes + celle-ci
    - etc...
    Si ce n'est pas ce que tu cherches, précise ta demande!
    je précise, je précise

    ce que je cherche, c'est que si l'utilisateur recherche, par exemple "haloa", et qu'il tape "aloa" parce qu'il ne sait pas comment cela s'écrit, cela lui ressorte une liste de tous les mots qui contiennet ces caracteres "aloa".
    or si j'ai bien compris ton programme tyrtamos, si l'utilisateur se plante sur la premiere lettre, le bon résultat n'apparaitra pas.

    je sais pas si c'est beaucoup plus clair...

  5. #5
    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
    Citation Envoyé par repgarent Voir le message
    ce que je cherche, c'est que si l'utilisateur recherche, par exemple "haloa", et qu'il tape "aloa" parce qu'il ne sait pas comment cela s'écrit, cela lui ressorte une liste de tous les mots qui contiennet ces caracteres "aloa".
    ...
    je sais pas si c'est beaucoup plus clair...
    Ça commence...

    A part avec les regex, on peut faire des recherches de 2 façons différentes: avec les wilcards" ou avec les mots similaires. Prenons des exemples:

    Wildcards: on utilise le module fnmatch
    - je tape a => il me propose la liste composé des "*a*"
    - je tape ensuite l et j'ai la liste composée des "*al*"
    - je tape ensuite o et j'ai la liste composée des "*alo*"
    - etc...
    A la place des '*', il peut y avoir n'importe quoi figurant dans la liste, qui "matche" avec le motif. Ce qui veut dire qu'avec "aloa", il y aura tous les mots de la liste qui contiennent "aloa" à l'intérieur.

    Mots similaires: on utilise la classe SequenceMatcher du module difflib
    Il faut définir un ratio pour "ratisser" plus ou moins large (80%?)
    - à chaque fois que j'ajoute une lettre, la liste renvoie les mots qui s'approche du mot tapé (au ratio près)
    Cela veut dire qu'avec le mot "aloa", la liste peut contenir des mots comme auloa, alao, loax, baloa, etc... (tous ces mots existant dans la liste bien sûr)
    J'utilise cette technique pour trouver des mots malgré des fautes de frappe (qui ne concernent en général qu'une lettre ou deux dans le mot mais placée(s) n'importe où)

    Est-ce que ce que tu cherches correspond à l'une de ces 2 solutions?

    En sachant qu'après, il faut voir comment modifier le fonctionnement de QCompleter pour qu'il apprenne à faire ça...

    [edit] en fait, dans la solution "wildcard", il suffira de faire des tests comme "if mot_tapé in mot_de_la_liste.
    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

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2014
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 31
    Points : 30
    Points
    30
    Par défaut
    la solution wildcard correspont tout a fait
    j'ai plus qu'a bosser la-dessus

    merci

  7. #7
    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,

    Comme c'était un problème plutôt intéressant et que j'aurai besoin un jour ou l'autre d'une telle solution, j'ai creusé un peu: voilà un petit code qui a l'air de faire le boulot:

    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
    #! /usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 3, PyQt4
     
    import sys
    from PyQt4 import QtCore, QtGui
     
    DATAS = ["Aanor", "Aaricia", "Aaron", "Abbon", "Abby", "Abdel", "Abdon",
               "Abel", "Abélard", "Abélia", "Abella", "Abigaël", "Abondance",
               "Abraham", "Acace", "Achille", "Acmé", "Ada", "Adalard",
               "Adalbert", "Adalric", "Adalsinde", "Adam", "Adama", "Adélaïde",
               "Adélaïs", "Adélard", "Adèle", "Adelice", "Adélie", "Adelin",
               "Adelind", "Adeline", "Adelphe", "Adelphine", "Adeltrude",
               "Adémar", "Adénora", "Adine", "Adolphe", "Adon", "Adonis",
               "Adria", "Adrian", "Adriana", "Adriano", "Adrien", "Adrienne",
               "Adriette", "Adula", "Aedhan", "Aël", "Aëla", "Aélia", "Aëlig",
               "Aëlis", "Aelith", "Aëlred", "Aénor"]
     
    #############################################################################
    class LineEdit(QtGui.QLineEdit):
        """QLineEdit avec une liste de mots pour completion datas
           la liste de mots sélectionnées s'affiche dans un popup
           les mots sélectionnés dans datas sont ceux qui contiennent le mot frappé
        """
     
        def __init__(self, datas, parent=None):
            super(LineEdit, self).__init__(parent)
     
            self.setFocusPolicy(QtCore.Qt.StrongFocus)
     
            # installe le QCompleter
            self.completer = QtGui.QCompleter(self)
            self.completer.setCompletionMode(QtGui.QCompleter.UnfilteredPopupCompletion)
            self.setCompleter(self.completer)
     
            # installe le model à partir de la liste fournie datas
            model = QtGui.QStandardItemModel()
            for i, word in enumerate(datas):
                item = QtGui.QStandardItem(word)
                model.setItem(i, 0, item)
     
            # installe le QSortFilterProxyModel qui s'insère entre le QCompleter et le model
            self.proxymodel = QtGui.QSortFilterProxyModel(self)
            self.proxymodel.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
            self.proxymodel.setSourceModel(model)
            self.completer.setModel(self.proxymodel)
     
            # chaque changement de texte déclenchera la filtration du model
            self.textEdited.connect(self.proxymodel.setFilterFixedString)
     
    #############################################################################
    class Fenetre(QtGui.QWidget):
     
        def __init__(self, parent=None):
            super(Fenetre, self).__init__(parent)
     
            self.lineEdit = LineEdit(DATAS, self)
     
            posit = QtGui.QGridLayout()
            posit.addWidget(self.lineEdit, 0, 0)
            self.setLayout(posit)
     
    #############################################################################
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        fen = Fenetre()
        fen.setAttribute(QtCore.Qt.WA_DeleteOnClose) # pour éviter un warning à la fermeture
        fen.show()
        sys.exit(app.exec_())
    On utilise ici un QSortFilterProxyModel qui s'insère entre le QCompleter et le model qui pointe sur la liste de mots.

    Ok?
    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

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2014
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2014
    Messages : 31
    Points : 30
    Points
    30
    Par défaut
    bonsoir,

    content que le sujet t'est intéréssé .
    le probleme est résolu de mon coté grace a ta derniere réponse.
    merci de ton aide.

    Rep

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

Discussions similaires

  1. configurer sql pour envoyer des mails
    Par arwen dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 29/07/2003, 16h28
  2. [postgresql]configuration serveur
    Par Fyna dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 16/06/2003, 20h22
  3. [configuration] lancer plusieurs serveurs Tomcat
    Par polo54 dans le forum JBuilder
    Réponses: 4
    Dernier message: 13/06/2003, 16h52
  4. Configurer OpenGL/Glut avec C++Bluider
    Par MiGoN dans le forum OpenGL
    Réponses: 2
    Dernier message: 14/09/2002, 00h18
  5. BDE : Configurer automatiquement le NETDIR
    Par Harry dans le forum Paradox
    Réponses: 10
    Dernier message: 29/07/2002, 12h33

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