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

  1. #1
    Membre confirmé

    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
    Points : 503
    Points
    503
    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.
    Le temps ronge l'amour comme l'acide.

  2. #2
    Membre confirmé

    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
    Points : 503
    Points
    503
    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.
    Le temps ronge l'amour comme l'acide.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    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 confirmé

    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
    Points : 503
    Points
    503
    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.
    Le temps ronge l'amour comme l'acide.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    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 confirmé

    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
    Points : 503
    Points
    503
    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
    Le temps ronge l'amour comme l'acide.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par bistouille Voir le message
    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.
    Pour ce qui est du mélange avec les threads, pygame n'est pas mieux que tkinter: c'est toujours une mainloop qui gère un multi-tache "coopératif" à mélanger avec un multi-tache pré-emptif.

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

  8. #8
    Membre confirmé

    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
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Ah

    Donc il reste quoi en bibliothèque graphique pour faire un jeu de ce type ?
    Qu'est-ce qui serait le plus conseillé ?

    Je m'étais rapidement penché sur pygtk, mais je n'avais pas vu de conteneur comme les canvas sur tkinter, à moins que j'ai loupé quelque chose.
    Le temps ronge l'amour comme l'acide.

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par bistouille Voir le message
    Donc il reste quoi en bibliothèque graphique pour faire un jeu de ce type ?
    Qu'est-ce qui serait le plus conseillé ?
    Je ne connais pas de bibliothèques graphiques utilisables avec des threads qui fonctionnent sans qu'on se pose de questions. De plus, le multi-tache coopératif qui est réalisé par la bibliothèque graphique permet de se passer des threads dans la plupart des cas.

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

  10. #10
    Membre confirmé

    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
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Merci de ces informations.
    Le temps ronge l'amour comme l'acide.

  11. #11
    Membre confirmé

    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
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Salut,

    Toujours en train de m'acharner sur le gel de mes fenêtres, je me suis rendu compte paradoxalement qu'il n'y avait pas de problème lorsque la main n'était pas au joueur, j'entends par là que si j'ouvre la fenêtre lorsque c'est l'ia qui joue ou encore dans le tirage au sort, la fenêtre s'ouvre instantanément.

    J'en suis arrivé à la conclusion que c'est le gestionnaire d'événements qui provoque le freeze, après plein de test de tout part, je suis arrivé par pur hasard à quelque chose qui fonctionne en mettant un simple ... print dans le while du run, là je comprends pas.

    Ca fait comme si le fait d'être en " inactivité ", enfin tourner sans rien exécuter, cela engendrait un freeze, mais alors pourquoi seulement une fenêtre esclave gèle et pas la totalité de tkinter, donc la fenêtre principale également ?
    Le temps ronge l'amour comme l'acide.

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