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

GUI Python Discussion :

Problème d'interface graphique


Sujet :

GUI Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 14
    Par défaut Problème d'interface graphique
    Bonjour, à tous!

    Je viens vers vous car je n'arrive pas à résoudre un problème.

    Je souhaiterais créer une interface graphique constituée d'un bouton quitté et d'un canevas qui affiche un défillement d'images se trouvant dans le même dossier (toutes les secondes, via time.sleep(1) ).

    Les images étant du JPG, j'utilise PIL mais pour la fenêtre j'aurrais vraiment une préférence pour wxpython ou encore PyQt parce que Tkinter... c moyen niveau qualité graphique.

    Une autre petite question : Pour les captures d'écran avec PIL, je peux choisir le format d'enregistrement via l'extension mais peut t-on choisir la qualité ou la résolution? (je voudrais une inférieure)

    Voila, j'espère avoir de vos nouvelles rapidement, Merci BCP!!!!

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    Bonjour,
    C'est facilement réalisable avec wxpython. (avec pyqt aussi, mais je suis moins à l'aise).
    Il ne faut pas utiliser time.sleep(1) car cela bloque le mainloop (à moins d'utiliser un thread).
    il existe wx.Timer prévu à cet effet.
    Voici un exemple:
    Je ne sais pas exactement quelle traitement tu veux effectuer avec pil, ici je redimensionne simplement l'image. Si tu ne veux pas faire de traitement Pil est inutile ici.

    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
     
    # -*- coding: utf-8 -*-
     
    import wx, os
    from PIL import Image
     
    class MyFrame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None)
            self.pathImg = "./"
            #liste des images
            self.listPathImg = self.getImgsPath()
            #pour récupérer l'image en cours d'affichage
            self.photoEnCours = 0
            sizer = wx.BoxSizer(wx.VERTICAL)
            #taille des images
            self.widthImg = 800
            self.heightImg = 600
     
            btnQuit = wx.Button(self, -1, "quitter")
            self.canvas = wx.StaticBitmap(self, -1, wx.EmptyBitmap(self.widthImg, self.heightImg))
     
            sizer.Add(self.canvas)
            sizer.Add(btnQuit)
            self.SetSizerAndFit(sizer)
     
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)
            self.Bind(wx.EVT_BUTTON, self.onQuit, btnQuit)
            self.timer.Start(1000)
     
            self.Show()
     
        #retourne la liste des *.jpg présent dans le dossier
        def getImgsPath(self):
            listPath = []
            for img in os.listdir(self.pathImg):
                if os.path.splitext(img)[1].lower() == ".jpg":
                    listPath.append(os.path.join(self.pathImg, img))
            return listPath
     
        #redimmentionne l'image et retourne un wx.Bitmap
        def resize(self, pathImg):
            im = Image.open(pathImg)
            im.thumbnail((self.widthImg, self.heightImg), Image.ANTIALIAS)
     
            image = wx.EmptyImage(im.size[0], im.size[1])
            image.SetData(im.convert('RGB').tostring())
     
            return image.ConvertToBitmap()
     
     
        #méthode appelée toutes les seconde, et affiche la nouvelle image
        def onTimer(self, event):
            if self.photoEnCours == len(self.listPathImg):
                self.photoEnCours = 0
            self.canvas.SetBitmap(self.resize(self.listPathImg[self.photoEnCours]))
            self.photoEnCours += 1
     
        def onQuit(self, event):
            self.timer.Stop()
            self.Destroy()        
     
     
    app = wx.App(0)
    MyFrame()
    app.MainLoop()

  3. #3
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 14
    Par défaut
    Ah merci beaucoup niko, je bloquait surtout sur le défilement de l'image : je savait en faire apparaître une mais pas en changer. Ton script correspond très bien à ce que je cherche, merci bcp!!!

    Par contre, je ne l'aurais pas fait de cette manière, est-t-il possible d'avoir un thread de traitement (script, fichier, etc....) et un thread qui ne gère que l'interface? Parce que je ne comprend pas pourquoi tu as mi le loop à la fin et non dans une fonction.

    Perso j'utilise cette méthode pour les threads :

    monthread1=threading.Thread(None, mafonction1, None)
    monthread2=threading.Thread(None, mafonction2, None)
    monthread1.start()
    monthread2.start()

    Pour une utilisation directe ca ne me pose pas de problème mais si je le compile, une fois la fin du programme atteinte il se termine même si des threads sont encore ouverts, je suis donc obligé de mettre une boucle pour autoriser la fermeture.

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    heu...
    c'est bizarre comme façon de faire (enfin je trouve).

    Je ne vois pas l'intérêt de mettre 2 threads.
    Le coté graphique est ton programme principale, donc pas besoin de le mettre dans un thread. D'où le mainloop en dehors d'une fonction ou d'un thread (ça commence à être tordu sinon). ça fait une boucle infini qui vérifie les évènements, c'est déjà une sorte de thread.
    Ensuite le wx.Timer est aussi un thread, c'est une juste une façon plus pratique dans ton cas que les thread standard de python.

    Pour une utilisation directe ca ne me pose pas de problème mais si je le compile
    Qu'appels tu "compile"?

    je suis donc obligé de mettre une boucle pour autoriser la fermeture
    Avec le wx.Timer je pense pas que tu aies ce problème(je suis vraiment pas sûr). As tu essayé?
    Si c'est le cas, comme tu le dis, il suffira de mettre une boucle dans le onQuit pour vérifier que la fonction est bien terminer.

    Dans l'exemple que j'ai donnée, il faut juste faire attention que le traitement ne dur pas plus longtemps que l'appel du Timer (1000ms). C'est déjà pas mal pour le traitement d'une photo.

    De plus c'est souvent compliqué d'utiliser les thread avec wxpython, car ça rentre en conflit avec le mainloop.

    Ensuite, j'ai peut-être pas bien compris ce que tu veux faire. Je pourrais t'en dire plus, si tu me convaincs que wx.Timer ne fonctionne dans ton cas .

  5. #5
    Membre habitué
    Inscrit en
    Mars 2010
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 14
    Par défaut
    Accroche toi xD!

    Alors pour les threads, j'ai toujours pris l'habitude de séparer les fonctions de mes programmes dans des threads différents, par exemple :

    En ce moment je suis sur un gros projet avec un gestion client serveur. Mon programme a quasiment 20 fonctions chacune dans un thread différent. Et les 20 ne sont pour qu'un client... après il faut les multiplier par le nombre de connexion....

    Cependant, pour que certaines fonctions puissent fonctionner, d'autre doivent être arrété c'est pour cela que j'utilise beaucoup de thread + un autre pour la gestion de ces derniers.

    Fonctionnement du thread de gestion:

    Le contrôle se fait par variable global (3 variables pour chaques thread) :
    1 - Thread demarré
    2 - Contrôle du bon fonctionnement périodique. (détection du changement de valeur indique que le thread fonctionne toujours)
    3 - Demande d'arret (l'arret c'est le thread concerné qui l'éxécute en testant la valeur de la variable)

    Il y a 2 autres variables mais celles-ci sont plus pour optimiser le tout.

    Donc pour revenir, oui j'ai besoin que l'interface soit dans un thread car je pourrais avoir besoin d'en créer des copies pour chaque client (par ex une fenêtre s'ouvre avec des info a chaque fois qu'un client se connecte).

    De cette facon, j'ai juste a démarrer le même thread pour chaque client avec un argument qui identifie le numéro du client.

    Il y a aussi un problème pour les connexions réseau : mon serveur doit pouvoir gérer un grand nombre de connexion et pour chacune d'entre elles, 20 fonctions utilisent le réseau... Ya vraiment intérêt à ce qu'il y ai un contrôle de thread parce que si tout ce petit monde envoi ses infos en même temps.... Pour l'instant j'ai pas encore trouvé d'autre solutions mais elle me convient très bien.

    Pour "compiler" je veux en réalité dire en faire un exécutable portable. Et donc le problème est dans la cas où mon programme est "compilé", si jamais il atteint la fin du prog, il s'arrette (même si d'autre thread son encore en cours....). Pour résoudre a ca, je met mon contrôle de thread dans le corps du programme et comme il est dans une boucle (normal vu qu'il est censé contrôler en permanence), le programme n'arrive jamais à la fin.

    Pour le wx.Timer, je n'est pas essayé puisque selon ma méthode de gestion avec les thread, il ne bloque que le thread concerné et non les autres, ce qui est doublement mieu.

    Je me suis apercu très récement que les méthodes des autre programmeur ne me convenait pas. C'est peut-être la pensé de tout les programmeurs.... Tout ca pour dire que cette facon d'utiliser les threads me permet une bonne gestion des taches à effectuer en même temps et de facon séquentielle même si cela peut paraîte étrange!

    ++

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    Bon d'accord.
    Et ça fonctionne comme tu le souhaites alors?

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

Discussions similaires

  1. Problème d'interface graphique
    Par nicogigo dans le forum Général Python
    Réponses: 6
    Dernier message: 19/03/2010, 06h27
  2. Problème compilation interface graphique
    Par jotiko dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 06/11/2008, 14h48
  3. problèmes d'interface graphiques
    Par Taaroa dans le forum JWS
    Réponses: 10
    Dernier message: 11/08/2008, 10h55
  4. Réponses: 11
    Dernier message: 21/04/2008, 12h23
  5. Réponses: 2
    Dernier message: 29/03/2004, 18h29

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