Pb changement d'image chaque seconde : lancer dé

Fermé
bubu - Modifié le 1 mars 2018 à 16:03
 bubu - 2 mars 2018 à 14:00
Bonjour, mon programme ne fonctionne pas comme je le veux :
au lieu d'afficher 10 images séparées d'1 seconde, il attend 10 secondes et affiche les 10 images les unes sur les autres.
Je ne veux pas utiliser de boutons, je veux que le changement se fasse tout seul à chaque seconde.
faut-il utiliser command pour qu'il l'affiche à chaque tour ? faut-il recolorer tout en ivory à chaque tour de boucle par un rectangle au lieu du can.delete ?
merci de votre intérêt.


from tkinter import *
from time import *
from random import *

def disque(x, y, r, coul ='black'):
    "tracé d'un disque de centre (x,y) et de rayon r"
    can.create_oval(x-r, y-r, x+r, y+r, fill=coul)

def dé_1():
    "dessiner un 1 sur le dé"
    disque(80, 80, 20, 'red')
   
def dé_2():
    "dessiner un 2 sur le dé"
    disque(30, 30, 20, 'red')
    disque(130, 130, 20, 'red')

def dé_3():
    "dessiner un 3 sur le dé"
    dé_1()
    dé_2()

def dé_4():
    "dessiner un 4 sur le dé"
    dé_2()
    disque(130, 30, 20, 'red')
    disque(30, 130, 20, 'red')

def dé_5():
    "dessiner un 5 sur le dé"
    dé_3()
    disque(130, 30, 20, 'red')
    disque(30, 130, 20, 'red')

def dé_6():
    "dessiner un 6 sur le dé"
    dé_4()
    disque(30, 80, 20, 'red')
    disque(130, 80, 20, 'red')

##### Programme principal : ############
fen = Tk()
can = Canvas(fen, width =160, height =160, bg ='ivory')
can.pack( )

for nbParties in range(10):
    can.delete(ALL)     # Effacer d'abord tout dessin préexistant :
    resDe=randrange(1,7)
    if resDe==1:
        dé_1()

    elif resDe==2:
        dé_2()

    elif resDe==3:
        dé_3()

    elif resDe==4:
        dé_4()

    elif resDe==5:
        dé_5()

    else :
        dé_6()


    sleep(1)
#fen.mainloop()



A voir également:

1 réponse

Bonjour.

Il ne faut pas utiliser sleep, le sleep gèle toute l'interface.

Il faut utiliser la méthode after de tkinter, le 1er argument est le temps en millisecondes, le second, la fonction à appeler, et optionnelement les arguments devant être passés à la fonction.

for nbParties in range(10):
     # Effacer d'abord tout dessin préexistant :
    resDe=randrange(1,7)
    if resDe==1:
        de = dé_1

    elif resDe==2:
        de = dé_2

    elif resDe==3:
        de = dé_3

    elif resDe==4:
        de = dé_4

    elif resDe==5:
        de = dé_5

    else :
        de = dé_6
    fen.after(1000 * nbParties, can.delete, ALL)
    fen.after(1000 * nbParties, de)


Toutes tes fonctions dé_x devraient en fait être regroupées en une seule à laquelle tu passeras le numéro du dé à afficher.
0
ça marche effectivement très bien, mais j'ai une interrogation :
la variable 'de' est bien une fonction ?
Si j'ai bien compris, fen.after(1000 * nbParties, can.delete, ALL) lance quasi immédiatement 10 can delete, espacés d'une seconde et juste après chaque, on lance l'affichage de la 'valeur' de la fonction "de" à ce moment là de la boucle. En fait on programme les 10 effacement et affichage, avec une temporisation.
0
critou > bubu
2 mars 2018 à 11:14
Oui, en gros, c'est ça, la boucle for est parcourue quasi instantanément, dans la boucle on demande à tkinter de lancer la fonction de() à 1 seconde d'intervalle, ce qui fait qu'au dernier tour de la boucle, le after lancera la dernière fonction 9 secondes plus tard.

Oui, la variable de est une fonction qui a la même référence à la fonction qu'on lui a assigné, c'est pour cela que je t'ai suggéré de créer une fonction plus générale.

Un exemple :

from tkinter import *
from random import *

def de(numero):
    # positions des disques (lignes et colonnes), True représente un disque
    pos = (
        ((False, False, False), (False, True, False), (False, False, False)), # numéro 1
        ((True, False, False), (False, False, False), (False, False, True)), # numéro 2
        ((True, False, False), (False, True, False), (False, False, True)),
        ((True, False, True), (False, False, False), (True, False, True)),
        ((True, False, True), (False, True, False), (True, False, True)),
        ((True, False, True), (True, False, True), (True, False, True)), # numéro 6
    )
    i = 0
    for ligne in pos[numero-1]:
        for colonne in ligne:
            if colonne:
                # On affiche le disque
                can.itemconfigure(disques[i], state=NORMAL)
            i += 1


##### Programme principal : ############
fen = Tk()
can = Canvas(fen, width =210, height =210, bg ='ivory')
can.pack()


# Création de tous les disques cachés du dé.
# On ajoute un tag global à tous les disque (disque)
disques = [] # Sert à enregistrer les ids des disques.
y = 10
for ligne in range(3):
    x = 10
    for colonne in range(3):
        i = can.create_oval(x, y, x+40, y+40, fill='red', tag='disque', state=HIDDEN)
        # Enregistrement de l'identifiant du disque sur le canvas
        disques.append(i)
        x += 70
    y += 70

for nbParties in range(10):
    resDe=randrange(1,7)
    # On cache tous les disques à l'aide du tag disque.
    fen.after(1000 * nbParties, can.itemconfigure, 'disque', dict(state=HIDDEN))
    # On appelle la fonction de, en lui fournissant le numero du de
    fen.after(1050 * nbParties, de, resDe)

fen.mainloop() 
0
il va me falloir du temps pour tenter de comprendre cet exemple. Merci de vos réponses
0