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 :

Afficher une image à l'interieur d'un QThread


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 19
    Par défaut Afficher une image à l'interieur d'un QThread
    Bonjour,
    Je cherche à afficher une image quelconque sur mon IHM pyQt à partir d'un Qthread depuis un certain temps déjà, sans succès. Connaitriez vous un exemple ou un lien sur le sujet? J'imagine que le besoin n'est pas nouveau mais je n'ai rien trouvé sur ce point.
    Merci beaucoup pour toute aide eventuelle!!
    cordialement
    Elmanu

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    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 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    J'ai bien peur que ce ne soit pas possible: à ma connaissance, on ne doit pas toucher à la partie graphique dans un thread.

    Par contre, un QThread peut envoyer un message (emit(...)) à la partie principale du programme, et c'est elle qui affichera.

  3. #3
    Expert confirmé

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Citation Envoyé par elmanu20 Voir le message
    Bonjour,
    Je cherche à afficher une image quelconque sur mon IHM pyQt
    Salut,

    Tu veux dire une image de fond sur toute l'Ihm ou sur un widget particulier ?

    De toute manière, comme le dit Tyrtamos, ton thread devra envoyer un signal et l'image sera transmise au serveur graphique à partir de la boucle principal du programme (main-thread), sinon plantage garantit.

  4. #4
    Membre averti
    Inscrit en
    Juillet 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 19
    Par défaut
    Salut
    Merci pour vos retours. Je me suis mal exprimé je cherche à afficher une image dans un widget bien particulier tel qu'un label avec un mécanisme de SIGNAL/slot comme le preconise tyrtamos.
    J'ai quand même réussi par trouver un exemple qui le fait mais je n'arrive toujours pas à l'appliquer:
    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
     
    from PyQt4 import QtCore, QtGui, uic
    import time,sys
    import threading
    from PyQt4.QtGui import QApplication, QDialog, QListWidgetItem, QListWidget, QIcon
    from PyQt4.Qt import *
     
    (loadUserInterface, QWidget) = uic.loadUiType('pyemission.ui')
     
     
    class emission_calibration(QThread):
        def __init__(self, parent=None):
    #        super(emission_calibration, self).__init__(parent=parent)
            QThread.__init__(self, parent)
            self.exiting=False
     
        def render(self):
            self.run()
     
        def measure(self):
            global window
            image ="notick.png"
            self.emit(SIGNAL("output(QLabel, QString)"), window.ui.tick1, image )
            window.ui.status.setText("Please wait for measure....")
     
        def run(self):
            applied_level = self.measure()
            return
     
        def __del__(self):
            self.exiting = True
            self.wait()
     
    class Main(QWidget):
        """constructor"""
        def __init__(self, parent = None):
            global directory,dir_state,gene,defaultbase,IMP_path,base_selected
            global base,gene,window
            QWidget.__init__(self, parent)
            self.ui = loadUserInterface()
            self.ui.setupUi(self)
            self.threadPool=[]
            self.thread = emission_calibration()
            # Connect the Buttons
     
     
            self.connect(self.thread, SIGNAL("finished()"), self.updateUi)
            self.connect(self.thread, SIGNAL("terminated()"), self.updateUi)
            QtCore.QObject.connect(self.ui.calibration,QtCore.SIGNAL("clicked()"),self.calibration)
            self.connect(self.thread, SIGNAL("output(QLabel, QString)"), self.addImage)
            dir_state = ''
            directory = ''
     
     
        def addImage(self, label, image):
            pixmap = QPixmap(label.size())
            pixmap.load(image)
            label.setPixmap(pixmap)
     
        def calibration(self):
            self.ui.calibration.setEnabled(False)
            self.thread.render()
     
     
        def updateUi(self):
            self.ui.calibration.setEnabled(True)
     
    def main():
        global window,debug
        app = QtGui.QApplication(sys.argv)
        window = Main()
        window.show()
        sys.exit(app.exec_())
     
    if __name__ == "__main__":
        main()
    Voila pyemission.ui est juste une fenêtre conçue avec Qtcreator contenant un simple label tick1. Je ne comprends pas pourquoi lorsque je remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
         def render(self):
            self.run()
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        def render(self):
            self.start()
    je n'affiche plus mon image dans le label tick1.
    Pouvez vous m'aider à localiser l'erreur?? D'avance merci infiniment

  5. #5
    Expert confirmé

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Trop de choses vraiment pas bien dans ton code.

    J'ai remplacé (ou effacé) des lignes de ton script et j'en ai mis les explications en commentaire.

    Je n'ai pas testé, bien sur, ce plaisir t'appartiens.
    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
     
    from PyQt4 import QtCore, QtGui, uic
    import time,sys
    import threading
     
    # Tous ces import servent-ils à quelque chose ?
    from PyQt4.QtGui import QApplication, QDialog, QListWidgetItem, QListWidget, QIcon
    from PyQt4.Qt import *
     
    (loadUserInterface, QWidget) = uic.loadUiType('pyemission.ui')
     
    class emission_calibration(QThread):
        beginMeasure = QtCore.pyqtSignal()     # Il faut créer ton signal
        def __init__(self, parent=None):
            QThread.__init__(self, parent)
            self.exiting=False
     
        def render(self):
            self.run()
     
        def measure(self):
            # global à proscrire ici
            self.beginMeasure.emit()    # On se contente simplement d'émettre
            # On suppose qu'ici vient la tâche du thread ...
     
        def run(self):
            # Pas sur de ce que tu veux faire, à quoi sert applied_level ?
            applied_level = self.measure()
            return
     
        def __del__(self):
            self.exiting = True
            self.wait()
     
    class Main(object):     # Pourquoi QWidget ?
        """constructor"""
        def __init__(self, parent = None):
            # global à proscrire ici
            self.ui = loadUserInterface()
            self.ui.setupUi(self)
            self.threadPool=[]
            self.thread = emission_calibration()
     
            # Il ne faut plus utiliser de signal old-style !
            self.thread.finished.connect(self.updateUi)
            self.thread.terminated.connect(self.updateUi)
            self.ui.calibration.clicked.connect(self.calibration)
            self.thread.beginMeasure.connect(self.addImage)
     
            self.dir_state = ''     # Il faut référencer ces deux noms à l'instance
            self.directory = ''     # sinon ils ne servent à rien
     
        def addImage(self):
            image = "notick.png"
            pixmap = QPixmap(label.size())
            pixmap.load(image)
            self.ui.tick1.setPixmap(pixmap)
            self.ui.status.setText("Please wait for measure....")
     
        def calibration(self):
            self.ui.calibration.setEnabled(False)
            self.thread.render()
     
        def updateUi(self):
            self.ui.calibration.setEnabled(True)
     
    def main():
        # global inutiles
        app = QtGui.QApplication(sys.argv)
        window = Main()
        window.show()
        sys.exit(app.exec_())
     
    if __name__ == "__main__":
        main()

  6. #6
    Membre averti
    Inscrit en
    Juillet 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 19
    Par défaut Merci!!!
    Salut,
    Merci infiniment pour cette correction! Du coup j'ai plein de questions à te poser mais je vais essayer de limiter au maximum
    1°) Ok pour tout les trucs inutiles: j'avais éliminé un max de choses pour rendre mon code le plus court possible mais j'ai été un peu vite et j'en ai laissé un peu partout, désolé.
    2°) la classe QWidget m'est utile pour charger mon fichier .ui issu de Qtcreator
    3°)pour les "connect": là je découvre totalement cette écriture que je n'avais jamais vue (désolé à nouveau) les exemples que j'ai trouvé étaient donc trop vieux Peux tu me donner un lien vers une doc sur ce sujet?
    4°)je comptais mettre à jour une série de pictos sur mon ihm. Là avec ce que tu me proposes il faut un signal/slot par picto ce qui est assez lourd je trouve. Y a t'il moyen de garder en argument de addImage le widget et le nom de l'image à afficher.
    Merci encore
    Elmanu

  7. #7
    Expert confirmé

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Citation Envoyé par elmanu20 Voir le message
    2°) la classe QWidget m'est utile pour charger mon fichier .ui issu de Qtcreator
    Non, pas du tout nécessaire, uic.loadUiType retourne l'instance de ta fenêtre, pas besoin de QWidget pour l'héberger.

    3°)pour les "connect": là je découvre totalement cette écriture que je n'avais jamais vue (désolé à nouveau) les exemples que j'ai trouvé étaient donc trop vieux Peux tu me donner un lien vers une doc sur ce sujet?
    http://pyqt.sourceforge.net/Docs/PyQ...als_slots.html

    4°)je comptais mettre à jour une série de pictos sur mon ihm. Là avec ce que tu me proposes il faut un signal/slot par picto ce qui est assez lourd je trouve. Y a t'il moyen de garder en argument de addImage le widget et le nom de l'image à afficher.
    On peut, bien sur, placer des arguments avec les pyqtSignal() mais il s'agit en général de données que seule la classe émettant le signal connaisse. Ici il s'agit d'images connues au niveau global de ton programme et de widgets qui n'ont, eux non plus, rien à voir avec le thread. Ta classe main() elle, par contre possède référence de la main window.

    Si le même signal doit être émit pour des raisons différentes place alors cette raison en argument. Ce peut être un simple entier.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class emission_calibration(QThread):
        beginMeasure = QtCore.pyqtSignal(int)
        ...
            self.beginMeasure.emit(1)    # ou 2 ou 3 ...
     
        ....
        def addImage(self, reason):
            if reason == 1:
                do something
            if reason == 2:
                ...
    Tu gardes ainsi tout contrôle de l'interface dans ta classe Main(), si tu veux introduire des changements, cela restera dans cette même classe.

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

Discussions similaires

  1. [VB.NET] afficher une image stockée dans une table
    Par matonfire dans le forum ASP.NET
    Réponses: 4
    Dernier message: 19/03/2004, 11h21
  2. Afficher une image JPG qui se trouve dans une bdd
    Par Harry dans le forum Bases de données
    Réponses: 6
    Dernier message: 27/02/2004, 10h51
  3. Charger et afficher une image jpg avec les mfc
    Par glop - pas glop dans le forum MFC
    Réponses: 3
    Dernier message: 11/02/2004, 18h59
  4. Réponses: 2
    Dernier message: 04/02/2004, 22h32
  5. Afficher une image sans passer par les textures
    Par Black_Daimond dans le forum DirectX
    Réponses: 3
    Dernier message: 09/05/2003, 19h13

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