Python: Tkinter: Pourquoi est-il de la racine.mainloop() et pas d'application.mainloop()
Je suis un nouveau membre à un Débordement de Pile.
J'ai trouvé ce fil de discussion, mais n'a pas été autorisé à faire des commentaires ou poser des questions sur elle, donc je pensais que je venais de référence ici: Comment puis-je faire un dans la liste interactive en Python Tkinter, complète avec des boutons qui peuvent modifier ces annonces?
from tkinter import *
import os
import easygui as eg
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
# character box
Label(frame, text = "Characters Editor").grid(row = 0, column = 0, rowspan = 1, columnspan = 2)
charbox = Listbox(frame)
for chars in []:
charbox.insert(END, chars)
charbox.grid(row = 1, column = 0, rowspan = 5)
charadd = Button(frame, text = " Add ", command = self.addchar).grid(row = 1, column = 1)
charremove = Button(frame, text = "Remove", command = self.removechar).grid(row = 2, column = 1)
charedit = Button(frame, text = " Edit ", command = self.editchar).grid(row = 3, column = 1)
def addchar(self):
print("not implemented yet")
def removechar(self):
print("not implemented yet")
def editchar(self):
print("not implemented yet")
root = Tk()
root.wm_title("IA Development Kit")
app = App(root)
root.mainloop()
Quelqu'un pourrait m'expliquer pourquoi la dernière ligne est la racine.mainloop()?
Étant un novice en Python, et venant du fond que de procédure orientée sans objet-orient expérience, j'aurais pensé qu'il aurait été d'application.mainloop().
En fait app = App(racine) , l'app est jamais utilisé dans le reste du code! Je vais avoir du mal à comprendre pourquoi la racine.mainloop() fonctionne toujours.
- Ainsi, lorsque vous initialisez votre
App
classe avecroot
, le__init__
fonction est exécutée, dans lequel tous les composants d'interface graphique sont chargés.mainloop
est une méthode deTk
qui commence la boucle d'événements de la fenêtre. Nous n'avons donc pas besoin de re-référence de l'class
(même si, techniquement, nous n'avons, à l'intérieur de laclass
lui-même) parce que tout ce dont nous avons besoin se fait que lorsque nous initialisons queclass
.
Vous devez vous connecter pour publier un commentaire.
Je ne sais pas si vous allez trouver cette réponse satisfaisante, mais vous appelez
root.mainloop()
parce queroot
est l'objet qui a lemainloop
méthode. Dans le code que vous avez donné,App
n'a pas demainloop
fonction.En termes plus simples, c'est juste la façon dont tkinter fonctionne -- vous toujours à la fin de votre script en appelant le
mainloop
méthode de la fenêtre racine. Lorsque cette méthode retourne, votre programme va fermer.Commençons par le début. Le plus simple, non-OO Tkinter programme va ressembler à l'exemple suivant. Notez que c'est un python 2.x exemple, et je ne suis pas d'utiliser une approche globale de l'importation car je pense que les importations mondiales sont mauvais.
Beaucoup de gens trouvent qu'un pur style procédural n'est pas un moyen efficace d'écrire du code, de sorte qu'ils pourraient choisir d'écrire dans un style orienté objets. Il est naturel de penser à "l'app" comme un objet singleton. Il y a beaucoup de façons de le faire-les dans votre question est, malheureusement, pas un seul de le plus clair de façons de le faire.
Une manière légèrement meilleure, OMI, est de structurer le code comme ceci:
Dans ce cas,
mainloop
est toujours appelé, même si maintenant c'est une méthode deApp
depuisApp
hérite deTk
. Il est conceptuellement le même queroot.mainloop()
puisque dans ce cas,app
est la fenêtre racine même si c'est par un nom différent.Donc, dans les deux cas,
mainloop
est une méthode qui appartient à la racine de la fenêtre. Et dans les deux cas, il doit être appelé pour l'interface graphique pour fonctionner correctement.Il y a une troisième variante, qui est ce que le code que vous avez choisi est à l'aide. Et avec cette variation, il y a plusieurs façons de la mettre en œuvre. La variation est à votre question utilise une classe pour définir l'interface graphique, mais ne pas hériter de
Tk
. C'est parfaitement bien, mais vous devez toujours appelermainloop
à un certain point. Puisque vous n'avez pas de créer (ou d'en hériter) unmainloop
fonction de votre classe, vous devez appeler l'un associé à la fenêtre racine. Les variations dont je parle sont les comment et où l'instance deApp
est ajouté à la fenêtre racine, et commentmainloop
est finalement appelé.Personnellement, je préfère que
App
hérite deFrame
, et que vous emballez l'application à l'extérieur la définition de l'application. Le modèle j'utilise ressemble à ceci:Dans ce dernier exemple,
app
etroot
sont deux totalement différents objets.app
représente une image qui existe à l'intérieur de la fenêtre racine. Les cadres sont couramment utilisés de cette façon, comme un conteneur pour les groupes d'autres widgets.Donc, dans tous les cas,
mainloop
doit être appelée. où il est appelé, et comment, dépend un peu de votre style de codage. Certaines personnes préfèrent pour hériter de la fenêtre racine, certains ne le font pas. Dans les deux cas, vous devez appeler lamainloop
fonction de la fenêtre racine.app = App(root)
, je pensais que cela signifiait que l'application était une sous-classe de la racine, et la racine est une instance de la classe Savoirs traditionnels. Mais vous avez répondu à ma question très élégamment, et relevé le vrai problème: j'ai tout simplement besoin d'apprendre le langage Python classes.J'ai testé les deux, comme vous voyez:
Est écrite avec "application". + ".pack()" et que l'on appelle "mainframe". + ".grille()"
Cette instance fonctionne très bien avec python 2.7. Dans ce test de la même application. peut gérer "mainloop()"
Ce script ouvre 2 fenêtres, l'une après l'autre (si vous fermez le premier) et le premier programme est mis en forme, n'a pas essayé d'écrire la chronique=3... des trucs dans le pack() serre.
J'ai encore commencé la Tkinter, afin de ne pas me battre, juste d'essayer.. j'Espère que je pourrais aider à répondre à votre question.
Tous les meilleurs, Ingo
La
App
objet est juste votre code d'application, et la raison pour laquelle vous appelezApp(root)
est de créer une instance de votre classe, qui dispose alors d'un accès à la racine de votre fenêtre.Il reçoit cette référence dans le
__init__
méthode:Vous pouvez voir l'ensemble de définition de la
App
objet (donné par le bloc de début avecclass App:
), et il n'a même pas unmainloop
méthode, afin de commencer le principal Tkinter, boucle, vous devez appeler la fenêtre racine.Dans le exemple dans la documentation Python2, ils ne appelez ça comme vous le soupçonnée devrait être fait, mais notez que l'exemple de leur classe en sous-classes les Savoirs traditionnels objet
Frame
. Dans votre exemple de code,App
est un vieux de la classe de style qui n'est pas hériter de quoi que ce soit.App(root)
n'est pas "pour enregistrer une référence", mais plutôt pour créer l'application. La seule chose qui sauve la référence, c'est quand vous attribuer le résultat à la variableapp
. Donc, encore une fois, vous n'avez pas appel pour enregistrer la référence, vous l'affecter à une variable pour enregistrer la référence.App
avecroot
comme paramètre, mais je crois que je vois ce que tu veux dire.root.mainloop()
est l'interface graphique principale de la fenêtre qui s'affiche. Puisapp = App(root)
est l'endroit où nous créons une instance de la classe App, mais l'application n'est jamais utilisée n'importe où ailleurs dans le code. Pourtant, par la création de l'instance de la classe App, tout dans ladef __init__(self, master):
de l'application est tout à coup visible sur l'interface graphique principale de la fenêtre (de la racine.mainloop()). Si c'est le mauvais endroit pour demander (parce que je sais vraiment zéro de la programmation orientée objet), je serai heureux d'être redirigé vers d'autres discussions qui peuvent l'expliquer.