La meilleure façon de structurer un tkinter application?
Ce qui suit est l'ensemble de la structure de mon type python tkinter programme.
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
apportera une autre Toplevel
windows avec les widgets lorsque l'utilisateur cliquera sur le bouton 1, 2, 3.
Je me demande si c'est la bonne façon d'écrire un python tkinter programme? Bien sûr, il fonctionnera même si j'écris de cette façon, mais est-ce la meilleure solution? Il semble stupide, mais quand je vois les codes d'autres personnes écrites, leur code n'est pas foiré avec des tas de fonctions et surtout, ils ont des classes.
Est-il une structure spécifique, que nous devons suivre comme une bonne pratique? Comment dois-je prévoir avant de commencer à écrire un programme en python?
Je sais il n'y a pas une telle chose comme la meilleure pratique dans la programmation et je ne suis pas en demandant qu'il soit. Je veux juste des conseils et des explications de me garder sur la bonne direction, car je suis à l'apprentissage de Python par moi-même.
- Voici un excellent tutoriel sur tkinter, GUI conception, avec un couple d'exemples -- python-textbok.readthedocs.org/en/latest/... Voici un autre exemple avec un modèle de conception MVC -- sukhbinder.wordpress.com/2014/12/25/...
- Cette question peut être large, mais il est utile et h relativement populaire réponse (par rapport à presque tous les autres [tkinter] réponses). Je suis en nomination pour rouvrir, comme je le vois avoir ouvert est plus utile que de l'avoir fermé.
Vous devez vous connecter pour publier un commentaire.
Je préconise une approche orientée objet. C'est le modèle que j'ai commencer avec:
Les points importants à noter sont:
Je ne pas utiliser un caractère générique à l'importation. J'ai importer le paquet comme "savoirs traditionnels", qui exige que je préfixe toutes les commandes avec
tk.
. Cela empêche espace de noms global de la pollution, et en plus il rend le code tout à fait évident quand vous êtes en utilisant Tkinter classes, ttk classes, ou une partie de votre propre.L'application principale est une classe. Cela vous donne un espace de noms privé pour tous vos rappels et des fonctions privées, et généralement facilite l'organisation de votre code. Dans un style procédural vous avez le code de haut en bas, de définir des fonctions avant de les utiliser, etc. Avec cette méthode, vous n'avez pas puisque vous n'avez pas réellement créer la fenêtre principale jusqu'à la dernière étape. Je préfère héritant de
tk.Frame
juste parce que je commence généralement par la création d'un cadre, mais il n'est pas nécessaire.Si votre application a plus de générique de windows, je recommande de faire chaque de ces dans une classe à part, héritant de
tk.Toplevel
. Cela vous donne tout de même des avantages mentionnés ci-dessus, les fenêtres sont atomiques, ils ont leur propre espace de noms, et le code est bien organisé. De Plus, il le rend facile à mettre chacun dans son propre module une fois que le code commence à devenir grand.Enfin, vous pouvez envisager d'utiliser des classes pour chaque grande partie de votre interface. Par exemple, si vous êtes en train de créer une application avec une barre d'outils, un volet de navigation, une barre de statut, et une zone principale, vous pourriez faire de chacune de ces classes. Cela rend votre code principal assez petit et facile à comprendre:
Depuis toutes ces instances partagent un parent, le parent devient le "contrôleur" partie d'un modèle-vue-contrôleur de l'architecture. Ainsi, par exemple, la fenêtre principale pourrait mettre 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, en aidant à maintenir le couplage à un minimum.self.parent = parent
est manquant. Juste en dessous de l'appel de la mère init et avantself.statusbar = Statusbar(self, ...)
parent
, sauf si vous allez l'utiliser plus tard. Je n'ai pas enregistrer parce que rien dans le code dans mon exemple en exigeant qu'il soit sauvé.main_window.py
,login_window.py
,import_file_window.py
)parent
même si le code ne l'utilise pas, parce que dans le texte qui suit immédiatement l'extrait de code, vous parler de la mère de devenir le "contrôleur" et d'appelself.parent.statusbar.set("Hello, world")
comme un exemple.MainApplication
pour enregistrerself.parent
. Le point est que le autres de windows serait passé comme un paramètre, et ils permettrait d'économiserself.parent
. Peut-être que je peux essayer de reformuler ce que le dernier bit de la rendre plus claire.MainApplication
et unMain
classe, qui sont tous deux des "fenêtres" (sous-classes detk.Frame
). Par conséquent, lorsque vous avez écrit "...par exemple, la fenêtre principale...", j'ai mélangé les deux et la pensée de laparent
dans leself.parent.statusbar.set()
appel a étéroot
, plutôt que ce soit l'instance deMainApplication
qui est passée comme laself
argument dans leself.main = Main(self, ...)
appel (et enregistrées par leMain
exemple dans un attribut de sa propre nomméeparent
).parent
pourclass
instanciations dansclass MainApplication(tk.Frame)
de l'initialisation, si ma compréhension, je pense que leself
ici est de jouer le rôle de ce qu'on appellecontroller
, est correcte.Statusbar(self, ...)
est le parent. aussi peut agir comme un contrôleur.self
commeparent
. Voulez-vous prendre un coup d'oeil et de le conseiller?De mettre chacun de vos fenêtres de niveau supérieur dans une catégorie distincte vous donne le code de la ré-utilisation et une meilleure organisation du code. Tous les boutons et les méthodes qui sont présents dans la fenêtre doit être définie à l'intérieur de cette classe. Voici un exemple (tiré de ici):
Voir aussi:
Espère que ça aide.
Ce n'est pas une mauvaise structure; il fonctionne très bien. Cependant, vous ne devez avoir les fonctions dans une fonction pour faire des commandes lorsque quelqu'un clique sur un bouton ou quelque chose
Donc ce que vous pourriez faire est d'écrire des classes pour ceux-ci, de disposer de méthodes dans la classe qui gèrent les commandes pour que le bouton s'enclenche et ces.
Voici un exemple:
Généralement les savoirs traditionnels des programmes avec plusieurs fenêtres sont plusieurs grandes classes et, dans le
__init__
toutes les entrées, étiquettes, etc sont créés et chaque méthode est de gérer les événements click de boutonIl n'est pas vraiment une bonne façon de le faire, tout ce qui fonctionne pour vous et fait le travail, aussi longtemps que ses lisible et vous pouvez facilement l'expliquer parce que si vous ne pouvez pas expliquer facilement votre programme, il y a sans doute une meilleure façon de le faire.
Prendre un coup d'oeil à Penser en Tkinter.
De la programmation orientée objet devrait être l'approche et
frame
devrait être un variable de classe au lieu de variable d'instance.Référence: http://www.python-course.eu/tkinter_buttons.php
TKinter
sur Python 2. Je vous conseille d'utilisertkinter
pour Python 3. Je voudrais également lieu les trois dernières lignes de code sous unmain()
fonction et l'appeler à la fin du programme. Je voudrais certainement évitez d'utiliserfrom module_name import *
comme il pollue l'espace de noms global et peut réduire la lisibilité.button1 = tk.Button(root, command=funA)
etbutton1 = ttk.Button(root, command=funA)
si letkinter
module d'extension a également été importé? Avec le*
syntaxe, les deux lignes de code semble êtrebutton1 = Button(root, command=funA)
. Je ne recommande pas d'utiliser cette syntaxe.Probablement la meilleure façon d'apprendre comment structurer votre programme est en lisant d'autres personnes de code, surtout si c'est un programme de taille importante pour laquelle de nombreuses personnes ont contribué. Après avoir regardé le code de nombreux projets, vous devriez avoir une idée de ce que le consensus de style devrait être.
Python, comme une langue, est particulier en ce qu'il y a de fortes lignes directrices sur la façon dont vous devez formater votre code. La première est la soi-disant "Zen de Python":
Sur un plan plus pratique, il est PEP8, le guide de style pour Python.
Avec celles à l'esprit, je dirais que votre style de code n'a pas vraiment d'ajustement, en particulier les fonctions imbriquées. Trouver un moyen de les aplatir ceux qui, soit par l'utilisation de classes ou de les déplacer dans des modules séparés. Cela permettra à la structure de votre programme beaucoup plus facile à comprendre.
Personnellement, je n'utilisez pas l'objection que l'approche orientée, surtout parce qu'il en a) ne obtenir de la manière; b) vous jamais les réutiliser en tant que module.
mais quelque chose qui n'est pas abordé ici, c'est que vous doit utiliser le filetage ou le multitraitement. Toujours. sinon votre demande sera terrible.
viens de faire un test simple: lancez une fenêtre, et de récupérer une URL ou quoi que ce soit d'autre. des changements sont à votre INTERFACE utilisateur ne sera pas mis à jour alors que la demande de réseau qui se passe. Sens, la fenêtre de l'application sera brisé. dépend de l'OS que vous êtes, mais la plupart du temps, il ne sera pas mis à jour, tout ce que vous faites glisser le pointeur sur la fenêtre sera plâtré sur elle, jusqu'à ce que le processus est de retour à la les SAVOIRS traditionnels mainloop.