Pourquoi utiliser des classes lors de la programmation d'une interface graphique tkinter en python

19

Je programme principalement en python et j'ai programmé quelques interfaces graphiques avec Tkinter, chaque tutoriel que j'ai jamais vu a recommandé de définir et d'utiliser une classe pour l'interface graphique, mais mon interface graphique fonctionne parfaitement en utilisant uniquement des procédures, sans classe.

Pourquoi utiliser une classe? Il me semble que ce n'est qu'une couche supplémentaire de complexité et de code inutile.

Devon Muraoka
la source

Réponses:

19

Pourquoi utiliser une classe? Parce que cela facilite le travail, en supposant que vous savez faire de la programmation orientée objet et en supposant que vous écrivez une interface graphique non triviale. L'utilisation d'objets vous permet de diviser facilement votre code en unités modulaires autonomes, et la modularisation de votre code est généralement considérée comme une meilleure pratique.

La programmation GUI se prête facilement à un style orienté objet, car une interface graphique est entièrement composée d'objets - étiquettes, boutons, barres de défilement, zones de texte, etc. Puisque vous utilisez déjà des objets, organiser votre code en objets plus grands est logique . La barre d'outils est un objet, la barre d'état est un objet, le volet de navigation est un objet, la zone principale est un objet, chaque onglet de bloc-notes est un objet, etc.

Même lorsque votre code n'est pas très complexe, d'un point de vue plus pratique, il vous permet de définir des liaisons et des rappels plus tôt dans le fichier que la définition de la fonction que vous appelez, ce qui, je pense, a beaucoup de sens.

Par exemple, considérons un exemple simple (en supposant que tkinter a été importé comme import tkinter as tk(python3) ou import Tkinter as tk(python2):

def quit(event=None):
    sys.exit()
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.pack()
label.bind("<1>", quit)
root.mainloop()

Pour moi, le flux de ce code est tout faux. Je dois définir la méthode quit avant de la référencer, et la création de la fenêtre racine et l'appel à mainloop sont séparés par tous les autres codes.

En utilisant des classes, cependant, je peux écrire le code dans un ordre plus naturel:

class MyWindow(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Hello, world")
        label.pack()
        label.bind("<1>", self.quit)
    def quit(self, event=None):
        sys.exit()

root = tk.Tk()
MyWindow(root).pack()
root.mainloop()

Le corps principal de l'interface graphique est en haut du fichier et le code de support est en dessous. Maintenant, bien sûr, vous pouvez utiliser des fonctions pour réaliser à peu près la même chose. À mon avis, cependant, les cours rendent tout cela un peu plus facile.

Un autre avantage est que je peux maintenant facilement changer la fenêtre contenant sans avoir à changer quoi que ce soit à propos de la fenêtre "principale" (et vice versa). Autrement dit, je peux ajouter des bordures ou une nouvelle section complète à l'interface graphique principale, mais je n'ai pas à toucher une seule ligne de code à l'intérieur de MyWindow. Comparez cela avec le code procédural où vous devrez peut-être modifier l' label.pack()instruction et les instructions pack (ou grille) de tous les autres widgets de l'interface utilisateur.

Cela étant dit, cependant, l'utilisation d'une approche orientée objet n'est pas nécessaire pour écrire un code correct, propre et maintenable. Cela peut être le cas, mais cela peut également conduire à un mauvais code. Au final, une approche orientée objet n'est qu'un outil. Que vous l'utilisiez ou non et que vous l'utilisiez correctement ou non dépend de nombreux facteurs. Il se peut donc très bien que pour vous, et pour le code que vous écrivez, un style fonctionnel soit parfaitement acceptable. Je pense que vous constaterez qu'à mesure que vos programmes deviennent plus complexes, une approche orientée objet facilitera l'organisation et la maintenance de votre code.

Bryan Oakley
la source
Pourquoi avez-vous utilisé un cadre dans le deuxième exemple? Ne pourriez-vous pas l'éviter comme vous l'avez fait dans le premier exemple? Y a-t-il un secret derrière l'utilisation de Frame avec des classes?
multigoodverse
2
Le cadre est simplement pour plus de commodité. Il n'y a pas de secret pour hériter de Frame. J'aurais pu hériter de objectou de toute autre classe, mais je finis généralement par créer un cadre de toute façon. Si je mets tout dans un cadre, il est logique de faire de la classe un cadre. .
Bryan Oakley
1
C'est logique, merci! De plus, j'ai vu d'autres utiliser des variables self avant, mais je vois que vous utilisez quelque chose comme label=tk.Label()au lieu de self.tk.Label(). Est-ce un choix de style? Voici un exemple utilisant self: python-textbok.readthedocs.org/en/1.0/…
multigoodverse
1
@BryanOakley, je suppose que vous vouliez utiliser parent au lieu de root dans la ligne suivante de MyWindow .__ init__: "label = tk.Label (root, text =" Hello, world ")"
user3885927
1
@ user3885927: oui! Wow, il a fallu près de trois ans à quelqu'un pour s'en rendre compte. Bien que non, parentmais plutôt self, car la classe elle-même est un Frame. Merci!
Bryan Oakley