Page 1 sur 1

Python, Tkinter et affichage

MessagePosté: Mercredi 05 Janvier 2011, 22:38
par rebouxo
J'ai commis le code suivant (en espérant que les tabulations seront conservées). Ce programme fonctionne fonctionne plutôt bien (C'est la première fois que je fais des fenêtres). Et j'espère ne pas avoir commis trop d'horreur dans les classes et autres bidules de la POO.
But du programme : simuler le lancer d'un grand nombre de fois le jet de deux dès à 6 faces.
Problème : Les effectifs de mes tirages apparaissent après tous les tirages, je voudrais que le tableau se remplisse au fur et à mesure éventuellement en mettant une petite pause entre deux affichages, si c'est vraiment trop rapide. Cela ne me paraît pas d'une grande complexité, mais je ne trouve rien sur internet et je dois dire que je trouve la POO assez lourdingue. Bon de tout façon, avec la POO ou sans, je ne trouve pas comment indiquer ça à Python. Je ne pense pas que cela soit possible en ligne de commande (ou alors j'ai point trouvé) et c'est pour cela que je me suis lancer la dedans. Bon cela doit être possible, puisque j'ai un exemple de code qui le fait, mais impossible d'adapter mon code.

Code: Tout sélectionner
# /usr/bin/python
# -*- coding:latin-1 -*-
def tirages() :
    c = random.randint(1,6)
    d = random.randint(1,6)
    n=c+d
    for j in range(2,13) :
        if n==j : s[j]=s[j]+1
    return s


class Fenetre(object) :
    def __init__(self):
        """Constructeur de la fenêtre principale"""
        self.root=Tk()
        self.root.title("Simulation de lancer de deux dés")
        # Un autre texte
        Label(self.root,text='Entrer un nombre entier').\
                       grid(row = 1,column=1)
        # Un champs de saisie
        self.entre=Entry(self.root)
        self.entre.grid(row=1,column=2)
        # Les résultats
        Label(self.root,text="Nombre : ").grid(row=1,column=3)
        Label(self.root,text="Effectif : ").grid(row=2,column=3)
        for j in range(2,13):
            Label(self.root,text=j).grid(row=1,column=j+3)
            Label(self.root,text='0').grid(row=2,column=j+3)

        # Bouton lancer
        self.lancer=Button(self.root,text='Lancer',command=self.lanceTirage).\
                     grid(row=3,column=1)
        # Bouton quitter
        self.bouton=Button(self.root,text='Quitter',command=self.root.quit).\
                     grid(row=3,column=2)
        self.root.mainloop()
    # Fin de la construction de l'objet fenêtre

    def lanceTirage(self) :
            "Récupère le nombre rentre et lance le tirage"
            self.valeur=self.entre.get() # on récupère la chaine de caractère
            N=int(self.valeur)               # on la transforme en entier
            for i in range(1,N+1):
                tirages()
            for i in range(2,13):
                Label(self.root,text=s[i]).grid(row=2,column=i+3)
   
        # Fin du tirage

####### MAIN #####

if __name__ == '__main__' :
    import random
    from Tkinter import *
    s=[0]*13
    f=Fenetre()


Merci pour tout début de commencement d'idée.
Olivier

Re: Python, Tkinter et affichage

MessagePosté: Mercredi 05 Janvier 2011, 23:58
par Arnaud
rebouxo a écrit:Problème : Les effectifs de mes tirages apparaissent après tous les tirages, je voudrais que le tableau se remplisse au fur et à mesure éventuellement en mettant une petite pause entre deux affichages, si c'est vraiment trop rapide.


J'ai du mal à cerner ce que tu veux.

Un truc genre :
"Tirages précédents : ...."
"Tirage : ...."
"Effectifs de tous les tirages : ...."

?

Re: Python, Tkinter et affichage

MessagePosté: Jeudi 06 Janvier 2011, 00:18
par projetmbc
Bonsoir,
il est tard et je ne connais pas trop Tkinter. Une réponse arrivera sûrement plus rapidement sur ce forum, j'y traîne.

Ceci étant, on ne voit pas trop ce que tu veux faire. Peux-tu préciser ta question ?

Re: Python, Tkinter et affichage

MessagePosté: Jeudi 06 Janvier 2011, 08:15
par rebouxo
projetmbc a écrit:Bonsoir,
il est tard et je ne connais pas trop Tkinter. Une réponse arrivera sûrement plus rapidement sur ce forum, j'y traîne.

Ceci étant, on ne voit pas trop ce que tu veux faire. Peux-tu préciser ta question ?


Zut et damned, moi qui croyait avoir été clair :D .
Je veux juste que les effectifs soient actualisés au fur et à mesure. Actuellement n'apparaissent que les effectifs finaux (au bout de N lancers). Je voudrais qu'à chaque lancer qui donne la somme i le compteur s[i] soit incrémenté (ça c'est fait) mais surtout que l'affichage soit modifié.

Au départ on a :
2 3 4 5 6 ....
0 0 0 0 0 ...
Après un lancer je voudrais avoir
2 3 4 5 6...
0 0 1 0 0 ...
Après deux lancers
2 3 4 5 6...
0 0 1 0 1...

Bref je voudrais réécrire par dessus ma ligne effectif et que ces modifications soient visibles.

En espérant être plus clair.

Olivier

Re: Python, Tkinter et affichage

MessagePosté: Jeudi 06 Janvier 2011, 11:56
par projetmbc
Bpnjour.

Maintenant que la question est clarifiée, voici une proposition avec une pause pour éviter des "scintillements" lors des changements.

Code: Tout sélectionner
# /usr/bin/python
# -*- coding:latin-1 -*-

# SOURCE : http://forum.mathematex.net/logiciels-mathematiques-f7/python-tkinter-et-affichage-t12314.html

import random
import time
from Tkinter import *

def tirages(s) :
    c = random.randint(1,6)
    d = random.randint(1,6)   
    n = c+d
   
    for j in range(2,13) :
        if n == j :
            s[j] = s[j]+1
    return s


class Fenetre(object) :
    def __init__(self):
        """Constructeur de la fenêtre principale"""
        self.root=Tk()
        self.root.title(u"Simulation de lancer de deux dés")
       
        # Un autre texte
        Label(self.root,
              text='Entrer un nombre entier').grid(row = 1, column = 1)

        # Un champs de saisie
        self.entre=Entry(self.root)
        self.entre.grid(row = 1, column = 2)

        # Les résultats
        Label(self.root,
              text="Nombre : ").grid(row = 1, column = 3)
        Label(self.root,
              text="Effectif : ").grid(row = 2, column = 3)
       
        for j in range(2,13):
            Label(self.root,
                  text=j).grid(row = 1, column = j+3)
            Label(self.root,
                  text='0').grid(row = 2, column = j+3)

        # Bouton lancer
        self.lancer=Button(self.root,
                           text='Lancer',
                           command=self.lanceTirage).grid(row = 3, column = 1)
        # Bouton quitter
        self.bouton=Button(self.root,
                           text='Quitter',
                           command=self.root.quit).grid(row = 3, column = 2)
       
        self.root.mainloop()

    def lanceTirage(self) :
        "Récupère le nombre rentre et lance le tirage"
        self.valeur=self.entre.get() # on récupère la chaine de caractère
       
        N = int(self.valeur)               # on la transforme en entier

        s = [0]*13
        for i in range(1, N+1):
            if i != 1:
                time.sleep(0.1)

            tirages(s)
           
            for i in range(2, 13):
                Label(self.root,
                      text = s[i]).grid(row = 2, column = i+3)
           
            self.root.update() # On force la mise à jour sinon elle se fera tout à la fin

####### MAIN #####

if __name__ == '__main__' :   
    f = Fenetre()

La difficulté technique est de penser que la mise à jour est automatique. Ce n'est pas le cas, il faut la forcer via self.root.update(). Ceci doit sûrement provenir du fait que Tkinter attend que tous les traitements soient faits pour faire une mise à jour visuelle.

Si je trouve la motivation j'essaierais de comparer cela avec le comportement de pyqt.

Re: Python, Tkinter et affichage

MessagePosté: Jeudi 06 Janvier 2011, 12:09
par Arnaud
Presque la même solution, car l'import de time n'est pas nécessaire :

Code: Tout sélectionner
# -*- coding: utf-8 -*-
# /usr/bin/python
# -*- coding:utf-8 -*-

def tirages() :
    global t
    c = random.randint(1,6)
    d = random.randint(1,6)
    n=c+d
    for j in range(2,13) :
        if n==j : t[j]=t[j]+1
    return t


class Fenetre(object) :
    def __init__(self):
        """Constructeur de la fenêtre principale"""
        self.root=Tk()
        self.root.title("Simulation de lancer de deux dés")
        # Un autre texte
        Label(self.root,text='Entrer un nombre entier').\
                       grid(row = 1,column=1)
        # Un champs de saisie
        self.entre=Entry(self.root)
        self.entre.grid(row=1,column=2)
        # Les résultats
        Label(self.root,text="Nombre : ").grid(row=1,column=3)
        Label(self.root,text="Effectif : ").grid(row=2,column=3)
        for j in range(2,13):
            Label(self.root,text=j).grid(row=1,column=j+3)
            Label(self.root,text='0').grid(row=2,column=j+3)

        # Bouton lancer
        self.lancer=Button(self.root,text='Lancer',command=self.lanceTirage).\
                     grid(row=3,column=1)
        # Bouton quitter
        self.bouton=Button(self.root,text='Quitter',command=self.root.quit).\
                     grid(row=3,column=2)
        self.root.mainloop()
    # Fin de la construction de l'objet fenêtre

    def lanceTirage(self) :
            "Récupère le nombre rentre et lance le tirage"
            global t
            self.valeur=self.entre.get() # on récupère la chaine de caractère
            N=int(self.valeur)               # on la transforme en entier   
            t=[0]*13
            for i in range(1,N+1):
                tirages()
            print s, t
            for i in range(2,13):
                while s[i] < t[i]:
                    s[i] += 1
                    self.root.after(500, Label(self.root,text=s[i]).grid(row=2,column=i+3))
                    self.root.update()
   
        # Fin du tirage

####### MAIN #####

if __name__ == '__main__' :
    import random
    from Tkinter import *
    s=[0]*13
    f=Fenetre()


Màj toutes les demi-secondes, si tu veux autre chose, il suffit de modifier le 500.

Re: Python, Tkinter et affichage

MessagePosté: Jeudi 06 Janvier 2011, 12:27
par rebouxo
Bon ben pour quelques choses d'aussi simples, pourquoi qu'on trouve rien chez google.

Merci à tous les deux.

Re: Python, Tkinter et affichage

MessagePosté: Jeudi 06 Janvier 2011, 12:44
par projetmbc
J'ai utilisé Google car je ne connais pas Tkinter (je vais utiliser PyQt pour mon projet).