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

GTK+ avec Python Discussion :

Pygtk-Glade lancement d'un MultiThread sans geler la fenêtre


Sujet :

GTK+ avec Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2010
    Messages : 4
    Par défaut Pygtk-Glade lancement d'un MultiThread sans geler la fenêtre
    Bonjour à tous,

    je m'explique, je suis entrain de m'amuser à faire un petit serveur (de tchat).

    Pour l'exemple j'ai créer une fenêtre glade avec un bouton et un TextBox (Je sait ... petite réminiscence VB je ferrai 2 ave patter et un ave Maria !!)

    Le bouton déclenche une fonction START_SRV() qui a son tour déclenche le Multi-Thread serveur qui va attendre les connexion des clients.

    le problème c'est que des que je presse mon bouton ma fenêtre gèle !!!

    Pour l'exemple j'ai retirer tout les test que j'avais fait avec gtk.gdk.Thread_init() mais je l'ai essayer dans tout les sens !!!

    Je comprend bien qu'il faudrait que ma GUI et mon serveur soit des Thread séparé mais dans la pratique ... je fait comment ? ... parce que j'ai beau tout essayer je vois bien qu'en fait je lance un Thread dans un Thread.

    je vous ai mi ci dessous :
    - le fichier qui démarre ma GUI
    - La fonction START-SRV() (Sans les import)
    - La class du serveur (Pardon s'il s'appel ThreadClient ... pas encore changé !! :-) )

    Si quelqu'un arrive a me dépanner c'est génial parce que la je suis vraiment dans les choux :-)

    Je vous remercie tous d'avance :-)

    P.S: Pardon pour la propreté du code et les 2 ou 3 truc bizarre mais suis débutant. :-)

    Code------

    Gui [TestThread.py]
    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
     
    import pygtk
    pygtk.require("2.0")
    import gtk
    import gtk.glade
    from ApiCtrlCommun import START_SRV
     
    class monprogramme:
        def __init__(self):
            self.widgets = gtk.Builder()
            self.widgets.add_from_file('test.glade')
            self.widgets.connect_signals(self)    
     
        def autoConnectb(self):
            eventHandlers = {}
            for (itemName,value) in self.__class__.__dict__.items(): 
                if callable(value) and itemName.startswith('gtk_'):  
                    eventHandlers[itemName[4:]] = getattr(self,itemName) 
            self.widgets.signal_autoconnect(eventHandlers)
     
        def delete(self, source=None, event=None):
            gtk.main_quit()
     
        def on_button1_clicked(self, source=None, event=None):
            START_SRV("localhost",40000)
            return True 
     
    if __name__ == '__main__':
        app = monprogramme()
        gtk.main()
    START_SRV [ApiCtrlCommun.py]
    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
     
    def START_SRV(HOST,PORT):
            mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            myThreadClient=ThreadClient
            try:
                mySocket.bind((HOST, PORT))
            except socket.error:
                print "La liaison du socket à l'adresse choisie a échoué."
                sys.exit()
            print "Serveur prêt, en attente de requêtes ..."
            mySocket.listen(5)
            # Attente et prise en charge des connexions demandées par les clients :
            conn_client = {}                 # dictionnaire des connexions clients
            while 1:
                connexion, adresse = mySocket.accept()
                # Créer un nouvel objet thread pour gérer la connexion :
                th = myThreadClient(connexion,conn_client)
                th.start()
                print th
                # Mémoriser la connexion dans le dictionnaire :
                it = th.getName()        # identifiant du thread
                conn_client[it] = connexion
                print "Client %s connecté, adresse IP %s, port %s." %\
                       (it, adresse[0], adresse[1])
                # Dialogue avec le client :
                connexion.send("Vous êtes connecté. Envoyez vos messages.")
    Thread Serveur [ApiNetwork.py]
    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
     
    import threading
    class ThreadClient(threading.Thread):
        #dérivation d'un objet thread pour gérer la connexion avec un client
        def __init__(self, conn ,client_return):
            threading.Thread.__init__(self)
            self.connexion = conn
            self.client_ret=client_return
            self.str_ret = "Serveur ok"
            return self.str_ret
        def run(self):
            # Dialogue avec le client :
            nom = self.getName()        # Chaque thread possède un nom
            while 1:
                msgClient = self.connexion.recv(1024)
                if msgClient.upper() == "FIN" or msgClient =="":
                    break
                message = "%s> %s" % (nom, msgClient)
                print message
                # Faire suivre le message à tous les autres clients :
                for cle in self.client_ret:
                    if cle != nom:      # ne pas le renvoyer à l'émetteur
                        self.client_ret[cle].send(message)
                        #conn_client[cle].send(message)
                        # Fermeture de la connexion :
            self.connexion.close()      # couper la connexion côté serveur
            del self.client_ret[nom]
            #del conn_client[nom]        # supprimer son entrée dans le dictionnaire
            print "Client %s déconnecté." % nom
        # Le thread se termine ici

  2. #2
    Membre chevronné
    Inscrit en
    Janvier 2007
    Messages
    329
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 329
    Par défaut
    Salut,

    Dans ton fichier ApiNetwork.py, il faut faire un "gobject.threads_init()" pour initialiser correctement un thread avec pygtk :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    import threading
    import gobject
    gobject.threads_init()
    ...
    Regarde la FAQ pour plus de précisions : http://faq.pygtk.org/
    (En particulier les points 20.1 et 20.6)

    Je peux difficilement t'en dire plus, je maîtrise pas trop les threads...



    -

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2010
    Messages : 4
    Par défaut Merci
    Décidément c'est la deuxième!!! lol ... ben encore merci ... encore une réponse de ta part et c'est l'apéro !!!

    En fait je me suis répondu tout seul ... regarde la jolie boucle sans fin (while 1 du fichier [ApiCtrlCommun.py]

    donc j'ai résolut mon problème comme ça ...

    1-------------------------------------------
    Lancement de l'interface j'ai ajouter un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    gtk.gdk.threads_init()
    ...
    gtk.gdk.threads_enter()
    gtk.main()
    gtk.gdk.threads_leave()
    1-------------------------------------------

    2-------------------------------------------
    Transformation de ma fonction START_SRV en class TH_START_SRV hérité de threading.Thread

    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
     
    class TH_START_SRV(threading.Thread):
     
        def __init__(self, HOST,PORT):
            threading.Thread.__init__(self)
            self.HOST = HOST
            self.PORT = PORT
            self.Terminated = False
     
        def run(self):
            mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            myThreadClient=ThreadClient
            try:
                mySocket.bind((self.HOST, self.PORT))
            except socket.error:
                print "La liaison du socket à l'adresse choisie a échoué."
                sys.exit()
            print "Serveur prêt, en attente de requêtes ..."
            mySocket.listen(5)
            # Attente et prise en charge des connexions demandées par les clients :
            conn_client = {}                 # dictionnaire des connexions clients
            while 1:
                connexion, adresse = mySocket.accept()
                # Créer un nouvel objet thread pour gérer la connexion :
                th = myThreadClient(connexion,conn_client)
                th.start()
                print th
                # Mémoriser la connexion dans le dictionnaire :
                it = th.getName()        # identifiant du thread
                conn_client[it] = connexion
                print "Client %s connecté, adresse IP %s, port %s." %\
                       (it, adresse[0], adresse[1])
                # Dialogue avec le client :
                connexion.send("Vous êtes connecté. Envoyez vos messages.")
    Je n'ai pas encore géré l'arrêt du thread

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    def on_button1_clicked(self, source=None, event=None):
            a=TH_START_SRV("localhost",40000)
            a.start()
            return True
    2-------------------------------------------

    et miracle ... ça fonctionne.

    Par-contre il y a des chance que pour la compatibilités Win32 je remplace les instructions d'ouverture de thread gtk.gdk.init(),Enter() et leave()

    Par gobject.threads_init()

    Je conseil d'ailleurs a tous la lecture de ces super articles d'on tu m'as donné le liens :

    http://faq.pygtk.org/ (En particulier les points 20.1 et 20.6)

    Pour terminer je dirait que while + pygtk = Thread obligatoire

    Encore merci.

  4. #4
    Membre chevronné
    Inscrit en
    Janvier 2007
    Messages
    329
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 329
    Par défaut
    Citation Envoyé par rcrivelliNET Voir le message
    Décidément c'est la deuxième!!! lol ... ben encore merci ... encore une réponse de ta part et c'est l'apéro !!!
    Bon, j'attends ta prochaine question !

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

Discussions similaires

  1. Lancement des commandes maven sans avoir internet
    Par dodi84 dans le forum Maven
    Réponses: 4
    Dernier message: 15/09/2009, 12h39
  2. pygtk + glade sous windows
    Par jvander59 dans le forum GTK+ avec Python
    Réponses: 1
    Dernier message: 22/08/2009, 12h21
  3. Pb PyGtk + Glade + pdock
    Par Radec dans le forum GTK+ avec Python
    Réponses: 0
    Dernier message: 25/03/2009, 17h41
  4. Réponses: 3
    Dernier message: 02/10/2006, 22h51

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