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 :

Débutant : modifications dynamiques dans une fenetre Tkinter


Sujet :

Tkinter Python

  1. #1
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut Débutant : modifications dynamiques dans une fenetre Tkinter
    Bonsoir,

    Je débute depuis quelques jours en python.
    J'ai réalisé un petit programme d'essai qui fonctionne très bien dans le shell. Il demande le nom du 'joueur' et lui fait faire des additions aléatoires de 2 valeurs comprises entre 0 et 10. Ne rien entrer comme réponse fait quitter le programme.

    voici le code :
    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
    #!/usr/bin/ python
    # -*- coding: utf-8 -*-
     
    # Programme permettant de s'entrainer au calcul mental
    # en générant aléatoirement des opérations simples à
    # résoudre
     
    from random import randrange
     
    def addition(min,max):
        max += 1 # inclure la borne supérieure pour la randomisation
        a = randrange(min, max)
        b = randrange(min, max)
        reponse = raw_input ('{0} + {1} = '.format (str(a),str(b)))
        resultat = str(a + b)
        if reponse == resultat :
            print( 'Tout bon !!' )
        elif reponse == '':
    	print( 'Fini de jouer !! Va ranger ta chambre {0} !!'.format(nom) )
        else:
            print( 'NON {0} !!! la bonne réponse était {1}'.format(nom,resultat) )
        return reponse
     
    nom = raw_input("Bonjour, comment t'appelles-tu ? ")
    boucle = True
    while boucle:
        if addition(0,10) == '':
    	boucle = False
    Je souhaite le porter dans une interface graphique (sous Tkinter puisque je poste ici), et là c'est la cata...

    j'ai grand mal à me représenter le fonctionnement des objets / classes (j'ai lu entièrement le swaroop et feuilleté le Swinnen, mais tout est loin d'être encore clair)

    voici mon code d'essai qui évidemment doit contenir des énormités... Merci d'avance de toute remarque utile voire d'exemple fonctionnel qui me permettrait de comprendre comment cela fonctionne.

    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
    #!/usr/bin/ python
    # -*- coding: utf-8 -*-
     
    # Programme permettant de s'entrainer au calcul mental
    # en générant aléatoirement des opérations simples à
    # résoudre
     
    from Tkinter import *
    from random import randrange
     
    class Application(Tk):
        def __init__(self):
            Tk.__init__(self)
    	question = Label(self)
    	question.pack()
    	saisie = Entry(self)
    	saisie.pack()
    	message = Label(self)
    	message.pack()
     
            self.mainloop()
     
    app = Application()
     
    # intervalle de randomisation
    mini, maxi = 0, 10 # les nombres aléatoire seront tirés dans l'intervalle [0,10]
    maxi += 1 # inclure la borne supérieure pour la randomisation
     
    while True:
        # initialisation des variables
        a = randrange(mini, maxi)
        b = randrange(mini, maxi)
        questionText = str('{0} + {1} = '.format (str(a),str(b)))
        resultat = str(a + b)
        reponse = None
        # affichage de l'opération à effectuer au niveau du Label 'question'
        app.question.config(text = questionText)
        app.question.update()
     
        # saisie de la réponse
        print(repr(reponse))
        reponse= str(app.saisie.get())
        # test de la réponse et affichage d'un message adapté au niveau du Label 'message'
        if reponse == resultat :
    	app.message.config(text= "bien joué ! on essaye encore") # afficher un message de félicitation
        elif reponse == 'stop':
    	app.message.config(text= "D'accord, à bientot") # afficher un message d'adieu
    	app.quit()
    	break
        else:
    	app.message.config(text= "NON !!! la bonne réponse était {0}".format(resultat)) # afficher un message d'erreur avec le résultat
    Cordialement,

    Spirzouf

  2. #2
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Pas trop de casse en fait.

    Je te laisse tester cela :

    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
    67
     
    #!/usr/bin/ python
    # -*- coding: utf-8 -*-
     
    # Programme permettant de s'entrainer au calcul mental
    # en générant aléatoirement des opérations simples à
    # résoudre
     
    from Tkinter import *
    from random import randrange
     
    # intervalle de randomisation
    mini, maxi = 0, 10 # les nombres aléatoire seront tirés dans l'intervalle [0,10]
    maxi += 1 # inclure la borne supérieure pour la randomisation
     
    class Application(Tk):
        def __init__(self):
            Tk.__init__(self)
    	self.question = Label(self)
    	self.question.pack()
    	self.saisie = Entry(self)
    	self.saisie.pack()
    	self.message = Label(self)
    	self.message.pack()
            self.saisie.bind('<Return>', self.monevent) # La touche Entrer lance la procédure monevent
            # http://www.pythonware.com/library/tkinter/introduction/events-and-bindings.htm
            # Premiere initialisation de self.question
            self.initvariable()
     
        def initvariable(self): # L'utilisation de self permet d'utiliser initvariable en tant que procédure et non 
            # initialisation des variables
            a = randrange(mini, maxi)
            b = randrange(mini, maxi)
            self.questionText = str('{0} + {1} = '.format (str(a),str(b)))
            self.resultat = str(a + b)
            # reponse = None Inutile
            self.question.config(text = self.questionText) # Affiche la question
            self.saisie.delete(0, END) # Vide saisie
            self.saisie.focus_set() # donne le focus a saisie
     
        def monevent(self, event=None): # event ) None car bind retourne un event et nous n'en avons pas besoin ici.
            # while True: Pas besoin avec le bind
            # reponse = None Inutile
            # affichage de l'opération à effectuer au niveau du Label 'question'
            self.question.config(text = self.questionText)
            # self.question.update() Inutile
     
            # saisie de la réponse
            # print(repr(reponse))
            reponse = self.saisie.get() # Un Entry retourne toujours un str (Exception, l'utilisation d'un IntVar()/textvariable par exemple)
            # http://python.developpez.com/faq/?page=Entry#EntryGet
            # test de la réponse et affichage d'un message adapté au niveau du Label 'message'
            if reponse == self.resultat :
                # self pas app
                self.message.config(text= "bien joué ! on essaye encore") # afficher un message de félicitation
                self.initvariable()
            elif reponse == 'stop':
    	    self.message.config(text= "D'accord, à bientot") # afficher un message d'adieu
    	    self.quit()
                # break Pas besion puisque self.quit()
            else:
    	    self.message.config(text= "NON !!! la bonne réponse était {0}".format(self.resultat)) # afficher un message d'erreur avec le resultat
                self.initvariable()
     
    app = Application()
    app.mainloop()
    # Tout code aprés le mainloop est executer aprés la destruction de la fenètre
    @+

  3. #3
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    merci beaucoup pour ce corrigé qui fonctionne comme je l'attendais

    Étudier ce code m'a permis de comprendre pas mal de choses.
    En particulier, j'ai compris comment utiliser le bind pour l'exécution de l'évènement dans le mainloop, en remplacement de ma tentative inefficace en boucle while.


    Sinon, 2 petites questions :
    - dans la procedure monevent, le 'event = None' est il indispensable et si oui pourquoi ?
    - en commentaire de initvariable, ta phrase est tronquée et je n'ai pas compris ce que tu avais voulu dire au sujet du 'self'

    Merci encore

    Spirzouf

  4. #4
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    bind retourne un event et nous n'en avons pas besoin ici.
    Si tu retire event=None Python vas te dire que monevent reçois deux informations (le self et l'event).

    Oups le mauvais copier/coller...
    L'utilisation de self permet d'utiliser initvariable en tant que procédure et non tant que fonction.
    Une fonction retourne quelque chose

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def mafonction():
        blabla = 'que du vent'
        return blabla
    Une procédure fais une action mais ne retourne rien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def maprocedure():
        blabla = 'et encore du vent'
    Donc si tu utilise self :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def maprocedure(self):
        self.blabla = 'et encore du vent'
    print self.blabla donne et encore du vent

    @+

  5. #5
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    donc si je comprend bien, en utilisant le self, cela permet de formaliser le fait qu'il s'agit d'une procédure, ce qui permet d'ajouter d'ajouter des objets qui appartiendront à la classe parente de ladite procédure, plutôt que de renvoyer une ou des valeurs lors de l'utilisation en tant que fonction avec return. C'est ça ?

    SI c'est bien ça, on pourrait d'ailleurs faire effectivement une fonction, et dans le __init__ de la classe, on pourrait créer les objets en récupérant les valeurs du return de la fonction et ainsi obtenir la même chose mais de façon moins élégante et plus lourde ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class machin():
        def __init__(self):
            self.a = uneFonction('blabla','blibli')
        def uneFonction(chaine1,chaine2):
            a = chaine1 + chaine2 # a est une variable locale de uneFontion qui n'a rien à voir avec self.a
            return a
    est équivalent a ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class machin():
        def __init__(self):
            uneProcedure('blabla','blibli')
        def uneProcedure(self,chaine1,chaine2):
            self.a = chaine1 + chaine2

  6. #6
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Pour rester dans le contexte la version avec une fonction

    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
     
    #!/usr/bin/ python
    # -*- coding: utf-8 -*-
     
    from Tkinter import *
    from random import randrange
     
    mini, maxi = 0, 10
    maxi += 1
     
    class Application(Tk):
        def __init__(self):
            Tk.__init__(self)
    	self.question = Label(self)
    	self.question.pack()
    	self.saisie = Entry(self)
    	self.saisie.pack()
    	self.message = Label(self)
    	self.message.pack()
            self.saisie.bind('<Return>', self.monevent)
            # Premiere initialisation
            self.questionText, self.resultat = self.initvariable()
            self.question.config(text = self.questionText)
     
        def initvariable(self):
            a = randrange(mini, maxi)
            b = randrange(mini, maxi)
            questionText = str('{0} + {1} = '.format (str(a),str(b)))
            resultat = str(a + b)
            return questionText, resultat
     
        def monevent(self, event=None):
            self.question.config(text = self.questionText)
            reponse = self.saisie.get()
            if reponse == self.resultat :
                self.message.config(text= "bien joué ! on essaye encore")
            elif reponse == 'stop':
    	    self.message.config(text= "D'accord, à bientot") # Inutile puisque self.quit() juste aprés
    	    self.quit()
            else:
    	    self.message.config(text= "NON !!! la bonne réponse était {0}".format(self.resultat))
            self.questionText, self.resultat = self.initvariable()
            self.question.config(text = self.questionText)
            self.saisie.delete(0, END)
            self.saisie.focus_set()
     
    app = Application()
    app.mainloop()

  7. #7
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    Donc dans une classe, le self est quand même indispensable, que ce soit procédure ou fonction.

    c'est le return pour la fonction avec ensuite affectation des variables, et le self.monObjet pour la procédure qui va faire la différence entre les 2.

    Bref, mon sujet est résolu ! Merci à toi.

    je poste ici le code actuel du prog : (je le mets en CC BY-NC-SA 2.0 si tu es ok, vu que tu as participé au code) :

    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    ############################################################
    ### Programme permettant de s'entrainer au calcul mental ###
    ### en générant aléatoirement des opérations simples à   ###
    ### résoudre						 ###
    ############################################################
     
    # Auteur : Spirzouf ( spirzouf at laposte point net )
    # Date : 24 jan 2010
    # Programme sous licence Creative Commons BY-NC-SA
    # http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
    # UN GRAND MERCI À PauseKawa POUR SON AIDE, SANS LAQUELLE J'AURAIS SUREMENT MIS PLUSIEURS JOURS DE PLUS POUR PROGRAMMER CECI
    # http://www.developpez.net/forums/d867242/autres-langages/python-zope/gui/tkinter/debutant-modifications-dynamiques-fenetre-tkinter/#post4942269
     
    # version de développement.
    # reste à faire :
    # - choix dynamique des intervalles de randomisation
    # - possibilité de faire soustraction / multiplication / division
    # - possibilité de panacher les exercices (addition suivie d'une soustraction, etc..)
    # - apprentissage des tables d'addition, soustraction et multiplication avec base de données donnant pour chaque opération (ex. 5 x 2 = ...)
    #   une note sur les 10 derniers essais afin de favoriser la sortie des opérations pour lesquelles l'élève a le moins bien répondu
    # Y'a encore du boulot !!!
     
    from Tkinter import *
    import tkFont, tkMessageBox
    from random import randint
     
    # intervalle de randomisation
    mini, maxi = 0, 10 # les nombres aléatoire seront tirés dans l'intervalle [0,10]
     
    class Application(Tk):
        def __init__(self):
            Tk.__init__(self)
            # Initialisation de la mise en forme tkFont
            tailleMath = tkFont.Font(self)
            tailleMath.config(size = 150)
            tailleMessage = tkFont.Font(self)
            tailleMessage.config(size = 40)
            # Initialisation des widgets de la fenetre
            self.title('Additions de chiffres entre 0 et 10')
            self.question = Label(self)
            self.question.config(font = tailleMath)
            self.question.pack()
            self.saisie = Entry(self)
            self.saisie.config(font = tailleMath, bg='lightyellow')
            self.saisie.pack()
            self.message = Label(self)
            self.message.config(font = tailleMessage, text='Ecris ta réponse dans la case jaune', width=500)
            self.message.pack()
            Label(self, text="Pour terminer, écris 'stop' ou cliques sur la croix en haut à droite").pack()
            # Création de binds pour enclencher la procédure reponseSaisie lors de l'appuie des 2 touches "entrée"
            # http://www.pythonware.com/library/tkinter/introduction/events-and-bindings.htm
            self.saisie.bind('<Return>', self.reponseSaisie)
            self.saisie.bind('<KP_Enter>', self.reponseSaisie)
            # Première initialisation de self.question
            self.initVariables()
     
        def initVariables(self): # Procédure d'initialisation des variables liées à la nouvelle opération à résoudre
            a = randint(mini, maxi)
            b = randint(mini, maxi)
            self.questionText = str('{0} + {1} = '.format (str(a),str(b)))
            self.resultat = str(a + b)
            self.question.config(text = self.questionText) # Affiche l'opération à résoudre
            self.saisie.delete(0, END) # Vide la l'espace de saisie
            self.saisie.focus_set() # Donne le focus à l'espace de saisie
     
        def reponseSaisie(self, event=None):
            ##### event=None car bind retourne un event et nous n'en avons pas besoin ici...
            ##### ... et necessaire sinon message d'erreur car deux arguments fournis alors que un seul serait attendu.
            # Affichage de l'opération à effectuer au niveau du Label 'question'
            self.question.config(text = self.questionText)
            # saisie de la réponse
            reponse = self.saisie.get() # Entry retourne toujours un str (Exception, l'utilisation d'un IntVar()/textvariable par exemple)
            # http://python.developpez.com/faq/?page=Entry#EntryGet
            # test de la réponse et affichage d'un message adapté au niveau du Label 'message'
            if reponse == self.resultat :
                # afficher un message de félicitation avec confirmation du résultat
                self.message.config(text= "Bien joué : {0}{1} ! On essaye encore".format(self.questionText, self.resultat), fg='darkgreen')
                # on lance une nouvelle opération à résoudre
                self.initVariables()
            elif reponse == 'stop':
                # afficher un message d'adieu
                self.message.config(text= "D'accord, à bientot", fg='yellow')
                tkMessageBox.showinfo('Fini !', "J'espère que tu t'es bien amusé, au revoir et à bientôt.")
                # on quitte
                self.quit()
            else:
                # afficher un message d'erreur avec le résultat
                self.message.config(text= "Et NON, ce n'est pas {0} !!! la bonne réponse était {1}{2}".format(reponse, self.questionText, self.resultat), fg='red') 
                # on lance une nouvelle opération à résoudre
                self.initVariables()
     
    app = Application()
    app.mainloop()
    # Tout code aprés le mainloop est exécuté après la destruction de la fenetre

  8. #8
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Juste deux choses

    Ton affichage est trop large, chez moi le texte du bas n'est pas complet.
    Regarde a faire une validation de ton Entry, c'est plus propre.

    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    #!/usr/bin/ python
    # -*- coding: utf-8 -*-
     
    ############################################################
    ### Programme permettant de s'entrainer au calcul mental ###
    ### en générant aléatoirement des opérations simples à   ###
    ### résoudre						 ###
    ############################################################
     
    # Auteur : Spirzouf ( spirzouf at laposte point net )
    # Date : 24 jan 2010
    # Programme sous licence Creative Commons BY-NC-SA
    # http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
    # UN GRAND MERCI À PauseKawa POUR SON AIDE, SANS LAQUELLE J'AURAIS SUREMENT MIS PLUSIEURS JOURS DE PLUS POUR PROGRAMMER CECI
    # http://www.developpez.net/forums/d867242/autres-langages/python-zope/gui/tkinter/debutant-modifications-dynamiques-fenetre-tkinter/#post4942269
     
    # version de développement.
    # reste à faire :
    # - choix dynamique des intervalles de randomisation
    # - possibilité de faire soustraction / multiplication / division
    # - possibilité de panacher les exercices (addition suivie d'une soustraction, etc..)
    # - apprentissage des tables d'addition, soustraction et multiplication avec base de données donnant poura chaque opération (ex. 5 x 2 = ...)
    #   une note sur les 10 dernièrs essai afin de favoriser la sortie des opérations pour lesquelles l'élève a le moins bien répondu
    # Y'a encore du boulot !!!
     
    from Tkinter import *
    import tkFont, tkMessageBox
    from random import randint
    from string import lower
     
    # intervalle de randomisation
    mini, maxi = 0, 10 # les nombres aléatoire seront tirés dans l'intervalle [0,10]
     
    class Application(Tk):
        def __init__(self):
    	Tk.__init__(self)
    	tailleMath = tkFont.Font(self, size = 150)
    	tailleMessage = tkFont.Font(self, size = 40)
    	self.title('Additions de chiffres entre 0 et 10')
    	self.question = Label(self)
    	self.question.config(font = tailleMath)
    	self.question.pack()
    	self.saisie = Entry(self, font = tailleMath, bg = 'lightyellow', validate = "key", validatecommand = self.veriftouche)
    	self.saisie.pack()
    	self.message = Label(self, font = tailleMessage, text = 'Ecris ta réponse dans la case jaune')
    	self.message.pack()
    	Label(self, text = "Pour terminer, écris 'Q' ou cliques sur la croix en haut à droite").pack()
    	self.saisie.bind('<Return>', self.reponseSaisie) # La touche Entrer lance la procédure reponseSaisie
    	self.saisie.bind('<KP_Enter>', self.reponseSaisie) # La touche Entrer du pavé numérique lance la procédure reponseSaisie
    	# http://www.pythonware.com/library/tkinter/introduction/events-and-bindings.htm
            # Validation de l'Entry
            self.saisie.bind("<Key>", self.quelletouche)
    	# Premiere initialisation de self.question
    	self.initvariable()
     
        def initvariable(self): # L'utilisation de self permet d'utiliser initvariable en tant que procédure et non 
    	# initialisation des variables
    	a = randint(mini, maxi)
    	b = randint(mini, maxi)
    	self.questionText = str('{0} + {1} = '.format (str(a),str(b)))
    	self.resultat = str(a + b)
    	self.question.config(text = self.questionText) # Affiche la question
    	self.saisie.delete(0, END) # Vide saisie
    	self.saisie.focus_set() # donne le focus a saisie
     
        def reponseSaisie(self, event=None): # event=None car bind retourne un event et nous n'en avons pas besoin ici...
            # ... et necessaire sinon message d'erreur car deux arguments fournis alors que un seul serait attendu.
    	# affichage de l'opération à effectuer au niveau du Label 'question'
    	self.question.config(text = self.questionText)
    	# saisie de la réponse
    	reponse = self.saisie.get() # Entry retourne toujours un str (Exception, l'utilisation d'un IntVar()/textvariable par exemple)
    	# http://python.developpez.com/faq/?page=Entry#EntryGet
    	# test de la réponse et affichage d'un message adapté au niveau du Label 'message'
    	if reponse == self.resultat :
    	    # afficher un message de félicitation avec confirmation du résultat
    	    self.message.config(text= "Bien joué : {0}{1} ! On essaye encore".format(self.questionText, self.resultat), fg='darkgreen') 
    	    self.initvariable()
    	elif reponse.lower() == 'q':
    	    # afficher un message d'adieu
    	    self.message.config(text= "D'accord, à bientot", fg='yellow')
    	    tkMessageBox.showinfo('Fini !', "J'espère que tu t'es bien amusé, au revoir et à bientôt.")
    	    self.quit()
    	else:
    	    # afficher un message d'erreur avec le resultat
    	    self.message.config(text= "Et NON, ce n'est pas {0} !!! la bonne réponse était {1}{2}".format(reponse, self.questionText, self.resultat), fg='red') 
    	    self.initvariable()
     
        def veriftouche(self):
            # Validation de la saisie
            if (self.touche.char in "0123456789") or (self.touche.keysym == "BackSpace") or (self.touche.keysym == "Q") or (self.touche.keysym == "q"):
                return True
            else:
                self.bell()
                return False
     
        def quelletouche(self, event):
            self.touche=event
     
    app = Application()
    app.mainloop()
    # Tout code aprés le mainloop est exécuté après la destruction de la fenetre
    A toi de voir pour le texte.

    @

  9. #9
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    cool le coup de la validation, encore un truc que je découvre qui me servira pour le résultat final. Comme c'est destiné à ma gamine qui est en CP, je trouvais plus sympa d'écrire 'stop' que de mettre un simple 'q' pour quitter. Du coup, cela complique la validation mais je garde ça de côté.

    Pour le texte trop long, j'ai un 16/10 et je me doutais que ça poserai problème sur du 4/3.

    En fait je vais bosser les options de mise en page voir si le retour à la ligne automatique est possible, et je crois avoir vu des options pour du formatage en proportion plutôt qu'en pixels ce qui est surement préférable pour la portabilité.

  10. #10
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Un dernier pour la route

    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    #!/usr/bin/ python
    # -*- coding: utf-8 -*-
     
    ############################################################
    ### Programme permettant de s'entrainer au calcul mental ###
    ### en générant aléatoirement des opérations simples à   ###
    ### résoudre						 ###
    ############################################################
     
    # Auteur : Spirzouf ( spirzouf at laposte point net )
    # Date : 24 jan 2010
    # Programme sous licence Creative Commons BY-NC-SA
    # http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
    # UN GRAND MERCI À PauseKawa POUR SON AIDE, SANS LAQUELLE J'AURAIS SUREMENT MIS PLUSIEURS JOURS DE PLUS POUR PROGRAMMER CECI
    # http://www.developpez.net/forums/d867242/autres-langages/python-zope/gui/tkinter/debutant-modifications-dynamiques-fenetre-tkinter/#post4942269
     
    # version de développement.
    # reste à faire :
    # - choix dynamique des intervalles de randomisation
    # - possibilité de faire soustraction / multiplication / division
    # - possibilité de panacher les exercices (addition suivie d'une soustraction, etc..)
    # - apprentissage des tables d'addition, soustraction et multiplication avec base de données donnant poura chaque opération (ex. 5 x 2 = ...)
    #   une note sur les 10 dernièrs essai afin de favoriser la sortie des opérations pour lesquelles l'élève a le moins bien répondu
    # Y'a encore du boulot !!!
     
    from Tkinter import *
    import tkFont, tkMessageBox
    from random import randint
    from string import lower
     
    # intervalle de randomisation
    mini, maxi = 0, 10 # les nombres aléatoire seront tirés dans l'intervalle [0,10]
     
    class Application(Tk):
        def __init__(self):
    	Tk.__init__(self)
    	tailleMath = tkFont.Font(self, size = 150)
    	tailleMessage = tkFont.Font(self, size = 40)
    	self.title('Additions de chiffres entre 0 et 10')
    	self.question = Label(self)
    	self.question.config(font = tailleMath)
    	self.question.pack()
    	self.saisie = Entry(self, font = tailleMath, bg = 'lightyellow', validate = "key", validatecommand = self.veriftouche)
    	self.saisie.pack()
    	self.message = Label(self, font = tailleMessage, text = 'Ecris ta réponse dans la case jaune')
    	self.message.pack()
    	Label(self, text = "Pour terminer, écris 'STOP' ou cliques sur la croix en haut à droite").pack()
    	self.saisie.bind('<Return>', self.reponseSaisie) # La touche Entrer lance la procédure reponseSaisie
    	self.saisie.bind('<KP_Enter>', self.reponseSaisie) # La touche Entrer du pavé numérique lance la procédure reponseSaisie
    	# http://www.pythonware.com/library/tkinter/introduction/events-and-bindings.htm
            # Validation de l'Entry
            self.saisie.bind("<Key>", self.quelletouche)
    	# Premiere initialisation de self.question
    	self.initvariable()
     
        def initvariable(self): # L'utilisation de self permet d'utiliser initvariable en tant que procédure et non 
    	# initialisation des variables
    	a = randint(mini, maxi)
    	b = randint(mini, maxi)
    	self.questionText = str('{0} + {1} = '.format (str(a),str(b)))
    	self.resultat = str(a + b)
    	self.question.config(text = self.questionText) # Affiche la question
    	self.saisie.delete(0, END) # Vide saisie
    	self.saisie.focus_set() # donne le focus a saisie
     
        def reponseSaisie(self, event=None): # event=None car bind retourne un event et nous n'en avons pas besoin ici...
            # ... et necessaire sinon message d'erreur car deux arguments fournis alors que un seul serait attendu.
    	# affichage de l'opération à effectuer au niveau du Label 'question'
    	self.question.config(text = self.questionText)
    	# saisie de la réponse
    	reponse = self.saisie.get() # Entry retourne toujours un str (Exception, l'utilisation d'un IntVar()/textvariable par exemple)
    	# http://python.developpez.com/faq/?page=Entry#EntryGet
    	# test de la réponse et affichage d'un message adapté au niveau du Label 'message'
    	if reponse == self.resultat :
    	    # afficher un message de félicitation avec confirmation du résultat
    	    self.message.config(text= "Bien joué : {0}{1} ! On essaye encore".format(self.questionText, self.resultat), fg='darkgreen') 
    	    self.initvariable()
    	elif reponse.lower() == 'stop':
    	    # afficher un message d'adieu
    	    self.message.config(text= "D'accord, à bientot", fg='yellow')
    	    tkMessageBox.showinfo('Fini !', "J'espère que tu t'es bien amusé, au revoir et à bientôt.")
    	    self.quit()
    	else:
    	    # afficher un message d'erreur avec le resultat
    	    self.message.config(text= "Et NON, ce n'est pas {0} !!! la bonne réponse était {1}{2}".format(reponse, self.questionText, self.resultat), fg='red', wraplength=1200) 
    	    self.initvariable()
     
        def veriftouche(self):
            # Validation de la saisie
            if (self.touche.char in "0123456789") or (self.touche.keysym == "BackSpace") or ((self.touche.keysym) in "SsTtOoPp"):
                return True
            else:
                self.bell()
                return False
     
        def quelletouche(self, event):
            self.touche=event
            self.saisie.configure(validate="key", validatecommand=self.veriftouche) # Pour éviter les plantages du validate
     
    app = Application()
    app.mainloop()
    # Tout code aprés le mainloop est exécuté après la destruction de la fenetre
    Edit pour le validate ;p

  11. #11
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    et le mot magique était.... wraplength !

    merci pour tout
    (on va surement se retrouver sur un autre topic, j'ai des ptit soucis sous kubuntu à utiliser Tkinter pour python3, suis bloqué en 2.6 là)

    j'y retourne

  12. #12
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Pense a regarder le validate

  13. #13
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    oui, je l'avais vu aussi

  14. #14
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    Citation Envoyé par spirzouf Voir le message
    on va surement se retrouver sur un autre topic, j'ai des ptit soucis sous kubuntu à utiliser Tkinter pour python3, suis bloqué en 2.6 là
    finalement j'ai résolu mon problème de portage en python3 grâce à la FAQ de tkinter
    http://python.developpez.com/faq/?pa...is#Tkinter2To3

  15. #15
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Suite à tes commentaires dans le code une petite idée

    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    #!/usr/bin/ python
    # -*- coding: utf-8 -*-
     
    ############################################################
    ### Programme permettant de s'entrainer au calcul mental ###
    ### en générant aléatoirement des opérations simples à   ###
    ### résoudre						 ###
    ############################################################
     
    # Auteur : Spirzouf ( spirzouf at laposte point net )
    # Date : 24 jan 2010
    # Programme sous licence Creative Commons BY-NC-SA
    # http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
    # UN GRAND MERCI À PauseKawa POUR SON AIDE, SANS LAQUELLE J'AURAIS SUREMENT MIS PLUSIEURS JOURS DE PLUS POUR PROGRAMMER CECI
    # http://www.developpez.net/forums/d867242/autres-langages/python-zope/gui/tkinter/debutant-modifications-dynamiques-fenetre-tkinter/#post4942269
     
    # version de développement.
    # reste à faire :
    # - choix dynamique des intervalles de randomisation
    # - possibilité de faire soustraction / multiplication / division
    # - possibilité de panacher les exercices (addition suivie d'une soustraction, etc..)
    # - apprentissage des tables d'addition, soustraction et multiplication avec base de données donnant poura chaque opération (ex. 5 x 2 = ...)
    #   une note sur les 10 dernièrs essai afin de favoriser la sortie des opérations pour lesquelles l'élève a le moins bien répondu
    # Y'a encore du boulot !!!
     
    from Tkinter import *
    import tkFont, tkMessageBox
    from random import randint
    from string import lower
     
    # intervalle de randomisation
    mini, maxi = 0, 10 # les nombres aléatoire seront tirés dans l'intervalle [0,10]
     
    class Application(Tk):
        def __init__(self):
    	Tk.__init__(self)
    	tailleMath = tkFont.Font(self, size = 150)
    	tailleMessage = tkFont.Font(self, size = 40)
    	self.title('Additions de chiffres entre 0 et 10')
            # Checkbutton du niveau de difficulte
            frbutton = Frame(self)
            frbutton.pack(side=TOP)
            self.Checklevel1_Checkbutton_IntVar = IntVar()
            self.Checklevel1_Checkbutton = Checkbutton(frbutton, text="Niveau 1", font=tailleMessage, variable=self.Checklevel1_Checkbutton_IntVar, onvalue=1, offvalue=0)
            self.Checklevel1_Checkbutton.pack(side=LEFT)
            self.Checklevel1_Checkbutton_IntVar_traceName = self.Checklevel1_Checkbutton_IntVar.trace_variable("w", self.Checklevel1_Checkbutton_IntVar_Callback)
            self.Checklevel2_Checkbutton_IntVar = IntVar()
            self.Checklevel2_Checkbutton = Checkbutton(frbutton, text="Niveau 2", font=tailleMessage, variable=self.Checklevel2_Checkbutton_IntVar, onvalue=1, offvalue=0)
            self.Checklevel2_Checkbutton.pack(side=LEFT)
            self.Checklevel2_Checkbutton_IntVar_traceName = self.Checklevel2_Checkbutton_IntVar.trace_variable("w", self.Checklevel2_Checkbutton_IntVar_Callback)
            # Etc...
            # Commencce au niveau 1 par defaut
            self.Checklevel1_Checkbutton_IntVar.set(1)
            #
    	self.question = Label(self)
    	self.question.config(font = tailleMath)
    	self.question.pack()
    	self.saisie = Entry(self, font = tailleMath, bg = 'lightyellow', validate = "key", validatecommand = self.veriftouche)
    	self.saisie.pack()
    	self.message = Label(self, font = tailleMessage, text = 'Ecris ta réponse dans la case jaune')
    	self.message.pack()
    	Label(self, text = "Pour terminer, écris 'STOP' ou cliques sur la croix en haut à droite").pack()
    	self.saisie.bind('<Return>', self.reponseSaisie) # La touche Entrer lance la procédure reponseSaisie
    	self.saisie.bind('<KP_Enter>', self.reponseSaisie) # La touche Entrer du pavé numérique lance la procédure reponseSaisie
    	# http://www.pythonware.com/library/tkinter/introduction/events-and-bindings.htm
            # Validation de l'Entry
            self.saisie.bind("<Key>", self.quelletouche)
    	# Premiere initialisation de self.question
    	self.initvariable()
     
        def initvariable(self): # L'utilisation de self permet d'utiliser initvariable en tant que procédure et non 
    	# initialisation des variables
            # A modifier suivant
            # if self.Checklevel1_Checkbutton_IntVar.get() == 1: Instruction pour le level 1
            # elif self.Checklevel2_Checkbutton_IntVar.get() == 1: Instruction pour le level 2
            # etc...
    	a = randint(mini, maxi)
    	b = randint(mini, maxi)
    	self.questionText = str('{0} + {1} = '.format (str(a),str(b)))
    	self.resultat = str(a + b)
    	self.question.config(text = self.questionText) # Affiche la question
    	self.saisie.delete(0, END) # Vide saisie
    	self.saisie.focus_set() # donne le focus a saisie
     
        def reponseSaisie(self, event=None): # event=None car bind retourne un event et nous n'en avons pas besoin ici...
            # ... et necessaire sinon message d'erreur car deux arguments fournis alors que un seul serait attendu.
    	# affichage de l'opération à effectuer au niveau du Label 'question'
    	self.question.config(text = self.questionText)
    	# saisie de la réponse
    	reponse = self.saisie.get() # Entry retourne toujours un str (Exception, l'utilisation d'un IntVar()/textvariable par exemple)
    	# http://python.developpez.com/faq/?page=Entry#EntryGet
    	# test de la réponse et affichage d'un message adapté au niveau du Label 'message'
    	if reponse == self.resultat :
    	    # afficher un message de félicitation avec confirmation du résultat
    	    self.message.config(text= "Bien joué : {0}{1} ! On essaye encore".format(self.questionText, self.resultat), fg='darkgreen') 
    	    self.initvariable()
    	elif reponse.lower() == 'stop':
    	    # afficher un message d'adieu
    	    self.message.config(text= "D'accord, à bientot", fg='yellow')
    	    tkMessageBox.showinfo('Fini !', "J'espère que tu t'es bien amusé, au revoir et à bientôt.")
    	    self.quit()
    	else:
    	    # afficher un message d'erreur avec le resultat
    	    self.message.config(text= "Et NON, ce n'est pas {0} !!! la bonne réponse était {1}{2}".format(reponse, self.questionText, self.resultat), fg='red', wraplength=1200) 
    	    self.initvariable()
     
        def veriftouche(self):
            # Validation de la saisie
            if (self.touche.char in "0123456789SsTtOoPp") or (self.touche.keysym == "BackSpace"):
                return True
            else:
                self.bell()
                return False
     
        def quelletouche(self, event):
            self.touche=event
            self.saisie.configure(validate="key", validatecommand=self.veriftouche) # Pour éviter les plantages du validate
     
        # Traitement des Checkbutton
        def Checklevel1_Checkbutton_IntVar_Callback(self, varName, index, mode):
            if self.Checklevel1_Checkbutton_IntVar.get() == 1:
                self.Checklevel2_Checkbutton_IntVar.set(0)
     
        def Checklevel2_Checkbutton_IntVar_Callback(self, varName, index, mode):
            if self.Checklevel2_Checkbutton_IntVar.get() == 1:
                self.Checklevel1_Checkbutton_IntVar.set(0)
     
    app = Application()
    app.mainloop()
    # Tout code aprés le mainloop est exécuté après la destruction de la fenetre
    @+

  16. #16
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Dernière idée avant d'aller au taf :

    Puisque c'est pour des enfants je pense que le plein écran serait sympa.
    Attention toutefois aux réactions du widget Entry dans ce cas de figure.

    Bon, comme l'on dit, 'y'a plus qu'a'

    @+

  17. #17
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    Bonsoir,

    merci pour toutes tes idées et exemples que je lis avec attention.

    J'ai passé les imports en python3 et surtout, j'ai pas mal avancé dans la mise en page, mais si ça fait un peu usine à gaz
    je me pose la question si cela est du à un codage non optimisé par absence d'expérience où si c'est irrémédiable avec tkinter (que je ne trouve franchement pas souple d'utilisation, peut-être par méconnaissance des arguments des modules)

    à l'heure actuelle, il me reste principalement à faire (pour la mise en page) :
    - j'ai réussi à faire du plein écran, mais reste à trouver comment faire des frame de taille dynamique et surtout proportionnelles à la taille de la fenêtre.
    - réduire la taille des entry (entry simple et combobox)
    - trouver comment grossir la taille des CheckBox
    - trouver comment grossir les fonts des ComboBox (suis déjà content d'avoir réussi à utiliser tix)

    sinon, c'est encore un peu flou concernant la portée des variables (locale, globale) : pour avoir un variable utilisable et modifiable dans toutes les procédures / fonctions, il faut qu'elles appartiennent à self ? self.mavariable
    (d'ailleurs, ne t'étonnes pas pour les variables déclarées dans le formulaire qui ne sont pas encore utilisées dans le cœur du programme, je n'ai tout simplement pas encore eu le temps de le faire. Je commencerai par mini et maxi)

    concernant python3, j'ai mis l'extension .py3 à mon fichier : ça se fait ou pas ?

    J'espère que tu auras un peu de temps pour toutes mes questions
    Merci et bonne soirée.

    EDIT 16h00 : j'ai un peu avancé depuis hier soir :
    - sur la partie fonctionnelle, les 4 opérations sont possibles, mais pas de façon dynamique : un truc m'échappe concernant l'utilisation des checkbutton...
    - pour la saisie prénom et date de naissance, je fais une saisie temps réel de l'entry pour ne pas avoir à taper sur la touche entrée, mais il manque toujours le dernier caractère : comment faire ?
    - toujours pas trouvé l'astuce pour la réduction de taille des entry

    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    # Necessite : python3 et les librairies tkinter / tix
     
    ############################################################
    ### Programme permettant de s'entrainer au calcul mental ###
    ### en générant aléatoirement des opérations simples à   ###
    ### résoudre						 ###
    ############################################################
     
    # Auteur : Spirzouf ( spirzouf at laposte point net )
    # Date : 26 jan 2010
    # Programme sous licence Creative Commons BY-NC-SA
    # http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
    # UN GRAND MERCI À PauseKawa POUR SON AIDE, SANS LAQUELLE J'AURAIS SUREMENT MIS PLUSIEURS JOURS DE PLUS POUR PROGRAMMER CECI
    # http://www.developpez.net/forums/d867242/autres-langages/python-zope/gui/tkinter/debutant-modifications-dynamiques-fenetre-tkinter/#post4942269
     
    # version de développement.
    # reste à faire :
    # - choix dynamique des intervalles de randomisation
    # - FAIT ! possibilité de faire soustraction / multiplication / division
    # - FAIT ! possibilité de panacher les exercices (addition suivie d'une soustraction, etc..)
    # - apprentissage des tables d'addition, soustraction et multiplication avec base de données donnant pour chaque opération (ex. 5 x 2 = ...)
    #   une note sur les 10 derniers essais afin de favoriser la sortie des opérations pour lesquelles l'élève a le moins bien répondu
    # Y'a encore du boulot !!!
     
    from tkinter import *
    import tkinter.font, tkinter.messagebox, tkinter.tix
    from random import randint
     
    class Application(tkinter.tix.Tk):
        def __init__(self):
            tkinter.tix.Tk.__init__(self)
            # Valeurs par défauts
            self.mini, self.maxi = 0, 10 # par défaut, les nombres aléatoires seront tirés dans l'intervalle [0,10]
            self.prenom, self.ddn = 'prénom', 'JJ/MM/AAAA'
            self.choixAdd, self.choixSous, self.choixMult, self.choixDiv = 1, 1, 1, 1
            #self.choixAdd, self.choixSous, self.choixMult, self.choixDiv = IntVar(), IntVar(), IntVar(), IntVar()
            # Création et configuration des frames et widgets inclus
            self.miseEnPage()
            # Affichage plein écran
            self.geometry(str(self.winfo_screenwidth())+"x"+str(self.winfo_screenheight())+"+0+0")
            # Création de binds pour enclencher la procédure reponseSaisie lors de l'appuie d'une des 2 touches "entrée"
            # http://www.pythonware.com/library/tkinter/introduction/events-and-bindings.htm
            self.saisie.bind('<Return>', self.reponseSaisie)
            self.saisie.bind('<KP_Enter>', self.reponseSaisie)
            # A FAIRE : bind de validation de la saisie (autoriser uniquement touches 0à9 + sToOpP) 
            self.saisiePrenom.bind('<Key>', self.reponsePrenom)
            self.saisieDDN.bind('<Key>', self.reponseDDN)
            # A FAIRE : binds des Entry du menu
            # Valeurs par défaut et Première initialisation de self.question
            self.initOperation()
     
        def miseEnPage(self): # Création des frames et des widgets
            CouleurFondMenu = 'lightyellow'
            CouleurFondExo = 'lightgreen'
            self.config(bg=CouleurFondMenu)
            # Frames du haut contenant le menu de l'application
            self.menu = Frame(self, width=1920, height=400, bg=CouleurFondMenu)
            self.menu.pack()
            self.menu1 = Frame(self.menu, width=480, height=400, bg=CouleurFondMenu)
            self.menu1.grid(row=1,column=1)
            self.menu2 = Frame(self.menu, width=480, height=400, bg=CouleurFondMenu)
            self.menu2.grid(row=1,column=2)
            self.menu3 = Frame(self.menu, width=480, height=400, bg=CouleurFondMenu)
            self.menu3.grid(row=1,column=3)
            self.menu4 = Frame(self.menu, width=480, height=400, bg=CouleurFondMenu)
            self.menu4.grid(row=1,column=4)
            # Frames du bas contenant la partie exercice et messages de l'application
            self.exo = Frame(self, width=1920, height=600, bg=CouleurFondExo)
            self.exo.pack()
            self.exo1 = Frame(self.exo, width=1920, height=300, bg=CouleurFondExo)
            self.exo1.pack(side=TOP)
            self.exo2 = Frame(self.exo, width=1920, height=300, bg=CouleurFondExo)
            self.exo2.pack()
            self.exo3 = Frame(self.exo, width=1920, height=100, bg=CouleurFondExo)
            self.exo3.pack(side=BOTTOM)
            # Initialisation de la mise en forme tkinter.font (taille des polices)
            tailleMenu = tkinter.font.Font(self)
            tailleMenu.config(size = 20)
            tailleMath = tkinter.font.Font(self)
            tailleMath.config(size = 150)
            tailleMessage = tkinter.font.Font(self)
            tailleMessage.config(size = 40)
            # Initialisation des widgets de la frame menu
            # menu1 ligne 1 : prénom
            self.prenom = Label(self.menu1, text='Mon prénom :')
            self.prenom.config(font = tailleMenu, bg=CouleurFondMenu)
            self.prenom.grid(row=1, column=1, sticky=E)
            self.saisiePrenom = Entry(self.menu1)
            self.saisiePrenom.config(font = tailleMenu, bg=CouleurFondMenu)
            self.saisiePrenom.grid(row=1, column=2)
            # menu1 ligne 2 : date de naissance : servira à créer un profil (associé au prénom)
            # A FAIRE : ComboBoX jour 1-31 - mois en lettres - 19xx/20xx - année 00-99
            self.ddn = Label(self.menu1, text='\nMa date\nde naissance :')
            self.ddn.config(font = tailleMenu, bg=CouleurFondMenu)
            self.ddn.grid(row=2, column=1, sticky=E)
            self.saisieDDN = Entry(self.menu1)
            self.saisieDDN.config(font = tailleMenu, bg=CouleurFondMenu)
            self.saisieDDN.grid(row=2, column=2, sticky=S)
            # menu2 : choix des opérations
            buttonChoixAdd = Checkbutton(self.menu2, text='additions (+)', variable=self.choixAdd, selectcolor='red', highlightcolor='green')
            buttonChoixAdd.config(font = tailleMenu, bg=CouleurFondMenu)
            buttonChoixAdd.grid(column=1, sticky=W)
            buttonChoixSous = Checkbutton(self.menu2, text='soustractions (-)', variable=self.choixSous, selectcolor='red', highlightcolor='green')
            buttonChoixSous.config(font = tailleMenu, bg=CouleurFondMenu)
            buttonChoixSous.grid(column=1, sticky=W)
            buttonChoixMult = Checkbutton(self.menu2, text='multiplications (×)', variable=self.choixMult, selectcolor='red', highlightcolor='green')
            buttonChoixMult.config(font = tailleMenu, bg=CouleurFondMenu)
            buttonChoixMult.grid(column=1, sticky=W)
            buttonChoixDiv = Checkbutton(self.menu2, text='divisions (÷)', variable=self.choixDiv, selectcolor='red', highlightcolor='green')
            buttonChoixDiv.config(font = tailleMenu, bg=CouleurFondMenu)
            buttonChoixDiv.grid(column=1, sticky=W)
            # menu3 (avec 2 nouvelles sous-frames) : A FAIRE binds et évènements
            self.menu31 = Frame(self.menu3) ; self.menu31.pack(side=TOP)
            self.menu32 = Frame(self.menu3) ; self.menu32.pack()
            Label(self.menu31, text='Avec les chiffres', font = tailleMenu, bg=CouleurFondMenu).pack()
            # -> déroulant chiffre self.mini
            Label(self.menu32, text='de', font = tailleMenu, bg=CouleurFondMenu).grid(row=1, column=1)
            listeMini = tkinter.tix.ComboBox(self.menu32, editable=1, dropdown=1, variable=self.mini)
            for i in range(0,11):
                listeMini.insert(i, i)
            listeMini.grid(row=1, column=2)
            # -> déroulant chiffre self.maxi
            Label(self.menu32, text='à', font = tailleMenu, bg=CouleurFondMenu).grid(row=1, column=3)
            listeMaxi = tkinter.tix.ComboBox(self.menu32, editable=1, dropdown=1, variable=self.maxi)
            for i in range(0,11):
                listeMaxi.insert(i, i)
            listeMaxi.grid(row=1, column=4)
            # menu4 : A FAIRE binds et évènements
            Label(self.menu4, text='Faire la table de', font = tailleMenu, bg=CouleurFondMenu).grid(row=1, column=1)
            ChiffreTable= tkinter.tix.IntVar()
            listeChiffreTable = tkinter.tix.ComboBox(self.menu4, editable=1, dropdown=1, variable=ChiffreTable)
            for i in range(0,11):
                listeChiffreTable.insert(i, i)
            listeChiffreTable.grid(row=1, column=2)
            listeChiffreTable.config(bg=CouleurFondMenu)
            Label(self.menu4, text='en', font = tailleMenu, bg=CouleurFondMenu).grid(row=2, column=1)
            TypeTable= tkinter.tix.IntVar()
            listeTypeTable = tkinter.tix.ComboBox(self.menu4, editable=1, dropdown=1, variable=TypeTable)
            listeTypeTable.config(bg=CouleurFondMenu)
            compteur = -1
            for i in ("additions", "soustractions", "multiplication", "divisions"):
                compteur += 1
                listeTypeTable.insert(compteur, i)
            listeTypeTable.grid(row=2, column=2)
            listeTypeTable.entry.delete(0, END) # efface la zone de saisie
            listeTypeTable.entry.insert(0, "additions") # initialise à addition
            listeTypeTable.entry.config(state='readonly')  # zone de saisie en lecture seule
            TypeTable = "additions"
     
            # Initialisation des widgets de la frame exo
            self.title('Additions de chiffres entre 0 et 10')
            self.message = Label(self.exo1)
            self.message.config(font = tailleMessage, text='Ecris ta réponse dans la case jaune', wraplength=1100, bg=CouleurFondExo)
            self.message.grid(row=2, column=1)
            self.question = Label(self.exo2)
            self.question.config(font = tailleMath, bg=CouleurFondExo)
            self.question.grid(row=1, column=1, sticky=W)
            self.saisie = Entry(self.exo2)
            self.saisie.grid(row=1, column=2, sticky=W)
            self.saisie.config(font = tailleMath, bg='lightyellow')
            Label(self.exo3, text="\nPour terminer, écris 'stop' ou cliques sur la croix en haut à droite\n", bg=CouleurFondExo).grid(row=3, column=1)
     
        def initOperation(self): # Procédure d'initialisation de la nouvelle opération à résoudre
            operandes, operandesOK, compteur = ['+', '-', '*', '/'], [], 0
            for i in ['self.choixAdd', 'self.choixSous', 'self.choixMult', 'self.choixDiv']:
                if eval(i) == 1:
                    operandesOK.append(operandes[compteur])
                compteur += 1
            operande = operandesOK[randint( 1 , len(operandesOK))-1]
            a, b = randint(self.mini, self.maxi), randint(self.mini, self.maxi)
            if operande == '/': # obtenir un résultat entier pour a/b
                a *= b
                b= max(b,1) # empecher la division par zero
            if operande == '-' : # obtenir a≥b pour lessoustractions
                a , b = max(a,b) , min (a,b)
            self.questionText = str('{0} {1} {2}'.format (a,operande,b))
            self.resultat = int(eval(self.questionText))
            if operande == '/':
                self.questionText = str('{0} ÷ {1} = '.format (a,b))
            elif operande == '*':
                self.questionText = str('{0} × {1} = '.format (a,b))
            else:
                self.questionText += ' = '            
            self.question.config(text = self.questionText) # Affiche l'opération à résoudre
            self.saisie.delete(0, END) # Vide l'espace de saisie
            self.saisie.focus_set() # Donne le focus à l'espace de saisie
     
        def reponseSaisie(self, event=None):
            ##### event=None car bind retourne un event et nous n'en avons pas besoin ici...
            ##### ... et nécessaire sinon message d'erreur car deux arguments fournis alors que un seul serait attendu.
            # Affichage de l'opération à effectuer au niveau du Label 'question'
            self.question.config(text = self.questionText)
            # Saisie de la réponse
            reponse = self.saisie.get() # Entry retourne toujours un str (Exception, l'utilisation d'un IntVar()/textvariable par exemple)
            if reponse == 'stop': # va afficher un message d'adieu
                self.message.config(text= "D'accord, à bientot", fg='orange')
                tkinter.messagebox.showinfo('Fini !', "J'espère que tu t'es bien amusé, au revoir et à bientôt.")
                self.quit() # on quitte
            reponse = eval(reponse)
            # http://python.developpez.com/faq/?page=Entry#EntryGet
            # test de la réponse et affichage d'un message adapté au niveau du Label 'message'
            if reponse == self.resultat : # va afficher un message de félicitation avec confirmation du résultat
                self.message.config(text= "Bien joué : {0}{1} !\nOn continue avec :".format(self.questionText, self.resultat), fg='darkgreen')
                self.initOperation() # on lance une nouvelle opération à résoudre
            else: # va afficher un message d'erreur avec le résultat
                self.bell() # bip
                self.message.config(text= "Et NON, ce n'est pas {0} !!!\nLa bonne réponse était {1}{2}".format(reponse, self.questionText, self.resultat), fg='red')
                self.initOperation() # on lance une nouvelle opération à résoudre
     
        def reponsePrenom(self, event=None):
            self.prenom = self.saisiePrenom.get() # Saisie du prénom
            print(self.prenom)
     
     
        def reponseDDN(self, event=None):
            self.ddn = self.saisieDDN.get() # Saisie de la date de naissance
            print(self.ddn)
     
    app = Application()
    app.mainloop()
    # Tout code après le mainloop est exécuté après la destruction de la fenetre

  18. #18
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    j'ai trouvé la solution pour les checkbutton EDIT : et aussi pour modifier l'entry des combobox

    dans def __init__(self) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
            self.choixAdd, self.choixSous, self.choixMult, self.choixDiv = IntVar(), IntVar(), IntVar(), IntVar()
    dans def initOperation(self) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            operandes, operandesOK, compteur = ['+', '-', '*', '/'], [], 0
            listeOperations = [self.choixAdd.get(), self.choixSous.get(), self.choixMult.get(), self.choixDiv.get()]
            for i in listeOperations :
                if i == 1:
                    operandesOK.append(operandes[compteur])
                compteur += 1
            operande = operandesOK[randint( 1 , len(operandesOK))-1]
    restent 3 problèmes principaux :
    - adapter l'intérieur de la fenêtre (y compris la taille des polices si possible) en fonction de sa taille totale : si on réduit de 50% sa hauteur et sa largeur, il faudrait tout réduire de 50% à l'intérieur
    - pour la saisie prénom et date de naissance, je fais une saisie temps réel de l'entry pour ne pas avoir à taper sur la touche entrée, mais il manque toujours le dernier caractère : comment faire ?
    - toujours pas trouvé l'astuce pour la réduction de taille des entry

  19. #19
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Pfffffffffff

    Je viens de passer un moment à te répondre et ma fille a fermer la fenêtre...

    Refais un post, avec le résolu cela tourne au dialogue

    @+

  20. #20
    Membre régulier
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Points : 97
    Points
    97
    Par défaut
    Oui, tu as raison, j'ouvre un nouveau sujet ici.

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

Discussions similaires

  1. [Python 2.X] Afficher les éléments d'une liste dans une fenetre tkinter
    Par Anatole01 dans le forum Général Python
    Réponses: 4
    Dernier message: 29/04/2015, 15h05
  2. Copier du texte dans une fenetre tkinter
    Par zemec9 dans le forum Tkinter
    Réponses: 0
    Dernier message: 20/02/2010, 19h30
  3. [SQL] Modification de champs d'un tableau dynamique dans une base de données
    Par loreleï85 dans le forum PHP & Base de données
    Réponses: 18
    Dernier message: 27/06/2006, 16h55
  4. [Tkinter] image dans une fenetre
    Par THE_VIP dans le forum Tkinter
    Réponses: 3
    Dernier message: 13/05/2006, 08h38
  5. Modification d'un texte dans une fenetre "d'erreur"
    Par PAUL87 dans le forum Access
    Réponses: 8
    Dernier message: 21/10/2005, 13h12

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