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 :

Répartir tkinter en classes


Sujet :

Tkinter Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    Amateur Informatique
    Inscrit en
    Décembre 2012
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Amateur Informatique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 17
    Points : 19
    Points
    19
    Par défaut Répartir tkinter en classes
    Bonjour à vous,

    Je me demandais, s'il était mieux de créer un programme utilisant Tkinter, en formant plusieurs classes.
    Je m'explique, j'ai créer un petit programme, que j'aimerais mettre en classes.
    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
    #!/usr/bin/env python
    #-*-coding:Utf-8 -*
    import Tkinter as tk
     
    # Centrez Fenetre
    def CenterWindows(original, w, h):
            """ Centrez les fenetres vers l'ecran:
            nom, weight, height"""
            original = original
            w = w
            h = h
            ws = original.winfo_screenwidth()
            hs = original.winfo_screenheight()
            # calculate position x, y
            x = (ws/2) - (w/2)
            y = (hs/2) - (h/2)
            original.geometry('%dx%d+%d+%d' % (w, h, x, y))
     
    class Foo(tk.Tk):
        """ Classe principale """
        ### Variable Constructeur.. ################################
        def __init__(self, parent):
            """Constructor"""
            tk.Tk.__init__(self,parent)
            self.parent = parent
            #Debut
            self.title("Bienvenue sur Foo")
            self.frame = tk.Frame(parent)
            self.frame.grid()
     
            #Centrez Fenetre
            centrez = CenterWindows(self,  300, 550)
     
            #Creation du frame
            self.rightFrame = tk.Frame(self, width=300, height = 600)
            self.rightFrame.grid(row=0, column=1, padx=10, pady=2)
     
            #Titre qui change Selon choix...
            self.labelA = tk.Label(self.rightFrame, text='Afficher')
            self.labelA.grid(row=0, column=0, columnspan=2, padx=10, pady=10)
     
            self.labelB = tk.Label(self.rightFrame, text='Ce que ')
            self.labelB.grid(row=1, column=0,columnspan=2,  padx=10, pady=10)
     
            self.labelC = tk.Label(self.rightFrame, text=' Coter ....')
            self.labelC.grid(row=2, column=0, columnspan=2, padx=10, pady=10)
     
            self.labelD = tk.Label(self.rightFrame, text=' ....')
            self.labelD.grid(row=3, column=0, columnspan=2, padx=10, pady=10)
     
            self.labelE = tk.Label(self.rightFrame, text='---------------------------------------------------------------------------')
            self.labelE.grid(row=4, column=0, columnspan=2, padx=10, pady=10)
     
            #Bouton#
            ##BoutonA##
            BtnA = tk.Button(self.rightFrame, text="BoutonA", fg='blue', command=self.BoutonA)
            BtnA.grid(row=5, column=0, sticky='we', padx=10, pady=2)
     
            ##BoutonB##
            BtnB = tk.Button(self.rightFrame, text="BoutonB", fg='green', command=self.BoutonB)
            BtnB.grid(row=6, column=0, sticky='we', padx=10, pady=2)
     
            ##BoutonA##
            BtnC = tk.Button(self.rightFrame, text="BoutonQuitter", fg='red', command=self.quit)
            BtnC.grid(row=7, column=0, sticky='we', padx=10, pady=2)
     
     
        ### Fonctions ####
        def BoutonA(self):
            """"""
            self.labelA.grid_forget()
            self.labelB.grid_forget()
     
        def BoutonB(self):
            """"""
            self.labelA.grid(row=0, column=0, columnspan=2, padx=10, pady=10)
            self.labelB.grid(row=1, column=0,columnspan=2,  padx=10, pady=10)
     
    ### Principale ################################################
    def main():
        app = Foo(None)
        app.mainloop()
        app.destroy()
     
    ######### Fin Programme ##############################
    #### Démarrarrez PRogramme Principale #####
    if __name__ == "__main__":
        main()
    J'aimerais tout créer en classe, si possible..
    Peut-être, je fais une erreur en voulant tout mettre en classe, je sais pas.
    Example :
    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
    #!/usr/bin/env python
    #-*-coding:Utf-8 -*
    import Tkinter as tk
     
    # Centrez Fenetre
    def CenterWindows(original, w, h):
            """ Centrez les fenetres vers l'ecran:
            nom, weight, height"""
            original = original
            w = w
            h = h
            ws = original.winfo_screenwidth()
            hs = original.winfo_screenheight()
            # calculate position x, y
            x = (ws/2) - (w/2)
            y = (hs/2) - (h/2)
            original.geometry('%dx%d+%d+%d' % (w, h, x, y))
     
    #Class Fenetre, Appelation du Tkinter.
    class Foo(tk.Tk):
        """ Classe principale """
        ### Variable Constructeur.. ################################
        def __init__(self, parent):
            """Constructor"""
            tk.Tk.__init__(self,parent)
            self.parent = parent
            #Debut
            self.title("Bienvenue sur Foo")
            self.frame = tk.Frame(parent)
            self.frame.grid()
            #Centrez Fenetre
            centrez = CenterWindows(self,  850, 550)
     
    #Classe des Frames.
    class Boite_Frame(tk.Frame):
        """Boite Frame """
        def __init__(self):
            """Constructeur"""
            self.rightFrame = tk.Frame(self, width=300, height = 600)
            self.rightFrame.grid(row=0, column=1, padx=10, pady=2)
     
            self.leftFrame = tk.Frame(self, width=300, height = 600)
            self.leftFrame.grid(row=0, column=0, padx=10, pady=2)
     
    ### Classe Widgets ####
    #Classe Boite Texte
    class Boite_Texte(tk.Text):
        """ Boite Texte défilement"""
        def __init__(self):
            """Constructeur"""
     
        def showBoite_Texte(self):
            """ Afficher la boite texte """
            #Boite Texte Dialog **
            textLog = tk.Text(self.rightFrame, width = 65, height = 20, takefocus=0)
            textLog.grid(row=6, column=0, columnspan=2, padx=10, pady=2)
     
    #Classe Bouton
    class Bouton_Quitter(tk.Button):
        """Bouton quitter"""
        def __init__(self):
            """Constructeur"""
        ### Fonction ####
        def show_btn(self):
            """Afficher bouton"""
     
        def hide_btn(self):
            """Cacher Bouton"""
     
    class Label_Principale(tk.Label):
        """ Label Principale : titre, version..."""
        def __init__(self):
            """Constructeur"""
     
    ### Principale ################################################
    def main():
        app = Foo(None)
        app.mainloop()
        app.destroy()
     
    ######### Fin Programme ##############################
    #### Démarrarrez PRogramme Principale #####
    if __name__ == "__main__":
        main()
    Je sais pas si vous comprenez l'idée.
    Es-ce la bonne voie?
    Comment puis-je faire appel au classes ?

    Le premier exemple fonctionne en copier/coller, pas le second.

    Merci de m'éclairer et de m'aider.

  2. #2
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Salut,

    Pour moi l'idée est bonne et il y a plusieurs raison à cela. Premièrement: "diviser pour mieux règner". Si tu découpe ton interface en plusieurs sections, il devient plus facile de maintenir le code, chaque classe ayant sa propre fonction. Deuxièment, il devient possible de créer des elements à la chaine. Voir l'exemple ci-dessous où je place un label et un boutton. Je souhaite répéter cela un certain nombre de fois. Plus facile avec un objet.

    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
    #!/usr/bin/env python
    # -*- coding: utf-8 -
     
    import Tkinter as tk
    import random
     
    class InputArea(tk.Frame):
        """
        """
        def __init__(self, parent, *args, **kwargs):
            tk.Frame.__init__(self, parent, *args, **kwargs)
            # Keep reference to parent (could be useful)
            self.parent = parent
            # Place an label and a button
            self.label = tk.Label(self, text='', width=10, height=1, bg='white')
            self.label.grid(row=0, column=0, padx=1, pady=2)
            self.button = tk.Button(self, text="GENERATE", command=self.run)
            self.button.grid(row=0, column=1, padx=1, pady=2)
     
        def run(self):
            nb = round(random.random(),2)
            self.label.config(text=str(nb))
     
     
    class MyApp(tk.Frame):
        """
        """
        def __init__(self, parent, *args, **kwargs):
            tk.Frame.__init__(self, parent, *args, **kwargs)
            # Keep reference to parent (could be useful)
            self.parent = parent
            # Place two input area frames
            InputArea(self).pack()
            InputArea(self).pack()
     
     
    if __name__ == '__main__':
        root = tk.Tk()
        app = MyApp(root)
        app.pack()
        root.mainloop()
    Pour revenir à ton code, il y a des choses qui ne vont pas. Tes différentes classes héritent d'un objet tkinter, mais tu n'appelle jamais le constructeur de cet objet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class MyApp(tk.Frame):
        def __init__(self, parent, *args, **kwargs):
            tk.Frame.__init__(self, parent, *args, **kwargs)
    Dans l'idée il faut créer une classe principale. Dans celle-ci tu places l'ensemble des tes elements dans le constructeur, elements qui peuvent être des widgets (Label, Button, Entry..) ou encore un frame créé par tes soins (classe héritant de Frame) contenant déjà des widgets.

    Ju

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Je me demandais, s'il était mieux de créer un programme utilisant Tkinter, en formant plusieurs classes.
    Je m'explique, j'ai créer un petit programme, que j'aimerais mettre en classes.
    Si ce "mieux" était si limpide pourquoi poser la question?

    Je sais pas si vous comprenez l'idée.
    Es-ce la bonne voie?
    Comment puis-je faire appel au classes ?
    Vous avez (éventuellement) besoin de "class" pour y définir les interfaces qui permettront d'agir sur vos objets.
    Je sais que ça n'aide pas de dire çà car les objets de votre application ne sont pas si facile à définir et les interfaces le sont encore moins. Si on reste dans le "confus", vous avez quand même une chose qui est le "panneau droit" (rightframe) qui contient des Labels et sur lesquels vous avez des actions déclenchées par l'appui sur ButtonA et ButtonB...

    On peut décider (mais c'est arbitraire) de faire une classe de cette chose là.
    Cela va permettre d'en cacher les détails et d'offrir une interface.
    Exemple:

    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
    #!/usr/bin/env python3
    #-*-coding:Utf-8 -*
    import tkinter as tk
     
    class Tk(tk.Tk):
        def center_window(self, width, height):
            x = (self.winfo_screenwidth() - width) // 2
            y = (self.winfo_screenheight() - height) // 2
            self.geometry('%dx%d+%d+%d' % (width, height, x, y))
     
    class RightPanel(tk.Frame):
        def __init__(self, master, text, **kwds):
            super().__init__(master, **kwds)
            labels = self._labels = []
            for x, s in enumerate(text.splitlines()):
                w  = tk.Label(self, text=s)
                w.grid(row=x, column=0, columnspan=2, padx=10, pady=10)
                labels.append(w)
        def do_show(self):
            for x, w in enumerate(self._labels[:2]):
                w.grid(row=x, column=0, columnspan=2, padx=10, pady=10)
        def do_hide(self):
            for w in self._labels[:2]:
                w.grid_forget()
     
     
    def create_application(master):
        assert isinstance(master, tk.Tk)
        master.center_window(300, 550)
        master.title("Bienvenue sur Foo")
        frame = tk.Frame(master)
     
        right_panel = RightPanel(frame, ''.join([
                'Afficher\n',
                'Ce que \n',
                ' Coter ....\n',
                ' ....\n'
                ]),
                width=300, height = 600
             )                
        w.grid(row=0, column=1, padx=10, pady=2)                         
        tk.Button(frame, text="BoutonA",
                  fg='blue', command=right_panel.do_hide
                  ).grid(row=5, column=0, sticky='we', padx=10, pady=2)
     
        tk.Button(frame, text="BoutonB",
                  fg='green', command=right_panel.do_show
                  ).grid(row=6, column=0, sticky='we', padx=10, pady=2)
     
        tk.Button(frame, text="BoutonQuitter",
                  fg='red', command=frame.quit
                  ).grid(row=7, column=0, sticky='we', padx=10, pady=2)
     
        return frame
     
    if __name__ == "__main__":
        root = Tk()
        frame = create_application(root)
        frame.pack()
        tk.mainloop()
    Vous voyez que dans cet exercice, je me suis amusé à créer 4 entités:
    • root: c'est l'initialisation de TCL/Tk et l'affichage de la fenêtre principale
    • create_application: çà peut rester fonction puisqu'il n'y a pas besoin pour l'instant d'ajouter de méthodes.. pourvu que çà retourne un widget
    • RightPanel: on crée des labels et les méthodes do_show et do_hide qui afficheront, masqueront les 2 premiers labels. Pour faire cela, ces méthodes doivent savoir ou RightPanels les cache. Par contre au-dessus, on se contente d'agir sur les interfaces.
    • Tk: juste pour y ranger la fonction center_widget. C'est une classe particulière qui n'a pas besoin d'__init__. On l'appelle "mixin".


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

  4. #4
    Membre à l'essai
    Homme Profil pro
    Amateur Informatique
    Inscrit en
    Décembre 2012
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Amateur Informatique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 17
    Points : 19
    Points
    19
    Par défaut
    Salut et merci

    Wow, j'en suis bouche-bée. D'après ce que je comprend, tout ma structure est erroné. Je suis entrain d'apprendre tout croche.
    J'ai souvent des erreurs d'attributs. Probablement, parce que j'ai tout créer en classe.
    Chaque bouton = une classe ( class BtnA, class BtnB, class BtnQuit)
    Chaque Label = une classe... ( class lblA, class lblB...)

    Les problèmes surviennent souvent lorsque je dois faire appel à une autre classe.

    Appeler une classe dans une classe, pour fermer une autre classe...
    AttributeError :

    Je dois donc apprendre les attributs et arguments au plus vite. Je croyais que c'était secondaire, puisque je réussissais quand même à avoir ce que je voulais.
    J’appellais jamais les fonctions de classes. J'apprends à l'envers.

    Donc,une classe par éléments ( bouttons, labels.. )

    Comme ma fais souligner, un internaute : Quel intérêt de créer 4 classe héritant de Tk.Button ? L'intérêt d'une classe est de pouvoir créer plusieurs objets dont les attributs peuvent éventuellement changer...


    Merci pour votre aide.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par nolimitech Voir le message
    Wow, j'en suis bouche-bée. D'après ce que je comprend, tout ma structure est erroné. Je suis entrain d'apprendre tout croche.
    J'ai souvent des erreurs d'attributs. Probablement, parce que j'ai tout créer en classe.
    Relisez les remarques de Julien N sur l'appel au constructeur de la classe parente.

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 07/10/2009, 11h17
  2. Tkinter et classes
    Par vorador666 dans le forum Tkinter
    Réponses: 2
    Dernier message: 24/03/2009, 13h10
  3. Dériver la classe Tkinter.Canvas
    Par Vladislav IV dans le forum Tkinter
    Réponses: 7
    Dernier message: 27/05/2007, 10h57
  4. VC++: impossible répartir classe entre .h et .cpp
    Par huguesacker dans le forum C++/CLI
    Réponses: 2
    Dernier message: 13/11/2006, 02h46
  5. [Tkinter] classes et menus déroulants
    Par THE_VIP dans le forum Tkinter
    Réponses: 3
    Dernier message: 12/08/2006, 12h53

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