Voici la structure générale de mon programme python tkinter typique.
def funA():
def funA1():
def funA12():
# stuff
def funA2():
# stuff
def funB():
def funB1():
# stuff
def funB2():
# stuff
def funC():
def funC1():
# stuff
def funC2():
# stuff
root = tk.Tk()
button1 = tk.Button(root, command=funA)
button1.pack()
button2 = tk.Button(root, command=funB)
button2.pack()
button3 = tk.Button(root, command=funC)
button3.pack()
funA
funB
et funC
ouvriront une autre fenêtre Toplevel
avec des widgets lorsque l'utilisateur cliquera sur le bouton 1, 2, 3.
Je me demande si c'est la bonne façon d'écrire un programme tkinter python? Bien sûr, cela fonctionnera même si j'écris de cette façon, mais est-ce le meilleur moyen? Cela semble stupide, mais quand je vois les codes écrits par d’autres personnes, leur code n’est pas gâché par un tas de fonctions et la plupart du temps, ils ont des cours.
Existe-t-il une structure spécifique que nous devrions suivre en tant que bonne pratique? Comment planifier avant de commencer à écrire un programme python?
Je sais que les meilleures pratiques en matière de programmation n'existent pas et je ne les demande pas non plus. Je veux juste des conseils et des explications pour me garder dans la bonne direction alors que j'apprends Python par moi-même.
Je préconise une approche orientée objet. Voici 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 __== "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Les points importants à noter sont:
Je n'utilise pas une importation générique. J'importe le paquet en tant que "tk", ce qui nécessite que je préfixe toutes les commandes avec tk.
. Cela évite la pollution globale des espaces de noms et rend le code complètement évident lorsque vous utilisez des classes Tkinter, des classes ttk ou certaines de vos propres.
L'application principale est une classe. Cela vous donne un espace de noms privé pour tous vos callbacks et fonctions privées, et facilite généralement l'organisation de votre code. Dans un style procédural, vous devez coder de haut en bas, définir les fonctions avant de les utiliser, etc. Avec cette méthode, vous ne le faites pas puisque vous ne créez pas la fenêtre principale avant la toute dernière étape. Je préfère hériter de tk.Frame
simplement parce que je commence généralement par créer un cadre, mais ce n'est en aucun cas nécessaire.
Si votre application dispose de fenêtres de niveau supérieur supplémentaires, il est recommandé de les affecter à une classe distincte, en héritant de tk.Toplevel
. Cela vous donne tous les avantages 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 mettre chacun dans son propre module une fois que le code commence à devenir volumineux.
Enfin, vous voudrez peut-être envisager d’utiliser des classes pour chaque partie majeure 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 chacune de ces classes. 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)
Étant donné que toutes ces instances partagent un parent commun, le parent devient en réalité le "contrôleur" de l'architecture modèle-vue-contrôleur. Ainsi, par exemple, la fenêtre principale peut placer quelque chose dans la barre d'état en appelant self.parent.statusbar.set("Hello, world")
. Cela vous permet de définir une interface simple entre les composants, aidant ainsi à rester couplé à un minimum.
En plaçant chacune de vos fenêtres de niveau supérieur dans sa propre classe, vous obtenez une réutilisation du code et une meilleure organisation du code. Tous les boutons et méthodes pertinents présents dans la fenêtre doivent être définis dans cette classe. Voici un exemple (tiré de here ):
import tkinter as tk
class Demo1:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.button1 = tk.Button(self.frame, text = 'New Window', width = 25, command = self.new_window)
self.button1.pack()
self.frame.pack()
def new_window(self):
self.newWindow = tk.Toplevel(self.master)
self.app = Demo2(self.newWindow)
class Demo2:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
self.quitButton.pack()
self.frame.pack()
def close_windows(self):
self.master.destroy()
def main():
root = tk.Tk()
app = Demo1(root)
root.mainloop()
if __== '__main__':
main()
Regarde aussi:
J'espère que ça t'as aidé.
Ce n'est pas une mauvaise structure; cela fonctionnera très bien. Cependant, vous devez avoir des fonctions dans une fonction pour faire des commandes quand quelqu'un clique sur un bouton ou quelque chose
Donc, ce que vous pourriez faire est d’écrire des classes pour celles-ci puis avoir des méthodes dans la classe qui gèrent les commandes pour les clics sur les boutons et autres.
Voici un exemple:
import tkinter as tk
class Window1:
def __init__(self, master):
pass
# Create labels, entries,buttons
def button_click(self):
pass
# If button is clicked, run this method and open window 2
class Window2:
def __init__(self, master):
#create buttons,entries,etc
def button_method(self):
#run this when button click to close window
self.master.destroy()
def main(): #run mianloop
root = tk.Tk()
app = Window1(root)
root.mainloop()
if __== '__main__':
main()
Habituellement, les programmes tk avec plusieurs fenêtres sont constitués de plusieurs grandes classes. Dans le __init__
, toutes les entrées, étiquettes, etc. sont créées, puis chaque méthode doit gérer les événements de clic de bouton.
Il n'y a pas vraiment de bonne façon de le faire, tout ce qui fonctionne pour vous et fait le travail aussi longtemps qu'il est lisible et vous pouvez facilement l'expliquer car si vous ne pouvez pas expliquer facilement votre programme, il y a probablement une meilleure façon de le faire. .
Jetez un oeil à Penser à Tkinter .
OOP devrait être l'approche et frame
devrait être une variable de classe au lieu de variable d'instance .
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame,
text="QUIT", fg="red",
command=frame.quit)
self.button.pack(side=LEFT)
self.slogan = Button(frame,
text="Hello",
command=self.write_slogan)
self.slogan.pack(side=LEFT)
def write_slogan(self):
print "Tkinter is easy to use!"
root = Tk()
app = App(root)
root.mainloop()