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 :

Penser en Tkinter


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur / Enseignant
    Inscrit en
    Février 2012
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur / Enseignant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2012
    Messages : 115
    Par défaut Penser en Tkinter
    Ce document est largement inspiré de "Tkhinking in Tkinter " de Stephen Ferg : http://thinkingtkinter.sourceforge.net/

    La même chose en français ici : http://www.ferg.org/thinking_in_tkin...n_tkinter.html

    INTRODUCTION

    A propos de " Penser en Tkinter "
    Les courts programmes suivants expliquent comment penser en Tkinter. Dans ces programmes tous les types de widgets, attributs, et méthodes qui sont disponibles dans Tkinter ne sont pas étudiés. La finalité est de comprendre quelques concepts de base de Tkinter.

    Les Quatre Tâches de base en programmation d'interfaces GUI
    Pour développer une interface utilisateur (UI), il y a une série de tâches à accomplir :

    1. Indiquer l'apparence voulue pour cette interface utilisateur. Le code détermine ce que l'utilisateur voit sur son écran.



    1. Décider ce que fait l'interface utilisateur (UI). Le code accomplit les tâches du programme.



    1. Associer "l'apparence" avec "l'action". Le code associe ce que voit l'utilisateur avec les routines qui exécutent les tâches du programme.



    1. Ecrire le code qui attend les entrées de l'utilisateur.


    Jargon de programmation avec un Gui
    La programmation avec un GUI (graphical user interface - interface utilisateur graphique) a un jargon spécifique associé avec ces tâches :

    1. Indiquer l'apparence du GUI en décrivant les "widgets" à afficher et leurs relations dans l'espace (c.à.d. Si un widget est au-dessus ou en dessous d'un autre, à droite ou à gauche d'autres widgets). Le mot widget est un objet banal et quelconque, que l’on peut traduire en français par "machin". Il est devenu en informatique un "composant de l'interface graphique". Les Widgets incluent des éléments d’affichage simple, des boutons, des menus, des conteneurs, des listes, des champs utilisateurs, des aides au retour utilisateur et des fenêtres.



    1. Les routines du GUI sont appelées les "callback handlers" ou "event handlers". Les "events" sont les évènements (clicks sur la souris, d'appuyer sur une touche du clavier, etc.). Ces routines sont appelées des "handlers" parce que elles gèrent "handle" (c.à.d. répondent à) de tels évènements.



    1. On appelle "binding" le fait d'associer un event handler avec un widget. En gros, le binding implique trois choses différentes :


    1. Un type d'évènement (ex : un click gauche sur la souris, appuyer sur la touche ENTER du clavier).
    2. Un widget (c.à.d. : un bouton, menu, etc.)
    3. Une routine de gestion d'évènement.

    Exemple : Associer un click gauche de la souris au bouton/widget "CLOSE" sur l'écran à la routine closeProgram, qui ferme la fenêtre et arrête le programme.


    1. Le code qui tourne et attend une saisie est appelé "l'event loop".


    A propos de l'Event Loop
    L'event loop passe tout son temps à regarder ce qui se passe et il voit tout. La plupart des évènements ne sont pas intéressants et quand il les voit, il ne fait rien. Mais quand il voit quelque chose d'intéressant, un évènement qu'il sait intéressant, parce qu'un event handler a été rattaché à l'évènement alors il contacte immédiatement l'event handler et l'informe de ce qui s'est passé.

  2. #2
    Membre confirmé
    Homme Profil pro
    Ingénieur / Enseignant
    Inscrit en
    Février 2012
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur / Enseignant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2012
    Messages : 115
    Par défaut
    Le plus court programme Tkinter - - Trois instructions !
    Concernant les quatre tâches de base d'un GUI décrites précédemment, ce programme en exécute juste une, l'event loop.

    (1) La première instruction importe Tkinter, pour qu'il soit disponible.
    NB : la forme de cet import ("from Tkinter import *") implique de ne pas avoir à préciser de widget avec un préfixe Tkinter.

    (2) La deuxième instruction crée une fenêtre "toplevel". Techniquement cette instruction crée une instance de la classe "Tkinter.Tk".
    La fenêtre d'avant-plan est le composant de plus haut niveau du GUI dans n'importe quelle application Tkinter. Par convention, on appelle cette fenêtre "root".

    (3) La troisième instruction exécute la boucle principale "mainloop" (c.à.d. l'event loop), qui est une méthode de l'objet root.
    Tant que l'on est dans la boucle principale, on attend un évènement qui se passe dans (la fenêtre) root. Quand un évènement arrive, il est traité et la boucle continue, en attente de l'évènement suivant. La boucle continue à s'exécuter jusqu'à ce qu'un évènement "destroy" arrive dans la fenêtre d'avant-plan. Un évènement destroy ferme une fenêtre. Quand la fenêtre d'avant-plan est détruite, la fenêtre est fermée et on sort de l'event loop.


    Comportement Du Programme
    Pendant l'exécution de ce programme, grâce à Tk, la fenêtre a des widgets pour réduire ou augmenter la taille de la fenêtre et fermer la fenêtre.

    Clicker sur le widget "close" (c.à.d. "x" à la droite de la barre de titre) déclenche un évènement "destroy". L'évènement destroy termine la boucle principale d'évènement. Et comme il n'y a pas d'instructions après "root.mainloop()", le programme n'a plus rien à faire et donc se termine.

    Programme Source Code


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from tkinter import *       # (1)
    
    root = Tk()                 # (2)
    root.mainloop()             # (3)

  3. #3
    Membre confirmé
    Homme Profil pro
    Ingénieur / Enseignant
    Inscrit en
    Février 2012
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur / Enseignant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2012
    Messages : 115
    Par défaut
    Une de nos quatre tâches du GUI -- indiquer à quoi le GUI doit ressembler.
    Avec ce programme, trois concepts importants de la programmation Tkinter sont introduits :

    1. Créer d’un objet GUI et l’associer avec ses parents.
    2. Le packing.
    3. Les containers par opposition aux widgets.


    Il faut faire la distinction entre un "container component" et un widget. Un widget est un composant du GUI (en général visible), un container est simplement un container -- un panier -- dans lequel nous plaçons des widgets.
    Tkinter propose de nombreux containers. "Canvas" (toile) est un container pour des applications de dessin. Le container le plus utilisé est le "Frame"(cadre). Les Frames sont fournis par Tkinter dans une classe appelée "Frame". Une expression comme :
    Frame (myParent)
    crée une instance de la classe Frame (c.à.d. crée un cadre), et associe l'instance Frame avec son parent, myParent. Autre façon de voir, l’expression ajoute un frame enfant au composant myParent.
    (1) La première expression crée un cadre (frame) dont le parent est myParent (c.à.d. root), et lui donne le nom "myContainer". En résumé, il crée un container dans lequel on peut placer des widgets.
    NB : la relation parent/enfant ici est une relation LOGIQUE, pas une relation visuelle. Cette relation existe pour supporter des choses comme l'évènement destroy -- afin que quand un composant parent (comme root) est détruit, le parent sait quels sont ses enfants et peut les détruire avant de se détruire lui-même.

    (2) L'instruction suivante "packe" (remplit) myContainer. Le "packing" consiste à mettre en place une relation VISUELLE entre un composant du GUI et son parent. Il faut faire un pack (insertion) d'un composant pour qu’il apparaisse. "Pack" appelle le geometry manager "pack" de Tkinter.

    NB : Un geometry manager est surtout une API -- une façon de communiquer avec Tkinter -- pour indiquer à Tkinter comment les containers et widgets doivent être visuellement présentés. Tkinter supporte trois geometry managers: pack, grid, et place.

    Pack et dans une moindre mesure grid sont les plus utilisés, parce qu'ils sont les plus faciles à utiliser. Tous les exemples dans "Penser en Tkinter" utilisent le pack geometry manager.

    (1) L’instruction crée une instance et l’associe avec son parent.

    (2) L’instance est packée (insérée)

    Comportement Du Programme
    Ce programme ressemble beaucoup au précédent, avec la différence qu'il affiche moins de choses. C'est parce que les Frames (cadres) sont élastiques.

    Un frame (un cadre) est fondamentalement un container. L'intérieur d'un container -- le "space" à l'intérieur du container -- est appelé la "cavity" (creux), un terme que Tkinter a pris à Tk.)

    La cavity est "stretchy" (élastique) comme un élastique. A moins d'indiquer une taille pour le frame, la cavity va s'étirer ou se réduire pour s'adapter dans le frame (cadre).

    Dans le programme précédent, le root s'est affiché avec la taille par défaut, car rien n’a été précisé. Mais dans ce programme, un container a été placé dans la cavity de root. Donc le cadre root se réduit pour s'adapter à la taille du container. Comme il n’y a pas de widgets dans container et pas de taille indiqué pour le container, la cavity de root se réduit à rien. Voilà pourquoi il n'y a rien à voir en dessous de la title bar.

    Programme Source Code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    from tkinter import *
    
    root = Tk()
    
    myContainer = Frame(root)       # (1)
    myContainer.pack()              # (2)
    
    root.mainloop()

  4. #4
    Membre confirmé
    Homme Profil pro
    Ingénieur / Enseignant
    Inscrit en
    Février 2012
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur / Enseignant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2012
    Messages : 115
    Par défaut
    Les premiers widgets
    Dans ce programme les premier widgets sont créés et placés dans myContainer.
    Le premier widget sera un bouton -- c.à.d. une instance de la classe "Button" de Tkinter.
    Le deuxième sera un canvas (toile) -- c.à.d. une instance de la classe "Canvas" de Tkinter.

    (1) L'instruction crée le bouton, lui donne le nom "button1", et l'associe avec son parent le container appelé myContainer.

    (2)(3) Les instructions définissent les attributs de notre bouton. Dans cet exemple, deux des attributs de button1 sont définit : la couleur d'arrière-plan et le texte avec les clés "text" et "background".

    NB : Les widgets possèdent de nombreux attributs, qui sont rangés dans le local namespace dictionary. Les Button widgets ont des attributs pour contrôler leur taille, leur couleurs d'arrière-plan et d'avant-plan, le texte qu'ils affichent, l'apparence de leur bord, etc. Les attributs sont définis en donnant les valeurs dans le dictionnaire du bouton.

    (4) L’instruction insère (avec pack) le button1.

    (5) L’instruction insère une zone de dessin, lui donne le nom de "myCanvas" et l’associe avec son parent.

    (6)(7) Les instructions donnent des valeurs attributs pour indiquer sa taille à l’objet myCanvas.

    Quelques Termes Techniques
    Quelques fois la relation entre un container et le widget qu'il contient est décrite comme une relation parent/enfant, d'autres fois comme une relation maitre/esclave.

    Comportement du Programme
    Le container contient maintenant un bouton vert avec le texte "Bonjour, Monde !" et une zone de dessin grise d’une certaine taille. Cliquer sur le bouton ne fait rien, car il n'a pas encore indiqué ce qui doit se passer quand ce bouton est cliqué.

    Pour l'instant, il faut fermer la fenêtre, comme précédemment, en cliquant sur l'icône "CLOSE" de la barre de titre.
    Le container s'est étiré pour accueillir bouton et la zone de dessin.

    Programme Source 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
    from tkinter import *
    
    root = Tk()
    
    myContainer1 = Frame(root)
    myContainer1.pack()
    
    button1 = Button(myContainer1)              # (1)
    button1["text"] = "Bonjour, Monde !"        # (2)
    button1["background"] = "green"             # (3)
    button1.pack()                              # (4)
    
    myCanvas = Canvas(myContainer1)             # (5)
    myCanvas["background"] = "grey"
    myCanvas["height"] = 100                    # (6)                    
    myCanvas["width"] = 100                     # (7)                     
    myCanvas.pack()                             
    
    root.mainloop()

  5. #5
    Membre confirmé
    Homme Profil pro
    Ingénieur / Enseignant
    Inscrit en
    Février 2012
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur / Enseignant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2012
    Messages : 115
    Par défaut
    Utilisation D'une Structure De Classe
    Dans ce programme, un nouveau concept est introduit, l’application Tkinter est structurée dans un ensemble classe. Une classe appelée MyApp est créée et une partie du code du programme précédent est déplacé dans la méthode constructor (__init__). Dans cette version modifiée, trois choses différentes sont effectuées:

    (1) L’instruction déclare une classe (MyApp). Cette classe indique à quoi notre GUI doit ressembler et le genre de choses que nous voulons faire avec.

    (2) Cette instruction place le code qui définit le GUI dans le constructeur de la méthode (__init__) de la classe. Le constructor method reconnait le root sous le nom "myParent".

    (3) Cette instruction crée une instance de la classe et passe le "root" en tant que paramètre dans le constructor method (__init__) de MyApp

    NB : Le nom de la classe est "MyApp" (avec majuscule) et le nom de l'instance est "myapp" (sans majuscule).

    (4) Cette instruction exécute mainloop sur le root.

    Pouquoi Structurer l’Application En Tant Que Classe ?
    Une des raisons d’utiliser une structure de classe dans un programme est de mieux contrôler le programme. Un programme structuré en classes est sans doute -- spécialement s'il s'agit d’un gros programme -- bien plus facile à comprendre qu'un programme qui n'est pas structuré.

    L’autre raison de structurer une application en tant que classe est d’éviter d'utiliser des variables globales. L’utilisation des variables globales est déconseillé car elles rendent plus difficile la compréhension d’un programme, son débogage et son amélioration future. Une meilleure manière de faire est d'utiliser les instances (c.à.d. les variables "self") et donc de donner à l’application une structure de classe.
    Quand Introduire Le Class Structuring
    Souvent, un programme Tkinter commence comme un simple script. Puis, le programme grossit et le programme commence à être difficile à comprendre et à modifier. Il est alors temps de refactoriser le programme et de le restructurer en utilisant des classes.

    D'un autre côté, en ayant une idée précise de ce doit être le programme, il est possible de choisir de structurer le programme en utilisant des classes dès le départ.

    D'un autre côté, au début du développement, la meilleure structure de classe à utiliser n’est pas connue. Commencer à utiliser des classes trop tôt peut ajouter une structure inutile qui encombre le code, gêne la compréhension, et éventuellement nécessite plus de refactoring.

    Donc cela dépend des préférences, de l’expérience et des circonstances. Il faut faire ce qui semble le mieux adapté et ne pas hésiter à faire une refactorisation importante quand cela est nécessaire.

    Comportement Du Programme
    Le programme semble complètement identique au précédent, les fonctionnalités n'ont pas changé, la seule différence, c'est la manière dont le code est structuré.

    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
    from tkinter import *
     
    class MyApp:                                            # (1)
        def __init__(self , myParent):                      # (2)
            self.myContainer1 = Frame(myParent)
            self.myContainer1.pack()
     
            self.button1 = Button(self.myContainer1)
            self.button1["text"] = "Bonjour le monde !"
            self.button1["background"] = "green"
            self.button1.pack()
     
            self.myCanvas = Canvas(self.myContainer1)
            self.myCanvas["background"] = "grey"
            self.myCanvas["height"] = 100
            self.myCanvas["width"] = 100
            self.myCanvas.pack()
     
    root = Tk()
    myapp = MyApp(root)                                     # (3)
    root.mainloop()                                         # (4)

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    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 754
    Par défaut
    Heu... Avez vous remarque que la traduction en français du document http://thinkingtkinter.sourceforge.net/ était déjà faite? Elle est mentionnée a la fin du document, dans downloads
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. [Tkinter] Binder le bouton de fermeture d'un Tk()
    Par jc_isd dans le forum Tkinter
    Réponses: 2
    Dernier message: 09/02/2005, 16h11
  2. Réponses: 3
    Dernier message: 26/10/2004, 07h31
  3. Réponses: 3
    Dernier message: 16/08/2004, 10h57
  4. Merci de penser au tag [Résolu] SVP
    Par grafikm_fr dans le forum Langages de programmation
    Réponses: 0
    Dernier message: 02/05/2004, 13h13
  5. Que penser de l'avenir de glut??
    Par xg dans le forum GLUT
    Réponses: 4
    Dernier message: 06/02/2004, 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