Das Folgende ist die Gesamtstruktur meines typischen Python-Tkinter-Programms.
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
und funC
öffnet ein weiteres Toplevel
Fenster mit Widgets, wenn der Benutzer auf die Schaltflächen 1, 2, 3 klickt.
Ich frage mich, ob dies der richtige Weg ist, um ein Python-Tkinter-Programm zu schreiben. Sicher, es wird funktionieren, auch wenn ich so schreibe, aber ist es der beste Weg? Es klingt dumm, aber wenn ich die Codes sehe, die andere Leute geschrieben haben, ist ihr Code nicht mit einer Reihe von Funktionen durcheinander und meistens haben sie Klassen.
Gibt es eine bestimmte Struktur, der wir als bewährte Praxis folgen sollten? Wie soll ich planen, bevor ich mit dem Schreiben eines Python-Programms beginne?
Ich weiß, dass es keine bewährten Methoden für die Programmierung gibt, und ich frage auch nicht danach. Ich möchte nur einige Ratschläge und Erklärungen, um mich auf dem richtigen Weg zu halten, während ich Python selbst lerne.
Antworten:
Ich befürworte einen objektorientierten Ansatz. Dies ist die Vorlage, mit der ich beginne:
Die wichtigsten Dinge zu beachten sind:
Ich verwende keinen Platzhalterimport. Ich importiere das Paket als "tk", was erfordert, dass ich allen Befehlen ein Präfix vorstelle
tk.
. Dies verhindert eine globale Verschmutzung des Namespace und macht den Code vollständig offensichtlich, wenn Sie Tkinter-Klassen, ttk-Klassen oder einige Ihrer eigenen verwenden.Die Hauptanwendung ist eine Klasse . Dies gibt Ihnen einen privaten Namespace für alle Ihre Rückrufe und privaten Funktionen und erleichtert im Allgemeinen die Organisation Ihres Codes. In einem prozeduralen Stil müssen Sie von oben nach unten codieren, Funktionen definieren, bevor Sie sie verwenden usw. Mit dieser Methode tun Sie dies nicht, da Sie das Hauptfenster erst im letzten Schritt erstellen. Ich bevorzuge es zu erben,
tk.Frame
nur weil ich normalerweise mit dem Erstellen eines Rahmens beginne, aber es ist keineswegs notwendig.Wenn Ihre App über zusätzliche Fenster auf oberster Ebene verfügt, empfehle ich, jede dieser Fenster zu einer separaten Klasse zu machen, von der geerbt wird
tk.Toplevel
. Dies bietet Ihnen alle oben genannten Vorteile: Die Fenster sind atomar, sie haben einen eigenen Namespace und der Code ist gut organisiert. Außerdem ist es einfach, jedes Modul in ein eigenes Modul zu integrieren, sobald der Code groß wird.Schließlich möchten Sie möglicherweise Klassen für jeden Hauptteil Ihrer Benutzeroberfläche verwenden. Wenn Sie beispielsweise eine App mit einer Symbolleiste, einem Navigationsbereich, einer Statusleiste und einem Hauptbereich erstellen, können Sie jede dieser Klassen erstellen. Dies macht Ihren Hauptcode ziemlich klein und leicht verständlich:
Da alle diese Instanzen ein gemeinsames übergeordnetes Element haben, wird das übergeordnete Element effektiv zum "Controller" -Teil einer Model-View-Controller-Architektur. So könnte beispielsweise das Hauptfenster durch Aufrufen etwas in der Statusleiste platzieren
self.parent.statusbar.set("Hello, world")
. Auf diese Weise können Sie eine einfache Schnittstelle zwischen den Komponenten definieren und so die Kopplung auf ein Minimum beschränken.quelle
parent
, es sei denn, Sie werden ihn später verwenden. Ich habe es nicht gespeichert, da für keinen der Codes in meinem Beispiel das Speichern erforderlich war.Wenn Sie jedes Fenster der obersten Ebene in eine eigene Klasse einordnen, können Sie den Code wiederverwenden und den Code besser organisieren. Alle im Fenster vorhandenen Schaltflächen und relevanten Methoden sollten in dieser Klasse definiert werden. Hier ist ein Beispiel (von hier genommen ):
Siehe auch:
Hoffentlich hilft das.
quelle
Dies ist keine schlechte Struktur; es wird gut funktionieren. Sie müssen jedoch Funktionen in einer Funktion haben, um Befehle ausführen zu können, wenn jemand auf eine Schaltfläche oder etwas klickt
Sie können also Klassen für diese schreiben und dann Methoden in der Klasse haben, die Befehle für die Schaltflächenklicks und dergleichen verarbeiten.
Hier ist ein Beispiel:
Normalerweise sind tk-Programme mit mehreren Fenstern mehrere große Klassen und in der
__init__
allen Einträgen werden Beschriftungen usw. erstellt. Anschließend werden bei jeder Methode Schaltflächenklickereignisse verarbeitetEs gibt nicht wirklich einen richtigen Weg, was auch immer für Sie funktioniert und die Arbeit erledigt, solange es lesbar ist und Sie es leicht erklären können, denn wenn Sie Ihr Programm nicht einfach erklären können, gibt es wahrscheinlich einen besseren Weg, es zu tun .
Schauen Sie sich Thinking in Tkinter an .
quelle
OOP sollte der Ansatz sein und
frame
eine Klassenvariable anstelle einer Instanzvariablen sein .Referenz: http://www.python-course.eu/tkinter_buttons.php
quelle
TKinter
Python 2 verwenden. Ich würde die Verwendungtkinter
für Python 3 empfehlen . Ich würde auch die letzten drei Codezeilen unter einermain()
Funktion platzieren und diese am Ende des Programms aufrufen. Ich würde es definitiv vermeiden, es zu verwenden,from module_name import *
da es den globalen Namespace verschmutzt und die Lesbarkeit beeinträchtigen kann.button1 = tk.Button(root, command=funA)
und erkennen,button1 = ttk.Button(root, command=funA)
ob dastkinter
Erweiterungsmodul auch importiert wurde? Mit der*
Syntax scheinen beide Codezeilen zu seinbutton1 = Button(root, command=funA)
. Ich würde die Verwendung dieser Syntax nicht empfehlen.Das Organisieren Ihrer Anwendung mithilfe von Klassen erleichtert Ihnen und anderen, die mit Ihnen zusammenarbeiten, das Debuggen von Problemen und das einfache Verbessern der App.
Sie können Ihre Anwendung einfach so organisieren:
quelle
Der wahrscheinlich beste Weg, um zu lernen, wie Sie Ihr Programm strukturieren, ist das Lesen des Codes anderer Personen, insbesondere wenn es sich um ein großes Programm handelt, zu dem viele Personen beigetragen haben. Nachdem Sie sich den Code vieler Projekte angesehen haben, sollten Sie eine Vorstellung davon bekommen, wie der Konsensstil aussehen sollte.
Python als Sprache ist insofern besonders, als es einige strenge Richtlinien gibt, wie Sie Ihren Code formatieren sollten. Das erste ist das sogenannte "Zen of Python":
Auf einer praktischeren Ebene gibt es PEP8 , den Styleguide für Python.
Vor diesem Hintergrund würde ich sagen, dass Ihr Codestil nicht wirklich passt, insbesondere die verschachtelten Funktionen. Finden Sie eine Möglichkeit, diese zu reduzieren, indem Sie entweder Klassen verwenden oder sie in separate Module verschieben. Dadurch wird die Struktur Ihres Programms viel einfacher zu verstehen.
quelle
Ich persönlich verwende den objektorientierten Ansatz nicht, hauptsächlich, weil er a) nur im Weg steht; b) Sie werden das niemals als Modul wiederverwenden.
sondern etwas , das nicht hier diskutiert wird, ist , dass Sie müssen verwenden Threading oder Multiprocessing. Immer. Andernfalls wird Ihre Bewerbung schrecklich sein.
Führen Sie einfach einen einfachen Test durch: Starten Sie ein Fenster und rufen Sie dann eine URL oder etwas anderes ab. Änderungen sind, dass Ihre Benutzeroberfläche nicht aktualisiert wird, während die Netzwerkanforderung ausgeführt wird. Das heißt, Ihr Anwendungsfenster wird beschädigt. Dies hängt vom Betriebssystem ab, auf dem Sie sich befinden. In den meisten Fällen wird es jedoch nicht neu gezeichnet. Alles, was Sie über das Fenster ziehen, wird darauf verputzt, bis der Vorgang wieder im TK-Mainloop ausgeführt wird.
quelle