Je préconise une approche orientée objet. C'est le modèle avec lequel je commence :
# Use Tkinter for python 2, tkinter for python 3
import tkinter as tk
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
<create the rest of your GUI here>
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Les éléments importants à noter sont :
-
Je n'utilise pas d'importation joker. J'importe le paquet en tant que "tk", ce qui nécessite de préfixer toutes les commandes par tk.
. Cela évite la pollution de l'espace de nom global, et rend le code complètement évident quand vous utilisez des classes Tkinter, des classes ttk, ou certaines de vos propres classes.
-
L'application principale est une classe . Vous disposez ainsi d'un espace de nom privé pour tous vos callbacks et fonctions privées, ce qui facilite l'organisation de votre code. Dans un style procédural, vous devez coder de haut en bas, en définissant les fonctions avant de les utiliser, etc. Avec cette méthode, ce n'est pas le cas puisque la fenêtre principale n'est créée qu'à la toute dernière étape. Je préfère hériter de tk.Frame
juste parce que je commence généralement par créer un cadre, mais ce n'est en aucun cas nécessaire.
Si votre application comporte des fenêtres de niveau supérieur supplémentaires, je vous recommande de créer une classe distincte pour chacune d'entre elles, en héritant de la classe tk.Toplevel
. Cela vous donne tous les mêmes avantages que ceux mentionnés ci-dessus : les fenêtres sont atomiques, elles ont leur propre espace de noms et le code est bien organisé. De plus, il est facile de placer chaque fenêtre dans son propre module lorsque le code commence à être volumineux.
Enfin, vous pouvez envisager d'utiliser des classes pour chaque partie importante de votre interface. Par exemple, si vous créez une application avec une barre d'outils, un volet de navigation, une barre d'état et une zone principale, vous pouvez créer des classes pour chacun de ces éléments. Cela rend votre code principal assez petit et facile à comprendre :
class Navbar(tk.Frame): ...
class Toolbar(tk.Frame): ...
class Statusbar(tk.Frame): ...
class Main(tk.Frame): ...
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.statusbar = Statusbar(self, ...)
self.toolbar = Toolbar(self, ...)
self.navbar = Navbar(self, ...)
self.main = Main(self, ...)
self.statusbar.pack(side="bottom", fill="x")
self.toolbar.pack(side="top", fill="x")
self.navbar.pack(side="left", fill="y")
self.main.pack(side="right", fill="both", expand=True)
Comme toutes ces instances partagent un parent commun, le parent devient effectivement la partie "contrôleur" d'une architecture modèle-vue-contrôleur. Ainsi, par exemple, la fenêtre principale peut placer quelque chose sur la barre d'état en appelant self.parent.statusbar.set("Hello, world")
. Cela vous permet de définir une interface simple entre les composants, ce qui contribue à réduire le couplage au minimum.