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 :

Thread combiné avec tkinter


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut Thread combiné avec tkinter
    Bonjour,

    Je suis assez novice en python, afin de m'exercer avec ce langage, j'ai développé un jeu basique 2d en tour par tour, joueur contre ordinateur avec tkinter, ce jeu fonctionne très bien, du moins tant que le jeu est mené à son terme.

    Mon problème se situe comme le titre l'indique avec la gestion du thread, chose que je ne maîtrise pas du tout et qui semble difficile à appréhender, malgré tous les exemples trouvés sur le web, ici avec les events, ailleurs avec sys.trace, je n'arrive toujours pas à redémarrer le thread lorsqu'on souhaite redémarrer la partie lors d'une partie déjà en cours.
    Soit je me retrouve avec de multiples thread, donc plusieurs duplication d'objets tkinter, soit dans des portions de codes bloquants (boucle, sleep)

    De plus j'ai également un problème similaire lorsque j'ouvre une fenêtre esclave (options de jeu, scores, etc...) de la fenêtre principale (root), cela provoque un freeze graphique et un temps de latence important, qui est aussi provoqué par le thread puisque lorsque le jeu n'est pas en cours d'exécution, ie : thread non lancé, il n'y a pas ce problème.

    Ma question est donc comment remédier à ces problèmes que je n'arrive pas à résoudre au vu de mon inexpérience avec ceux-ci ?
    Si vous connaissez une simple appli similaire pouvant me servir d'exemple, je suis preneur.

    L'architecture de mon application est simple, j'ai une classe principale, celle-ci lance une seconde classe qui hérite de Thread, celle-ci instancie donc les 2 classes (joueur, ordinateur) et s'occupe de lancer tour par tour une même méthode de ces 2 objets.

    Merci.

  2. #2
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Je suppose que personne n'est en mesure de me répondre, sans plus d'infos concernant ce que j'ai fait.

    Comme je ne voulais pas trop mettre de code à rallonge dans mon sujet, je joins une archive de tous les fichiers de mon application, ce sera plus simple.

    Soyez indulgent, tout est loin d'être au point, et surtout rien n'est encore fini, j'en suis conscient, la priorité avant de continuer cette application est de résoudre ce problème de thread.

    A noter que si vous testez sur windows, je ne suis pas sûr que la fermeture de la fenêtre kill bien le thread en cours, sur linux c'est ok avec pthread_kill.
    Le fichier à lancer est donc bataille_navale.py (python3.4, et tk >= 8.6)


    L'archive des fichiers :
    Pièce jointe 206490

    Merci à ceux qui prendront le temps de tester, et de regarder un peu mon code.

  3. #3
    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 bistouille Voir le message
    Merci à ceux qui prendront le temps de tester, et de regarder un peu mon code.
    Apparemment vous savez programmer.
    Vous devriez donc pouvoir réduire votre problème au cas d'utilisation que vous faites entre threads et tkinter et résumer cela en quelques dizaines de lignes de code.
    note: je dis çà parce que pas grand monde va prendre le temps de debugger votre code.

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

  4. #4
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Merci du conseil, mais en fait, je ne sais pas trop quelles parties de mon code exposer, car je n'ai pas vraiment d'indice pour savoir d'où proviennent mes problèmes.

    J'expose tout de même en un gros résumé en quelques lignes de code.


    Classe de l'appli principale :

    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
    class Bn(tk.Frame) :
     
        def __init__(self, joueur='physique', parent=None) :
     
            # Définitons des attributs
     
            # Définition des 3 cadres enfants
            # Dont le cadre supérieur contenant le menu, par lequel sera ouvert
            # les fenêtres des options (préférences, scores, stats)
     
            self.initialisation()
     
        def redemarrer(self) : 
            if self.phase :
                if isinstance(self.phase, Controleur) :
                    print('Redémarrage !')
                    self.phase.stop()
     
            # Suppression des éléments tkinter du canevas et de la frame
            self.cadreJeu.vider()
            self.zi.vider()
            #del(self.phase)
     
            self.initialisation()
     
        def initialisation(self) :
            # Démarrage de la 1ère phase du jeu (disposition des bateaux sur la grille)
     
        def lancer(self) :
            # Seconde phase du jeu (déroulement de la partie)
            # Lancement et déroulement de la partie
            da = DisposerAleatoirement(self.__params.nbc, self.__bateaux)
            j1 = {'nom':'Vous', 'bateaux':self.casesBateaux}
            j2 = {'nom':self.nomEnnemi, 'bateaux':da.positions()}
     
            self.cadreJeu.vider()
            self.zi.vider()
            del(self.phase)
            self.phase = Controleur(self, self.matrice, j1, j2)
     
     
        # Ouverture d'une fenêtre score
        # me pose problème, car engendre un bug graphique (freeze), et un temps d'affichage 
        # de la fenêtre important (latence)
        def scores(self, titre) :
            if MenuScores not in MenuScores.instances :
                scores = MenuScores(self.menuOptions, titre)
                scores.afficher()
    Classe chargée d'instancier le joueur, et l'ordinateur (joueur virtuel)
    Et d'appeler à tour de rôle une même méthode de ces 2 objets.
    Trame est une classe gérant des objets graphiques tkinter.

    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
    class Controleur(Trame, threading.Thread) :
     
        def __init__(self, parent, matrice, joueurPhysique, joueurVirtuel) :
     
            # Déclaration des divers attributs
     
            Trame.__init__(self, matrice, self.params, self.theme)
     
            # Création des éléments tkinter
     
            # Création des 2 joueurs
     
            # Instanciation et lancement du thread
            threading.Thread.__init__(self)
            self.__stopEvent = threading.Event()
            self.start()
     
        def tirerAuSort(self) :
            # Code du tirage
     
        def retour(self, message, coup, fin=False) :
            # Méthode utilisée par les objets joueurs
            # Afin d'envoyer les infos nécessaires
            # au controleur
     
        def run(self) :
            while not self.__stopEvent.isSet() :
                self.__stopEvent.wait(0.5)
                if not self.initJeu :
                    try :
                        self.tirerAuSort()
                    except AttributeError :
                        self.etatJeu = False
     
                while self.etatJeu :
                    if self.tourFini :
                        self.tourFini = False
                        try :
                            self.tour.activer()
                        except AttributeError :
                            self.etatJeu = False
            print('Fini')
     
        def stop(self) :
            print('arrêt demandé')
     
            # Si je détruit les objets joueurs après le while
            # Ils ne sont jamais détruits
            try :
                del(self.j1)
            except :
                pass
     
            try :
                del(self.j2)
            except :
                pass
     
            # L'action n'est pas interrompue, et une erreur est engendrée (accès à une méthode de j1/j2)
            # Donc une exception doit être attrapée dans le run        
     
            self.etatJeu = False
            while not self.__stopEvent.isSet() :
                print('...')
                self.__stopEvent.wait(0.05)
                self.__stopEvent.set()
    En l'état, ça fonctionne à peu près, mais l'arrêt du thread n'est pas immédiat, il prend environ 3/4 secondes
    Et j'ai toujours ce problème de freeze lors de l'ouverture d'une fenêtre du menu du jeu, et là, je ne sais pas du tout ce qui le provoque.

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

    A défaut de cas d'utilisation, on peut disserter.

    tk est multithreads et tkinter fait de son mieux pour être utilisable depuis plusieurs threads, mais çà ne fonctionne pas si bien que çà (faites des recherches sur Google).
    C'est ce qui explique peut être les "freeze".

    Un GUI comme tkinter permet de faire du multi-tâche coopératif: chaque tache doit se terminer assez vite pour ne pas bloquer le GUI. Le threading n'est indispensable que pour gérer les taches "non coopératives" i.e. dont on ne sait trop quand elle se terminent (et bloquant le GUI pour une durée indéfinie: des calculs un peu long, un accès réseau,...): c'est le système qui va suspendre le "thread courant" pour donner le CPU a un autre thread en attente.

    Dit autrement, mixer threads et GUI c'est compliqué mais nécessaire que dans des cas particuliers.

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

  6. #6
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    D'accord, je comprends que c'est ardu, vu le temps que j'ai perdu a essayé de tout faire fonctionner au poil sans pouvoir y arriver.

    Du coup je vais sans doute recommencer mais en utilisant pygame que je ne connais pas du tout, bon même si je n'ai pas mené à son terme ce jeu, au moins j'ai pu découvrir un peu toutes les facettes de tkinter et ça m'a permis au fil de la programmation de ce jeu python de mieux en mieux le connaître.

    Merci de ta réponse

Discussions similaires

  1. [Tkinter] Un petit souçis d'event avec Tkinter
    Par fire.stone dans le forum Tkinter
    Réponses: 4
    Dernier message: 29/10/2005, 20h56
  2. CSS : Flottement de tableaux combiné avec du texte justifié
    Par Nullos Oracle dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 14/10/2005, 02h10
  3. Thread--> problème avec ThreadProc
    Par stof dans le forum MFC
    Réponses: 33
    Dernier message: 08/06/2005, 13h47
  4. [Thread] Probleme avec mon Timer
    Par Nico66 dans le forum EDT/SwingWorker
    Réponses: 10
    Dernier message: 02/06/2005, 17h10
  5. Thread probs avec WaitFor()
    Par pixelrock dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/11/2002, 09h40

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