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

Python Discussion :

Problème de séquencement d'objets de classes


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Ingénieur géologue
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur géologue
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Par défaut Problème de séquencement d'objets de classes
    Bonjour,
    Je travaille sous QGIS 3 avec Pyhon. La question que je pose doit être la même sans QGis, dans un environnement Python seul.
    En résumé, j'utilise deux classes: une première est une fenêtre PyQt5 (class QWindow(QMainWindow)) demandant le nom d'une commune. La seconde est une classe class RechercheCommune(): recherchant cette commune dans le SIG QGis.
    Pardonnez-moi le programme qui n'est pas entièrement terminé.
    Mon problème est que la seconde classe (recherche commune) est lancée sans attendre le résultat de la classe précédente.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        mw = QWindow()                               # QWindow() est une classe
        print("après mw = QWindow()")
        communeRecherchee = mw.textbox.text()
        rc = RechercheCommune()                     # RechercheCommune() est une classe
        rc.rechercheCommune(communeRecherchee)
    Je pense que la solution est toute simple et qu'une commande doit être écrite pour que le programme attende le résultat des commandes antérieures avant de continuer.
    Le programme entier est le suivant:
    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
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    import sys
    from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QMenu, QPushButton, QLabel
    from PyQt5.QtGui import QIcon
    # from PyQt5.QtCore import pyqtSlot
     
    class QWindow(QMainWindow):
     
        def __init__(self):
            super().__init__()
            self.createMenusHorizontaux()
            self.initUI()
            self.createStatusBar()
     
        def initUI(self):
            self.modificationParametresWindow(200, 300, 400, 250, 'titre')
            self.modificationParametresToolTips()
     
            # création d'un bouton
            btn1 = self.createButton("sortie", self.width-125, self.height-30, "tooltip btn1", self.on_click)
            btn1.setToolTip('lg=120, haut=15, x=100, y=70, désactivé')
            btn1.resize(120,20)
            # btn1.clicked.connect(self.on_click)
     
            self.creationLabel ("<font color=#4400FF size='3'><b>Commune à rechercher:</b>", 10, 50, 300, 15)
            self.creationTextBox (150, 50, 150, 20)
     
            # self.getText()
            self.show()
     
        def modificationParametresWindow(self, x, y, l, h, titre):
            self.title = titre
            self.left = x
            self.top = y
            self.width = l
            self.height = h
            self.setWindowTitle(titre)
            self.setGeometry(self.left, self.top, self.width, self.height)
     
        def modificationParametresToolTips(self):
            # modification des paramètres des tooltips
            QToolTip.setFont(QFont('SansSerif', 9))                                                        # Cette méthode statique définit une police utilisée pour rendre les info-bulles.
            couleurFondToolTips = QToolTip.palette();
            couleurFondToolTips.setColor(QPalette.ToolTipBase,QColor("#FFdddd"));                                       # 
            couleurFondToolTips.setColor(QPalette.ToolTipText,QColor("#000000"));                                       # 
            QToolTip.setPalette(couleurFondToolTips)
     
        def createStatusBar(self):
            sb = QStatusBar()
            sb.setFixedHeight(18)
            self.setStatusBar(sb)
            self.statusBar().showMessage(self.tr("Ready"))
     
        def createMenusHorizontaux(self):
            # <a href="https://www.tutorialspoint.com/pyqt/qmenubar_qmenu_qaction_widgets.htm" target="_blank">https://www.tutorialspoint.com/pyqt/...on_widgets.htm</a>
            # la classe QMenuBar possède les méthodes suivantes : addMenu(), addAction(), setEnabled(), addSeperator(), Clear(), setShortcut(), setText(), setTitle(), 
            bar = self.menuBar()                                                                             # création d'un menu en haut d'écran; menuBar() est une méthode de la classe QMenuBar
            file = bar.addMenu("&File")
            file.addAction("New")
            save = QAction("Save",self)
            save.setShortcut("Ctrl+S")
            file.addAction(save)
            edit = file.addMenu("Edit")
            edit.addAction("copy")
            edit.addAction("paste")
            quit = QAction("Quit",self) 
            file.addAction(quit)
            file.triggered[QAction].connect(self.processtrigger)
            self.helpMenu = self.menuBar().addMenu(self.tr("&Help"))
    #        self.helpMenu.addAction(self.aboutAct)
    #        self.helpMenu.addAction(self.aboutQtAct)
            bar.setStyleSheet("QMenuBar::item { color: rgb(0, 0, 0); }")
     
        def createButton(self, text, x, y, toolTip, member=None):
            bouton = QPushButton(text, self)
            bouton.setToolTip(text)
            bouton.move(x,y)
            if (member != None) : bouton.clicked.connect(member);
            return bouton
     
        def creationLabel (self, text, x, y, l, h):
            self.libelle = QLabel(self)
            self.libelle.setText(text)
            #self.libelle.setAlignment(Qt.AlignCenter)
            self.libelle.move(x,y)
            #self.libelle.adjustSize()
            self.libelle.resize(300, 15)
     
        def getText(self):
            text, okPressed = QInputDialog.getText(self, "Get text","Your name:", QLineEdit.Normal, "")
            if okPressed and text != '':
                print(text)
     
        def creationTextBox (self, x, y, l, h):
            self.textbox = QLineEdit(self)
            self.textbox.move(x, y)
            self.textbox.resize(l,h)
     
     
        def processtrigger(self,q):
            print (q.text()+" is triggered")
            if (q.text() == "Quit"): self.close();
     
     
        @pyqtSlot()
        def on_click(self):
            print('PyQt5 button click')
            textboxValue = self.textbox.text()
            QMessageBox.question(self, 'Message - pythonspot.com', "You typed: " + textboxValue, QMessageBox.Ok, QMessageBox.Ok)
            # self.textbox.setText("")
            self.close()
    # fin class App(QWidget):
     
     
     
     
    class RechercheCommune():
        def __init__(self):
            self.nomFichierCommune = "D:/_Informatique/011_QGis/_QGis_donnees/_QGis_couches/_Administratif/communes.shp"
            self.aliasFichierCommune = "communes"
            self.chargementCouche()
            self.rechercheCommune("Ponteilla")
     
        def chargementCouche(self):
            # la couche est-elle déjà chargée?
            bCoucheCommunesDejaChargee = False
            for l in QgsProject.instance().mapLayers().values():                                            #iface.mapCanvas().layers():
                # print ("l.name()=", l.name(), l.source())
                # print(l.source())
                if (l.source().find("communes") >=0):
                    bCoucheCommunesDejaChargee = True
            if (bCoucheCommunesDejaChargee == False):
                # la couche n'est pas encore chargée
                # self.layerCommunes = iface.addVectorLayer(self.nomFichierCommune, self.aliasFichierCommune, "ogr")
                iface.addVectorLayer(self.nomFichierCommune, self.aliasFichierCommune, "ogr")
                print("couche communes créée")
            else:
                print("couche déjà présente")
                # self.layerCommunes = iface.setActiveLayer(QgsProject.instance().mapLayersByName('communes')[0])
     
            # la couche 'communes' est rendue active
            iface.setActiveLayer(QgsProject.instance().mapLayersByName('communes')[0])
            self.layerCommunes = iface.activeLayer()
            print("la couche 'communes' est rendue active")
            # type de symbologie de la couche
            renderer = self.layerCommunes.renderer()
            # print("Type:", renderer.type())                                                               # ['nullSymbol', 'singleSymbol', 'categorizedSymbol', 'graduatedSymbol', 'RuleRenderer', ...]
            # on change le remplissage des communes (jaune pâle, avec transparence)
            #symbols = self.layerCommunes.renderer().symbols(QgsRenderContext());                            # print(symbols)
            #symbols[0].setColor(QColor.fromRgb(0,255,0, 80))
            layerRenderer = self.layerCommunes.renderer()	# modif fond, et bordure
            mySymbol1 = QgsFillSymbol.createSimple({'color':'#00ff00', 'color_border':'#ff0000', 'width_border':'0.5'})
            layerRenderer.setSymbol (mySymbol1)
     
            self.layerCommunes.triggerRepaint()
     
        def rechercheCommune(self, nomCommune):
            # on parcours les 'features' de la couche pour y trouver la commune souhaitée
            print("...rechercheCommune...self.layerCommunes.name()=", self.layerCommunes.name())
            self.layerCommunes.selectByExpression("nom ILIKE \'" + nomCommune + "\'", QgsVectorLayer.SetSelection)
            iface.mapCanvas().zoomToSelected()
            scale = iface.mapCanvas().scale()
            scale = 120000  # int(int(scale)*2000)/1000
            iface.mapCanvas().zoomScale(scale)
     
     
     
     
     
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        mw = QWindow()
        sys.exit(app.exec_())
    else:
        mw = QWindow()
        print("après mw = QWindow()")
        communeRecherchee = mw.textbox.text()
        rc = RechercheCommune()
        # rc.rechercheCommune("Arles")
        rc.rechercheCommune(communeRecherchee)
    Merci pour votre aide

    Le copier/coller du programme a enlevé la tabulation primordiale pour python.
    Malheureusement, je ne connais pas le remède.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Citation Envoyé par BrDep Voir le message
    Mon problème est que la seconde classe (recherche commune) est lancée sans attendre le résultat de la classe précédente.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        mw = QWindow()                               # QWindow() est une classe
        print("après mw = QWindow()")
        communeRecherchee = mw.textbox.text()
        rc = RechercheCommune()                     # RechercheCommune() est une classe
        rc.rechercheCommune(communeRecherchee)
    Je pense que la solution est toute simple et qu'une commande doit être écrite pour que le programme attende le résultat des commandes antérieures avant de continuer.
    C'est le fonctionnement normal d'une interface graphique: mw = QWindow() démarre l'interface, l'instruction suivante app.exec_() démarre l'attente des évènements qui vont déclencher des callbacks et modifier l'état des objets de l'application.
    Dit autrement, l'instruction communeRecherchee = mw.textbox.text() s'exécute avant même que l'utilisateur ait pu faire quoi que ce soit.

    Difficile de modifier la mécanique d'un code sans comprendre comment elle est construite.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre habitué
    Homme Profil pro
    Ingénieur géologue
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur géologue
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Par défaut
    Merci pour vos aides.
    J'ai édulcoré le programme en éliminant les fonctions du SIG Qgis pour ne garder que du Python et le PyQt5.
    Le programme sera plus facilement compréhensible.
    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
     
    import sys
    from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QMenu, QPushButton, QLabel
     
    class QWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
     
        def initUI(self):
            self.modificationParametresWindow(200, 300, 400, 250, 'titre')
            self.creationBouton("ok", self.width-35, 50, 30, 20, "tooltip btn", self.on_click)
            self.creationLabel ("Commune à rechercher:", 10, 50, 300, 15)
            self.creationTextBox (150, 50, 150, 20)
            self.show()
     
        def modificationParametresWindow(self, x, y, l, h, titre):
            self.title = titre
            self.left = x
            self.top = y
            self.width = l
            self.height = h
            self.setWindowTitle(titre)
            self.setGeometry(self.left, self.top, self.width, self.height)
     
        def creationBouton(self, text, x, y, l, h, toolTip, member=None):
            self.bouton = QPushButton(text, self)
            self.bouton.setToolTip(text)
            self.bouton.move(x,y)
            self.bouton.resize(l, h)
            if (member != None) : self.bouton.clicked.connect(member);
     
        def creationLabel (self, text, x, y, l, h):
            self.libelle = QLabel(self)
            self.libelle.setText(text)
            self.libelle.move(x,y)
            self.libelle.resize(l, h)
     
        def creationTextBox (self, x, y, l, h):
            self.textbox = QLineEdit(self)
            self.textbox.move(x, y)
            self.textbox.resize(l,h)
     
        @pyqtSlot()
        def on_click(self):
            textboxValue = self.textbox.text()
            self.close()
    # fin class App(QWidget):
     
     
     
    class RechercheCommune():
        def __init__(self):
            print("classe RechercheCommune()")
     
        def rechercheCommune(self, nomCommune):
            print("nomCommune=", nomCommune)
    # fin class RechercheCommune()
     
     
     
     
    mw = QWindow()                          # instanciation de la classe
    communeRecherchee = mw.textbox.text()   # Récupération de la valeur entrée dans la TexBox de la classe QWindow
    rc = RechercheCommune()                 # instanciation de la classe
    rc.rechercheCommune(communeRecherchee)
    Donc mon problème est que les instructions rc = RechercheCommune() et rc.rechercheCommune(communeRecherchee) sont exécutées immédiatement et le nom de la commune entré dans la TexBox n'est pas pris en compte

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Citation Envoyé par BrDep Voir le message
    Donc mon problème est que les instructions rc = RechercheCommune() et rc.rechercheCommune(communeRecherchee) sont exécutées immédiatement et le nom de la commune entré dans la TexBox n'est pas pris en compte
    Sûr qu'avec la mise en forme, c'est bien plus lisible...

    Mais çà ne change pas le problème: vous voulez un fonctionnement séquentiel alors que le GUI vous impose un fonctionnement évènementiel: impossible!

    Comme c'est la base du fonctionnement de n'importe quel GUI, la solution sera d'ouvrir un tuto. et apprendre à programmer avec.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre habitué
    Homme Profil pro
    Ingénieur géologue
    Inscrit en
    Avril 2019
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur géologue
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 12
    Par défaut ok sur le principe
    Je comprends que vous essayez de faire trouver la solution par nous-mêmes.
    Je suis persuadé que la solution est très simple et que n'importe quel programmateur la trouverait...et la donnerait.
    D'après vous je dois compulser tous les tutos sur les GUI et trouver celui qui convient.
    Pour moi, l'aide serait plutôt de me donner la solution ou de me donner les éléments pour qu'en une heure je puisse résoudre ce problème qui me bloque et, si possible, de me donner les liens des meilleurs tutos.
    Souhaitez-moi bon courage pour les semaines à venir...
    Cordialement,

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Citation Envoyé par BrDep Voir le message
    Pour moi, l'aide serait plutôt de me donner la solution ou de me donner les éléments pour qu'en une heure je puisse résoudre ce problème qui me bloque
    Tel que vous posez le problème, il n'y a pas de solution.
    Pour le comprendre, il faut avoir appris comment fonctionne un GUI.

    Citation Envoyé par BrDep Voir le message
    et, si possible, de me donner les liens des meilleurs tutos.
    Un tuto. sera "bon" s'il prend en compte votre niveau, vos attentes,... et s'il est rédigé sous une forme suffisamment attractive pour vous donner envie d'apprendre (faire les exercices pour comprendre).
    Difficile de chercher pour vous dans la liste de ce remontera n'importe quel moteur de recherche.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par BrDep Voir le message
    J'ai édulcoré le programme en éliminant les fonctions du SIG Qgis pour ne garder que du Python et le PyQt5.
    Le programme sera plus facilement compréhensible.
    C'est un peu mieux. Toutefois il te faut aussi inclure PyQt5.QtCore pour pouvoir utiliser les pyqtSlot. Et comme il manque un QApplication, ton programme reste non testable. Or tu dois quand-même arriver ici avec un programme exécutable et que tu as testé toi-même.

    Accessoirement sais-tu qu'il y a une sous-partie du forum Python dédiée à PyQt ??? C'est pas que tu trouveras pas de réponse ici, mais t'auras plus de chances de trouver des connaisseurs PyQt là bas plutôt qu'ici.

    Citation Envoyé par BrDep Voir le message
    Donc mon problème est que les instructions rc = RechercheCommune() et rc.rechercheCommune(communeRecherchee) sont exécutées immédiatement et le nom de la commune entré dans la TexBox n'est pas pris en compte
    wiztricks a expliqué le souci. Tu ne peux pas demander du séquentiel dans une boucle évènementielle.
    Tu dois relier un signal de ta QLineEdit (je pense qu'un editingFinished serait un bon candidat) à un slot qui effectuera la recherche de ta commune et qui placera le résultat dans un QWidget adéquat.


    Citation Envoyé par BrDep Voir le message
    D'après vous je dois compulser tous les tutos sur les GUI et trouver celui qui convient.
    Ben c'est sûr que lire un tuto Qt serait un plus. Qt c'est pas un truc qu'on peut apprendre comme ça. Quand je m'y suis mis, j'ai carrément acheté un livre car à l'époque il n'y avait pas foule de tutos gratuits sur le net.

    Citation Envoyé par BrDep Voir le message
    Pour moi, l'aide serait plutôt de me donner la solution ou de me donner les éléments pour qu'en une heure je puisse résoudre ce problème qui me bloque et, si possible, de me donner les liens des meilleurs tutos.
    https://qt.developpez.com/tutoriels/. Ok ils sont pour Qt4 mais une fois qu'on a compris les bases, passer à Qt5 est assez facile (d'autant plus que Qt5 accepte l'ancienne syntaxe Qt4).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. Réponses: 2
    Dernier message: 30/07/2016, 18h38
  2. Réponses: 1
    Dernier message: 23/03/2012, 15h41
  3. Réponses: 8
    Dernier message: 12/01/2011, 19h00
  4. Réponses: 5
    Dernier message: 18/12/2009, 17h05
  5. Problème pour créer des objets de la même classe
    Par Dietzer dans le forum Code::Blocks
    Réponses: 1
    Dernier message: 25/06/2009, 17h01

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