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

Tkinter Python Discussion :

Mettre en pause l'exécution du programme sans bloquer la mise à jour du canvas [Python 3.X]


Sujet :

Tkinter Python

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Mars 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut Mettre en pause l'exécution du programme sans bloquer la mise à jour du canvas
    Bonjour,

    La fonction suivante met à jour mon interface graphique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def majgraphique(canvas,plateau):
        for i in range(8):
            for j in range(8):
                if plateau[j][i]!=0:
                    if plateau[j][i]==1:
                        couleur = "black"
                    else:
                        couleur = "white"
                    canvas.create_oval(80*i+2,80*j+2,80*i+78,80*j+78,fill=couleur)

    Elle est appelée par la fonction click après jouer_coup (coup de l'humain) et coup_aleatoire (coup de l'ordinateur).
    Je voudrais :
    - coup humain
    - mise à jour graphique
    - une ou deux secondes de pause
    - coup d' ordi
    - mise à jour graphisme

    Quand je rajoute un time.sleep(2) APRES l'appel de majgraphique dans mon programme, la pause s'effectue en réalité avant la mise à jour, et les deux mises à jour humain et ordinateur s'effectuent en suivant et je n'ai pas le temps de voir le coup de l'humain.
    J'ai essayé de glisser mon time.sleep(2) à plusieurs endroits, mais j'ai toujours le même problème. Mon programme pause 2 secondes, puis les deux coups s'affichent en suivant (simultanément en apparence).
    J'ai essayé de remplacer le sleep par un while portant sur time.time(), mais cela revient au même.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def click(event):
        global joueur
        x,y = event.x//80,event.y//80
        if est_possible(joueur,x,y):
            jouer_coup(joueur,x,y)
            majgraphique(canvas,plateau)
            # je rajoute ici le time.sleep(2) mais le graphisme n'est pas actualisé avant la pause.
            joueur = 3 - joueur
            coup_aleatoire(joueur)
            majgraphique(canvas,plateau)
            joueur = 3 - joueur
    Quelqu'un pourrait-il m'expliquer pourquoi mon code ne fonctionne pas comme espéré et me proposer une solution ?
    Merci d'avance.

  2. #2
    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 778
    Points
    36 778
    Par défaut
    Salut,

    Citation Envoyé par galigori Voir le message
    Quelqu'un pourrait-il m'expliquer pourquoi mon code ne fonctionne pas comme espéré et me proposer une solution ?
    click(event) n'est pas une fonction mais un "callback"... qui doit se terminer le plus rapidement possible pour que le GUI puisse mettre à jour l'affichage rapidement. Ce qui exclu l'usage de time.sleep qui va tout bloquer.
    La solution est de comprendre comment fonctionne un GUI et de structurer votre code en conséquence.
    Et vous avez la chance d'avoir de bons tuto. qui expliquent bien tout çà.


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

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Mars 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    Merci pour cette réponse rapide !

    Je comprends maintenant pourquoi mon programme ne fonctionne pas, mais toujours pas comment régler mon problème... bon, je vais chercher.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Mars 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    J'ai essayé une autre solution, mais elle ne fonctionne pas non plus.

    Je n'ai mis que le jeu du joueur dans le callback :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def click(event):
        global joueur
        x,y = event.x//80,event.y//80
        if est_possible(joueur,x,y):
            jouer_coup(joueur,x,y)
            majgraphique(canvas,plateau)
            joueur = 3 - joueur
    Et j'ai voulu gérer le jeu de l'ordinateur à part :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def jeuordi():
        global joueur
        while coups_possibles(joueur) != []:
            if (joueur == 1 and jnoir.get() == "ordinateur") or (joueur == 2 and jblanc.get() == "ordinateur"):
                coup_aleatoire(joueur)
                majgraphique(canvas,plateau)
                joueur = 3 - joueur
    Je pensais pouvoir faire tourner en simultané ma détection de click et ma fonction jeuordi en la lançant avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fenetre.after(500,jeuordi)
    , mais cela ne marche toujours pas.
    Comment dois-je procéder ?

  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 778
    Points
    36 778
    Par défaut
    Citation Envoyé par galigori Voir le message
    Comment dois-je procéder ?
    wouah... vous avez ouvert le tuto. tkinter depuis hier et déjà vous vous sentez suffisamment à l'aise avec toutes les implications que çà a sur le codage des applications?

    Essayez de réfléchir à ce qu'impliquent "apprendre" et "comprendre". Quelque part, c'est un processus mémorisera des concepts et créera des liens entre différentes régions du cerveau. Comme çà travaille à la vitesse de la chimie (i.e. lentement et plutôt quand on dort), il faut être patient et avoir la chance que le tuto. présente cet ensemble de concepts dans un ordre optimal vis à vis de l'organisation de votre cerveau à l'instant t.
    Ce qui a peu de chance d'arriver car nous sommes tous différents... Et vous pourrez constater par vous même que la relecture du même tuto. dans une semaine vous fera découvrir des choses que vous n'aviez pas encore "vue".

    Donnez vous le temps d'apprendre... d'autant que ces concepts seront utiles pour travailler avec d'autres GUI (ou d'autres bibliothèques qui utilisent ce style de programmation) et que la complexité naturelle d'un GUI vous permettra de mieux comprendre (plus tard) l'intérêt de la POO (i.e. structurer votre code en class).

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

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Mars 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    Bonsoir,

    C'est très gentil de répondre, mais vous ne m'aidez pas beaucoup...! C'est peut-être qu'il n'y a peut-être pas de solution simple (sans faire de la vraie POO) ?
    C'est dommage parce que mon code fonctionne parfaitement sauf que je ne parviens pas à glisser une pause entre le coup du joueur et le coup de l'ordi.
    Je vais travailler sur Python avec des étudiants qui débutent en Python et la POO n'est pas au programme...

    Merci quand même.

  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 778
    Points
    36 778
    Par défaut
    Citation Envoyé par galigori Voir le message
    C'est dommage parce que mon code fonctionne parfaitement sauf que je ne parviens pas à glisser une pause entre le coup du joueur et le coup de l'ordi.
    A la base, le GUI écoute et réagit aux évènements qui ont été programmés.
    Donc si vous voulez faire une pause (quelle drôle d'idée mais pourquoi pas) vous avez (au moins) 5 options:
    - neutraliser temporairement les bindings...
    - ajouter un flag global qui fera retourner immédiatement les callbacks associés,
    - créer un Toplevel (une boîte de dialogue "modale" qui pourrait afficher un progressbar) qui s'autodétruit dans n secondes pendant que le code principal attend via .wait_window
    - jouer avec des appels imbriqués à .mainloop()
    - éviter les appels à .mainloop pour gérer tout çà "à la main".

    Citation Envoyé par galigori Voir le message
    C'est très gentil de répondre, mais vous ne m'aidez pas beaucoup...! C'est peut-être qu'il n'y a peut-être pas de solution simple (sans faire de la vraie POO) ?
    Les 3 premières solutions sont du niveau débutant tkinter (celui qui a lu et un peu pratiqué le tuto. doit pouvoir les comprendre et les réaliser pas forcément y penser), les deux dernières sont un peu plus avancées (il faut savoir ce qu'il y a sous le capot pour les utiliser sans que çà vous pète dans les doigts).
    Mais vous devrez retenir celle qui sera la plus cohérente avec ce que vous voulez apprendre à vos élèves...
    Pas facile de choisir à votre place laquelle explorer et retenir.

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

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Mars 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    Je vais examiner les différentes pistes que vous proposez. Merci pour vos réponses.

    Si je veux faire une pause, c'est parce que je ne vois pas le coup du joueur. La mise à jour de l'interface graphique ne s'effectue pas après le coup du joueur, mais à la sortie du callback, après le coup de l'ordinateur.
    Plutôt que de faire une pause dans le callback, l'idéal serait en fait de quitter le callback, de faire la MAJ du canvas, puis de déclencher le coup de l'ordinateur... mais je ne sais pas comment faire ça avec mes connaissances actuelles.
    Comme vous dites, il faut que je bosse un peu plus sur tkinter.

    En attendant de savoir faire ce que je voulais, j'ai finalement contourné le problème en déclenchant le coup de l'ordinateur avec un autre click...

  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 778
    Points
    36 778
    Par défaut
    Citation Envoyé par galigori Voir le message
    Plutôt que de faire une pause dans le callback, l'idéal serait en fait de quitter le callback, de faire la MAJ du canvas, puis de déclencher le coup de l'ordinateur... mais je ne sais pas comment faire ça avec mes connaissances actuelles.
    à priori, c'est ce que pourrait faire fenetre.after(500, jeuordi).
    Le soucis, c'est que je ne vois pas ce qui va empêcher le joueur d'être "actif" pendant ce temps là.
    L'autre soucis est que pour vous çà ne fonctionne pas.

    Si vous voulez progresser, il faut vous sortir la tête du jeu et vous concentrer à l'organisation des enchaînements.
    Partez d'un exemple comme:
    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
    import tkinter as tk
    from tkinter.constants import *
     
    def computer_play():
        frame['bg'] = 'blue'
        btn['state'] = NORMAL
     
    def do_play():
        frame['bg'] = 'green'
        root.after(500, computer_play)
        btn['state'] = DISABLED
     
    root = tk.Tk()
     
    frame = tk.Frame(root, width=300, height=300, bg='white')
    frame.pack()
     
    btn = tk.Button(root, text='joue', command=do_play)
    btn.pack()
     
    tk.mainloop()
    C'est sûr que ce n'est pas représentatif de votre code, çà montre juste qu'en simplifiant et en se concentrant sur l'effet recherché, on va pouvoir travailler sur la mécanique puis structurer le reste autour.

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

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Mars 2009
    Messages : 33
    Points : 22
    Points
    22
    Par défaut
    C'est exactement ce que je cherchais !
    Ce n'est pas tant pour mon programme actuel (ou le déclenchement par click convient aussi) que pour apprendre à gérer ce type de situation.
    Merci beaucoup !

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

Discussions similaires

  1. [Débutant] Mettre en pause l'exécution d'un programme
    Par Moux29 dans le forum MATLAB
    Réponses: 2
    Dernier message: 08/04/2016, 10h35
  2. Réponses: 2
    Dernier message: 16/01/2012, 14h08
  3. Réponses: 8
    Dernier message: 04/08/2011, 10h17
  4. problème d'exécution de programme sans delphi installé
    Par bouha2008 dans le forum Débuter
    Réponses: 13
    Dernier message: 09/06/2009, 16h08
  5. Réponses: 5
    Dernier message: 14/01/2007, 18h12

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