tkinter — Python-Schnittstelle zu Tcl/Tk¶
Quellcode: Lib/tkinter/__init__.py
Das Paket tkinter (Tk-Schnittstelle) ist die Standard-Python-Schnittstelle zum Tcl/Tk GUI-Toolkit. Sowohl Tk als auch tkinter sind auf den meisten Unix-Plattformen, einschließlich macOS, sowie auf Windows-Systemen verfügbar.
Wenn Sie python -m tkinter in der Befehlszeile ausführen, sollte ein Fenster geöffnet werden, das eine einfache Tk-Oberfläche demonstriert und Ihnen mitteilt, dass tkinter korrekt auf Ihrem System installiert ist. Außerdem wird die installierte Version von Tcl/Tk angezeigt, sodass Sie die Dokumentation zu Tcl/Tk lesen können, die spezifisch für diese Version ist.
Tkinter unterstützt eine Reihe von Tcl/Tk-Versionen, die entweder mit oder ohne Thread-Unterstützung kompiliert wurden. Die offizielle binäre Python-Distribution bündelt Tcl/Tk 8.6 mit Thread-Unterstützung. Weitere Informationen zu unterstützten Versionen finden Sie im Quellcode des Moduls _tkinter.
Tkinter ist keine dünne Hülle, sondern fügt eine beträchtliche Menge eigener Logik hinzu, um die Benutzererfahrung pythonischer zu gestalten. Diese Dokumentation konzentriert sich auf diese Ergänzungen und Änderungen und verweist für unveränderte Details auf die offizielle Tcl/Tk-Dokumentation.
Hinweis
Tcl/Tk 8.5 (2007) führte einen modernen Satz thematisierter Benutzeroberflächenkomponenten zusammen mit einer neuen API zu deren Verwendung ein. Sowohl die alte als auch die neue API sind weiterhin verfügbar. Die meisten online verfügbaren Dokumentationen verwenden noch die alte API und können veraltet sein.
Siehe auch
- TkDocs
Umfassendes Tutorial zur Erstellung von Benutzeroberflächen mit Tkinter. Erklärt Schlüsselkonzepte und veranschaulicht empfohlene Vorgehensweisen unter Verwendung der modernen API.
- Tkinter 8.5 Referenz: eine GUI für Python
Referenzdokumentation für Tkinter 8.5 mit Details zu verfügbaren Klassen, Methoden und Optionen.
Tcl/Tk Ressourcen
- Tk-Befehle
Umfassende Referenz für jeden der zugrundeliegenden Tcl/Tk-Befehle, die von Tkinter verwendet werden.
- Tcl/Tk Homepage
Zusätzliche Dokumentation und Links zur Kernentwicklung von Tcl/Tk.
Bücher
- Modern Tkinter for Busy Python Developers
Von Mark Roseman. (ISBN 978-1999149567)
- Python GUI programming with Tkinter
Von Alan D. Moore. (ISBN 978-1788835886)
- Programming Python
Von Mark Lutz; enthält eine ausgezeichnete Abdeckung von Tkinter. (ISBN 978-0596158101)
- Tcl and the Tk Toolkit (2nd edition)
Von John Ousterhout, Erfinder von Tcl/Tk, und Ken Jones; deckt Tkinter nicht ab. (ISBN 978-0321336330)
Architektur¶
Tcl/Tk ist keine einzelne Bibliothek, sondern besteht aus einigen separaten Modulen, jedes mit eigener Funktionalität und eigener offizieller Dokumentation. Die binären Python-Distributionen enthalten auch ein Add-on-Modul.
- Tcl
Tcl ist eine dynamische interpretierte Programmiersprache, ähnlich wie Python. Obwohl es eigenständig als Allzweck-Programmiersprache verwendet werden kann, wird es am häufigsten in C-Anwendungen als Skript-Engine oder als Schnittstelle zum Tk-Toolkit eingebettet. Die Tcl-Bibliothek verfügt über eine C-Schnittstelle zur Erstellung und Verwaltung einer oder mehrerer Instanzen eines Tcl-Interpreters, zur Ausführung von Tcl-Befehlen und Skripten in diesen Instanzen und zum Hinzufügen benutzerdefinierter Befehle, die entweder in Tcl oder C implementiert sind. Jeder Interpreter verfügt über eine Ereignisschleife und Einrichtungen zur Übermittlung von Ereignissen an diese und deren Verarbeitung. Im Gegensatz zu Python ist das Ausführungsmodell von Tcl auf kooperatives Multitasking ausgelegt, und Tkinter überbrückt diesen Unterschied (siehe Threading model für Details).
- Tk
Tk ist ein Tcl-Paket, das in C implementiert ist und benutzerdefinierte Befehle zur Erstellung und Manipulation von GUI-Widgets hinzufügt. Jedes
Tk-Objekt bettet seine eigene Tcl-Interpreterinstanz mit geladenem Tk ein. Die Widgets von Tk sind sehr anpassbar, allerdings auf Kosten eines veralteten Erscheinungsbilds. Tk verwendet die Tcl-Ereignisschleife, um GUI-Ereignisse zu generieren und zu verarbeiten.- Ttk
Themed Tk (Ttk) ist eine neuere Familie von Tk-Widgets, die ein wesentlich besseres Erscheinungsbild auf verschiedenen Plattformen bieten als viele der klassischen Tk-Widgets. Ttk wird seit Tk Version 8.5 als Teil von Tk vertrieben. Python-Bindings werden in einem separaten Modul,
tkinter.ttk, bereitgestellt.
Intern verwenden Tk und Ttk Einrichtungen des zugrunde liegenden Betriebssystems, d. h. Xlib unter Unix/X11, Cocoa unter macOS, GDI unter Windows.
Wenn Ihre Python-Anwendung eine Klasse in Tkinter verwendet, z. B. zur Erstellung eines Widgets, setzt das Modul tkinter zunächst eine Tcl/Tk-Befehlszeichenfolge zusammen. Diese Tcl-Befehlszeichenfolge wird an ein internes Binärmodul _tkinter übergeben, das dann den Tcl-Interpreter aufruft, um sie auszuwerten. Der Tcl-Interpreter ruft dann die Tk- und/oder Ttk-Pakete auf, die wiederum Xlib, Cocoa oder GDI aufrufen.
Tkinter-Module¶
Die Unterstützung für Tkinter ist auf mehrere Module verteilt. Die meisten Anwendungen benötigen das Hauptmodul tkinter sowie das Modul tkinter.ttk, das den modernen Satz thematisierter Widgets und die API bereitstellt.
from tkinter import *
from tkinter import ttk
- class tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=True, sync=False, use=None)¶
Konstruiert ein Top-Level-Tk-Widget, das normalerweise das Hauptfenster einer Anwendung ist, und initialisiert einen Tcl-Interpreter für dieses Widget. Jede Instanz hat ihren eigenen zugehörigen Tcl-Interpreter.
Die Klasse
Tkwird typischerweise mit allen Standardwerten instanziiert. Derzeit werden jedoch die folgenden Schlüsselwortargumente erkannt:- screenName
Wenn angegeben (als Zeichenkette), setzt die Umgebungsvariable
DISPLAY. (Nur X11)- baseName
Name der Profildatei. Standardmäßig wird *baseName* aus dem Programmnamen (
sys.argv[0]) abgeleitet.- className
Name der Widget-Klasse. Wird als Profildatei und auch als Name verwendet, mit dem Tcl aufgerufen wird (argv0 in interp).
- useTk
Wenn
True, wird das Tk-Subsystem initialisiert. Die Funktiontkinter.Tcl()setzt dies aufFalse.- sync
Wenn
True, werden alle X-Server-Befehle synchron ausgeführt, sodass Fehler sofort gemeldet werden. Kann zur Fehlersuche verwendet werden. (Nur X11)- use
Gibt die *id* des Fensters an, in das die Anwendung eingebettet werden soll, anstatt dass sie als unabhängiges Top-Level-Fenster erstellt wird. *id* muss auf die gleiche Weise angegeben werden wie der Wert für die -use Option für Top-Level-Widgets (d. h., sie hat die Form, die von
winfo_id()zurückgegeben wird).Beachten Sie, dass dies auf einigen Plattformen nur dann korrekt funktioniert, wenn *id* sich auf einen Tk-Frame oder ein Top-Level-Fenster bezieht, bei dem die Option -container aktiviert ist.
Tkliest und interpretiert Profildateien namens.className.tclund.baseName.tclin den Tcl-Interpreter und ruftexec()auf den Inhalt von.className.pyund.baseName.pyauf. Der Pfad für die Profildateien ist die UmgebungsvariableHOMEoder, falls diese nicht definiert ist, dannos.curdir.- tk¶
Das Tk-Anwendungsobjekt, das durch Instanziierung von
Tkerstellt wird. Dies bietet Zugriff auf den Tcl-Interpreter. Jedes Widget, das an dieselbe Instanz vonTkangehängt ist, hat denselben Wert für seintk-Attribut.
- master¶
Das Widget-Objekt, das dieses Widget enthält. Für
Tkist das *master*None, da es sich um das Hauptfenster handelt. Die Begriffe *master* und *parent* sind ähnlich und werden manchmal als Argumentnamen austauschbar verwendet; jedoch gibt der Aufruf vonwinfo_parent()eine Zeichenkette des Widget-Namens zurück, währendmasterdas Objekt zurückgibt. *parent*/*child* spiegelt die baumartige Beziehung wider, während *master*/*slave* die Containerstruktur widerspiegelt.
- tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=False)¶
Die Funktion
Tcl()ist eine Factory-Funktion, die ein Objekt erstellt, das dem von der KlasseTkerstellten Objekt ähnelt, mit dem Unterschied, dass das Tk-Subsystem nicht initialisiert wird. Dies ist am nützlichsten, wenn der Tcl-Interpreter in einer Umgebung gesteuert wird, in der man keine zusätzlichen Top-Level-Fenster erstellen möchte oder wo man dies nicht kann (wie z. B. unter Unix/Linux-Systemen ohne X-Server). Ein von einemTcl()-Objekt erstelltes Objekt kann ein Top-Level-Fenster haben, das durch Aufrufen seiner Methodeloadtk()erstellt wird (und das Tk-Subsystem initialisiert wird).
Die Module, die Tk-Unterstützung bieten, umfassen
tkinterHauptmodul Tkinter.
tkinter.colorchooserDialog zur Farbauswahl durch den Benutzer.
tkinter.commondialogBasisklasse für die Dialoge, die in den anderen hier aufgeführten Modulen definiert sind.
tkinter.filedialogAllgemeine Dialoge, die es dem Benutzer ermöglichen, eine zu öffnende oder zu speichernde Datei anzugeben.
tkinter.fontDienstprogramme zur Unterstützung der Arbeit mit Schriftarten.
tkinter.messageboxZugriff auf Standard-Tk-Dialogfelder.
tkinter.scrolledtextText-Widget mit einer integrierten vertikalen Scrollleiste.
tkinter.simpledialogGrundlegende Dialoge und Komfortfunktionen.
tkinter.ttkThematisierte Widget-Sammlung, eingeführt in Tk 8.5, die moderne Alternativen zu vielen der klassischen Widgets im Hauptmodul
tkinterbietet.
Zusätzliche Module
_tkinterEin Binärmodul, das die Low-Level-Schnittstelle zu Tcl/Tk enthält. Es wird automatisch vom Hauptmodul
tkinterimportiert und sollte niemals direkt von Anwendungsprogrammierern verwendet werden. Es ist normalerweise eine Shared Library (oder DLL), kann aber in einigen Fällen statisch mit dem Python-Interpreter verknüpft sein.idlelibPythons Integrierte Entwicklungs- und Lernumgebung (IDLE). Basiert auf
tkinter.tkinter.constantsSymbolische Konstanten, die anstelle von Zeichenketten verwendet werden können, wenn verschiedene Parameter an Tkinter-Aufrufe übergeben werden. Automatisch vom Hauptmodul
tkinterimportiert.tkinter.dnd(experimentell) Drag-and-Drop-Unterstützung für
tkinter. Dies wird veraltet sein, wenn es durch Tk DND ersetzt wird.turtleTurtle-Grafik in einem Tk-Fenster.
Tkinter Life Preserver¶
Dieser Abschnitt ist keine erschöpfende Einführung in Tk oder Tkinter. Dafür verweisen Sie auf eine der zuvor genannten externen Ressourcen. Stattdessen bietet dieser Abschnitt eine sehr schnelle Orientierung darüber, wie eine Tkinter-Anwendung aussieht, identifiziert grundlegende Tk-Konzepte und erklärt, wie die Tkinter-Hülle strukturiert ist.
Der Rest dieses Abschnitts hilft Ihnen, die Klassen, Methoden und Optionen zu identifizieren, die Sie in Ihrer Tkinter-Anwendung benötigen, und wo Sie detailliertere Dokumentationen dazu finden, einschließlich des offiziellen Tcl/Tk-Referenzhandbuchs.
Ein „Hallo Welt“-Programm¶
Wir beginnen mit einem „Hallo Welt“-Programm in Tkinter. Dies ist nicht das kleinste, das wir schreiben könnten, aber es enthält genug, um einige Schlüsselkonzepte zu veranschaulichen, die Sie kennen müssen.
from tkinter import *
from tkinter import ttk
root = Tk()
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
root.mainloop()
Nach den Importen erstellt die nächste Zeile eine Instanz der Klasse Tk, die Tk initialisiert und ihren zugehörigen Tcl-Interpreter erstellt. Sie erstellt auch ein Top-Level-Fenster, das als Hauptfenster der Anwendung bekannt ist.
Die folgende Zeile erstellt ein Frame-Widget, das in diesem Fall eine Beschriftung und eine Schaltfläche enthalten wird, die wir als Nächstes erstellen werden. Das Frame wird innerhalb des Hauptfensters platziert.
Die nächste Zeile erstellt ein Beschriftungs-Widget, das einen statischen Text enthält. Die Methode grid() wird verwendet, um das relative Layout (Position) der Beschriftung innerhalb ihres enthaltenden Frame-Widgets festzulegen, ähnlich wie Tabellen in HTML funktionieren.
Ein Schaltflächen-Widget wird dann erstellt und rechts neben der Beschriftung platziert. Wenn es gedrückt wird, ruft es die Methode destroy() des Hauptfensters auf.
Schließlich platziert die Methode mainloop() alles auf dem Bildschirm und reagiert auf Benutzereingaben, bis das Programm beendet wird.
Wichtige Tk-Konzepte¶
Selbst dieses einfache Programm veranschaulicht die folgenden Schlüsselkonzepte von Tk:
- Widgets
Eine Tkinter-Benutzeroberfläche besteht aus einzelnen *Widgets*. Jedes Widget wird als Python-Objekt dargestellt, das aus Klassen wie
ttk.Frame,ttk.Labelundttk.Buttoninstanziiert wird.- Widget-Hierarchie
Widgets sind in einer *Hierarchie* angeordnet. Die Beschriftung und die Schaltfläche waren in einem Frame enthalten, der wiederum im Hauptfenster enthalten war. Beim Erstellen jedes *Kind*-Widgets wird sein *Eltern*-Widget als erstes Argument an den Widget-Konstruktor übergeben.
- Konfigurationsoptionen
Widgets haben *Konfigurationsoptionen*, die ihr Aussehen und Verhalten ändern, wie z. B. den anzuzeigenden Text in einer Beschriftung oder Schaltfläche. Unterschiedliche Widget-Klassen haben unterschiedliche Optionssätze.
- Geometrie-Management
Widgets werden beim Erstellen nicht automatisch zur Benutzeroberfläche hinzugefügt. Ein *Geometrie-Manager* wie
gridsteuert, wo sie in der Benutzeroberfläche platziert werden.- Ereignisschleife
Tkinter reagiert auf Benutzereingaben, Änderungen durch Ihr Programm und aktualisiert sogar die Anzeige nur, wenn aktiv eine *Ereignisschleife* läuft. Wenn Ihr Programm die Ereignisschleife nicht ausführt, wird Ihre Benutzeroberfläche nicht aktualisiert.
Verständnis, wie Tkinter Tcl/Tk umschließt¶
Wenn Ihre Anwendung Tkinter-Klassen und -Methoden verwendet, setzt Tkinter intern Zeichenketten zusammen, die Tcl/Tk-Befehle darstellen, und führt diese Befehle im Tcl-Interpreter aus, der an die Tk-Instanz Ihrer Anwendung angehängt ist.
Ob Sie versuchen, in der Referenzdokumentation zu navigieren, die richtige Methode oder Option zu finden, vorhandenen Code anzupassen oder Ihre Tkinter-Anwendung zu debuggen, es ist hilfreich zu verstehen, wie diese zugrunde liegenden Tcl/Tk-Befehle aussehen.
Zur Veranschaulichung ist hier das Tcl/Tk-Äquivalent des Hauptteils des obigen Tkinter-Skripts.
ttk::frame .frm -padding 10
grid .frm
grid [ttk::label .frm.lbl -text "Hello World!"] -column 0 -row 0
grid [ttk::button .frm.btn -text "Quit" -command "destroy ."] -column 1 -row 0
Die Syntax von Tcl ähnelt vielen Shell-Sprachen, bei denen das erste Wort der auszuführende Befehl ist, gefolgt von den Argumenten zu diesem Befehl, getrennt durch Leerzeichen. Ohne zu viele Details zu erfahren, beachten Sie Folgendes:
Die Befehle zur Erstellung von Widgets (wie
ttk::frame) entsprechen den Widget-Klassen in Tkinter.Tcl-Widget-Optionen (wie
-text) entsprechen Schlüsselwortargumenten in Tkinter.Widgets werden in Tcl durch einen *Pfadnamen* referenziert (wie
.frm.btn), während Tkinter keine Namen, sondern Objektverweise verwendet.Die Position eines Widgets in der Widget-Hierarchie ist in seinem (hierarchischen) Pfadnamen kodiert, der einen
.(Punkt) als Pfadtrennzeichen verwendet. Der Pfadname für das Hauptfenster ist einfach.(Punkt). In Tkinter wird die Hierarchie nicht durch den Pfadnamen definiert, sondern durch die Angabe des Eltern-Widgets bei der Erstellung jedes Kind-Widgets.Operationen, die in Tcl als separate *Befehle* implementiert sind (wie
gridoderdestroy), werden als *Methoden* auf Tkinter-Widget-Objekten dargestellt. Wie Sie gleich sehen werden, verwendet Tcl zu anderen Zeiten Aufrufe, die wie Methoden auf Widget-Objekten aussehen, was dem in Tkinter verwendeten näher kommt.
Wie mache ich...? Welche Option...?¶
Wenn Sie unsicher sind, wie Sie etwas in Tkinter tun können, und es in der Tutorial- oder Referenzdokumentation, die Sie verwenden, nicht sofort finden, gibt es einige Strategien, die hilfreich sein können.
Erstens, denken Sie daran, dass die Details, wie einzelne Widgets funktionieren, je nach Version von Tkinter und Tcl/Tk variieren können. Wenn Sie nach Dokumentation suchen, stellen Sie sicher, dass sie mit den auf Ihrem System installierten Python- und Tcl/Tk-Versionen übereinstimmt.
Bei der Suche nach der Verwendung einer API ist es hilfreich, den genauen Namen der Klasse, Option oder Methode zu kennen, die Sie verwenden. Introspektion, entweder in einer interaktiven Python-Shell oder mit print(), kann Ihnen helfen, das zu identifizieren, was Sie brauchen.
Um herauszufinden, welche Konfigurationsoptionen für ein Widget verfügbar sind, rufen Sie seine Methode configure() auf, die ein Wörterbuch zurückgibt, das verschiedene Informationen über jedes Objekt enthält, einschließlich seiner Standard- und aktuellen Werte. Verwenden Sie keys(), um nur die Namen jeder Option zu erhalten.
btn = ttk.Button(frm, ...)
print(btn.configure().keys())
Da die meisten Widgets viele Konfigurationsoptionen gemeinsam haben, kann es hilfreich sein, herauszufinden, welche für eine bestimmte Widget-Klasse spezifisch sind. Ein Vergleich der Optionsliste mit der eines einfacheren Widgets, wie z. B. eines Frames, ist eine Möglichkeit, dies zu tun.
print(set(btn.configure().keys()) - set(frm.configure().keys()))
Ebenso können Sie die verfügbaren Methoden für ein Widget-Objekt mit der Standardfunktion dir() finden. Wenn Sie es ausprobieren, werden Sie feststellen, dass es über 200 gängige Widget-Methoden gibt, daher ist die Identifizierung der spezifischen Methoden für eine Widget-Klasse hilfreich.
print(dir(btn))
print(set(dir(btn)) - set(dir(frm)))
Threading-Modell¶
Python und Tcl/Tk haben sehr unterschiedliche Threading-Modelle, die tkinter zu überbrücken versucht. Wenn Sie Threads verwenden, müssen Sie sich dessen möglicherweise bewusst sein.
Ein Python-Interpreter kann viele Threads enthalten, die mit ihm assoziiert sind. In Tcl können mehrere Threads erstellt werden, aber jeder Thread hat einen separaten Tcl-Interpreter, der mit ihm assoziiert ist. Threads können auch mehr als eine Interpreterinstanz erstellen, obwohl jede Interpreterinstanz nur von dem Thread verwendet werden kann, der sie erstellt hat.
Jedes von tkinter erstellte Tk-Objekt enthält einen Tcl-Interpreter. Es merkt sich auch, welcher Thread diesen Interpreter erstellt hat. Aufrufe von tkinter können von jedem Python-Thread erfolgen. Intern, wenn ein Aufruf von einem anderen Thread als dem stammt, der das Tk-Objekt erstellt hat, wird ein Ereignis in die Ereigniswarteschlange des Interpreters gestellt und, wenn es ausgeführt wird, das Ergebnis an den aufrufenden Python-Thread zurückgegeben.
Tcl/Tk-Anwendungen sind normalerweise ereignisgesteuert, was bedeutet, dass der Interpreter nach der Initialisierung eine Ereignisschleife ausführt (d. h. Tk.mainloop()) und auf Ereignisse reagiert. Da es sich um einen einzelnen Thread handelt, müssen Ereignisbehandler schnell reagieren, da sie sonst andere Ereignisse blockieren würden. Um dies zu vermeiden, sollten lang andauernde Berechnungen nicht in einem Ereignisbehandler ausgeführt werden, sondern entweder mit Timern in kleinere Teile zerlegt oder in einem anderen Thread ausgeführt werden. Dies unterscheidet sich von vielen GUI-Toolkits, bei denen die GUI in einem völlig separaten Thread von allem Anwendungscode, einschließlich Ereignisbehandlern, ausgeführt wird.
Wenn der Tcl-Interpreter die Ereignisschleife nicht ausführt und keine Ereignisse verarbeitet, schlagen alle tkinter-Aufrufe, die von anderen Threads als dem, der den Tcl-Interpreter ausführt, erfolgen, fehl.
Es gibt eine Reihe von Sonderfällen
Tcl/Tk-Bibliotheken können so kompiliert werden, dass sie nicht thread-fähig sind. In diesem Fall ruft
tkinterdie Bibliothek aus dem ursprünglichen Python-Thread auf, auch wenn dies anders ist als der Thread, der den Tcl-Interpreter erstellt hat. Eine globale Sperre stellt sicher, dass nur ein Aufruf gleichzeitig erfolgt.Während
tkinterIhnen erlaubt, mehr als eine Instanz einesTk-Objekts (mit eigenem Interpreter) zu erstellen, teilen sich alle Interpreter, die Teil desselben Threads sind, eine gemeinsame Ereigniswarteschlange, was schnell unübersichtlich wird. In der Praxis sollten Sie nicht mehr als eine Instanz vonTkgleichzeitig erstellen. Andernfalls ist es am besten, sie in separaten Threads zu erstellen und sicherzustellen, dass Sie eine thread-fähige Tcl/Tk-Version verwenden.Blockierende Ereignisbehandler sind nicht die einzige Möglichkeit, den Tcl-Interpreter daran zu hindern, die Ereignisschleife erneut aufzurufen. Es ist sogar möglich, mehrere verschachtelte Ereignisschleifen auszuführen oder die Ereignisschleife ganz zu verlassen. Wenn Sie bei Ereignissen oder Threads etwas kniffliges tun, sollten Sie sich dieser Möglichkeiten bewusst sein.
Es gibt einige wenige ausgewählte
tkinter-Funktionen, die derzeit nur funktionieren, wenn sie vom Thread aufgerufen werden, der den Tcl-Interpreter erstellt hat.
Praktische Referenz¶
Optionen setzen¶
Optionen steuern Dinge wie die Farbe und Randbreite eines Widgets. Optionen können auf drei Arten gesetzt werden
- Zum Zeitpunkt der Objekterstellung unter Verwendung von Schlüsselwortargumenten
fred = Button(self, fg="red", bg="blue")
- Nach der Objekterstellung, wobei der Optionsname wie ein Wörterbuchindex behandelt wird
fred["fg"] = "red" fred["bg"] = "blue"
- Verwenden Sie die Methode config(), um nach der Objekterstellung mehrere Attribute zu aktualisieren
fred.config(fg="red", bg="blue")
Eine vollständige Erklärung einer gegebenen Option und ihres Verhaltens finden Sie in den Tk-Manpages für das betreffende Widget.
Beachten Sie, dass die Manpages "STANDARDOPTIONS" und "WIDGET SPECIFIC OPTIONS" für jedes Widget auflisten. Erstere ist eine Liste von Optionen, die vielen Widgets gemeinsam sind, letztere sind die Optionen, die für dieses spezielle Widget eigen sind. Die Standardoptionen sind auf der Manpage options(3) dokumentiert.
In diesem Dokument wird keine Unterscheidung zwischen Standard- und Widget-spezifischen Optionen gemacht. Einige Optionen gelten nicht für bestimmte Widget-Typen. Ob ein gegebenes Widget auf eine bestimmte Option reagiert, hängt von der Widget-Klasse ab; Buttons haben eine command-Option, Labels nicht.
Die von einem gegebenen Widget unterstützten Optionen sind in der Manpage dieses Widgets aufgeführt oder können zur Laufzeit abgefragt werden, indem die Methode config() ohne Argumente aufgerufen wird oder indem die Methode keys() für dieses Widget aufgerufen wird. Der Rückgabewert dieser Aufrufe ist ein Wörterbuch, dessen Schlüssel der Name der Option als Zeichenkette ist (z. B. 'relief') und dessen Werte 5-Tupel sind.
Einige Optionen, wie bg, sind Synonyme für gängige Optionen mit langen Namen (bg ist eine Abkürzung für "background"). Die Übergabe des Namens einer Kurzform-Option an die Methode config() gibt ein 2-Tupel zurück, nicht ein 5-Tupel. Das zurückgegebene 2-Tupel enthält den Namen des Synonyms und die "wirkliche" Option (z. B. ('bg', 'background')).
Index |
Bedeutung |
Beispiel |
|---|---|---|
0 |
Optionsname |
|
1 |
Optionsname für Datenbankabfrage |
|
2 |
Optionenklasse für Datenbankabfrage |
|
3 |
Standardwert |
|
4 |
Aktueller Wert |
|
Beispiel
>>> print(fred.config())
{'relief': ('relief', 'relief', 'Relief', 'raised', 'groove')}
Natürlich enthält das ausgegebene Wörterbuch alle verfügbaren Optionen und ihre Werte. Dies ist nur als Beispiel gedacht.
Der Packer¶
Der Packer ist einer der Geometrie-Management-Mechanismen von Tk. Geometrie-Manager werden verwendet, um die relative Positionierung von Widgets innerhalb ihres Containers – ihres gegenseitigen *Meisters* – festzulegen. Im Gegensatz zum umständlicheren *Placer* (der weniger häufig verwendet wird und hier nicht behandelt wird) verwendet der Packer qualitative Bezeichner – *über*, *links von*, *füllend* usw. – und arbeitet alles aus, um die genauen Positionierungskoordinaten für Sie zu ermitteln.
Die Größe jedes *Master*-Widgets wird durch die Größe der darin enthaltenen "Slave-Widgets" bestimmt. Der Packer wird verwendet, um zu steuern, wo Slave-Widgets innerhalb des Masters erscheinen, in den sie gepackt werden. Sie können Widgets in Frames packen und Frames in andere Frames, um das gewünschte Layout zu erzielen. Darüber hinaus passt sich die Anordnung dynamisch an inkrementelle Änderungen der Konfiguration an, sobald sie gepackt ist.
Beachten Sie, dass Widgets erst erscheinen, wenn ihre Geometrie mit einem Geometrie-Manager angegeben wurde. Es ist ein häufiger anfänglicher Fehler, die Geometrieangabe wegzulassen und sich dann zu wundern, warum das Widget erstellt wurde, aber nichts angezeigt wird. Ein Widget erscheint erst, nachdem beispielsweise die pack()-Methode des Packers darauf angewendet wurde.
Die pack()-Methode kann mit Schlüsselwort-Option-/Wert-Paaren aufgerufen werden, die steuern, wo das Widget innerhalb seines Containers erscheinen soll und wie es sich verhalten soll, wenn das Hauptanwendungsfenster vergrößert wird. Hier sind einige Beispiele
fred.pack() # defaults to side = "top"
fred.pack(side="left")
fred.pack(expand=1)
Packer-Optionen¶
Weitere ausführliche Informationen über den Packer und die von ihm akzeptierten Optionen finden Sie in den Manpages und auf Seite 183 von John Ousterhout's Buch.
- anchor
Ankertyp. Bezeichnet, wo der Packer jeden Slave in seinem Feld platzieren soll.
- expand
Boolesch,
0oder1.- fill
Gültige Werte:
'x','y','both','none'.- ipadx und ipady
Ein Abstand – der den inneren Abstand auf jeder Seite des Slave-Widgets bezeichnet.
- padx und pady
Ein Abstand – der den äußeren Abstand auf jeder Seite des Slave-Widgets bezeichnet.
- side
Gültige Werte sind:
'left','right','top','bottom'.
Widget-Variablen koppeln¶
Der aktuelle Wert einiger Widgets (wie Text-Eingabefelder) kann über spezielle Optionen direkt mit Anwendungsvariablen verbunden werden. Diese Optionen sind variable, textvariable, onvalue, offvalue und value. Diese Verbindung funktioniert in beide Richtungen: Wenn sich die Variable aus irgendeinem Grund ändert, wird das Widget, mit dem sie verbunden ist, aktualisiert, um den neuen Wert widerzuspiegeln.
Leider ist es in der aktuellen Implementierung von tkinter nicht möglich, eine beliebige Python-Variable über eine variable- oder textvariable-Option an ein Widget zu übergeben. Die einzigen Arten von Variablen, für die dies funktioniert, sind Variablen, die von einer Klasse namens Variable abgeleitet sind, die in tkinter definiert ist.
Es gibt viele nützliche Unterklassen von Variable, die bereits definiert sind: StringVar, IntVar, DoubleVar und BooleanVar. Um den aktuellen Wert einer solchen Variablen zu lesen, rufen Sie die Methode get() darauf auf, und um ihren Wert zu ändern, rufen Sie die Methode set() auf. Wenn Sie dieses Protokoll befolgen, wird das Widget immer den Wert der Variablen verfolgen, ohne dass Sie weitere Eingriffe vornehmen müssen.
Zum Beispiel
import tkinter as tk
class App(tk.Frame):
def __init__(self, master):
super().__init__(master)
self.pack()
self.entrythingy = tk.Entry()
self.entrythingy.pack()
# Create the application variable.
self.contents = tk.StringVar()
# Set it to some value.
self.contents.set("this is a variable")
# Tell the entry widget to watch this variable.
self.entrythingy["textvariable"] = self.contents
# Define a callback for when the user hits return.
# It prints the current value of the variable.
self.entrythingy.bind('<Key-Return>',
self.print_contents)
def print_contents(self, event):
print("Hi. The current entry content is:",
self.contents.get())
root = tk.Tk()
myapp = App(root)
myapp.mainloop()
Der Fenstermanager¶
In Tk gibt es einen Dienstprogramm-Befehl, wm, zur Interaktion mit dem Fenstermanager. Optionen für den wm-Befehl erlauben Ihnen, Dinge wie Titel, Platzierung, Icon-Bitmaps und Ähnliches zu steuern. In tkinter wurden diese Befehle als Methoden der Klasse Wm implementiert. Toplevel-Widgets sind von der Klasse Wm abgeleitet und können daher die Wm-Methoden direkt aufrufen.
Um auf das Toplevel-Fenster zuzugreifen, das ein gegebenes Widget enthält, können Sie oft einfach auf den Master des Widgets verweisen. Wenn das Widget natürlich in einen Frame gepackt wurde, repräsentiert der Master kein Toplevel-Fenster. Um auf das Toplevel-Fenster zuzugreifen, das ein beliebiges Widget enthält, können Sie die Methode _root() aufrufen. Diese Methode beginnt mit einem Unterstrich, um zu kennzeichnen, dass diese Funktion Teil der Implementierung ist und keine Schnittstelle zur Tk-Funktionalität darstellt.
Hier sind einige Beispiele für typische Verwendungen
import tkinter as tk
class App(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
# create the application
myapp = App()
#
# here are method calls to the window manager class
#
myapp.master.title("My Do-Nothing Application")
myapp.master.maxsize(1000, 400)
# start the program
myapp.mainloop()
Tk Options-Datentypen¶
- anchor
Gültige Werte sind Himmelsrichtungen:
"n","ne","e","se","s","sw","w","nw", und auch"center".- bitmap
Es gibt acht eingebaute, benannte Bitmaps:
'error','gray25','gray50','hourglass','info','questhead','question','warning'. Um einen X-Bitmap-Dateinamen anzugeben, geben Sie den vollständigen Pfad zur Datei an, dem ein@vorangestellt ist, wie in"@/usr/contrib/bitmap/gumby.bit".- boolean
Sie können die Ganzzahlen 0 oder 1 oder die Zeichenketten
"yes"oder"no"übergeben.- callback
Dies ist jede Python-Funktion, die keine Argumente entgegennimmt. Zum Beispiel
def print_it(): print("hi there") fred["command"] = print_it
- color
Farben können als X-Farbnamen aus der Datei rgb.txt oder als Zeichenketten angegeben werden, die RGB-Werte in 4 Bit darstellen:
"#RGB", 8 Bit:"#RRGGBB", 12 Bit:"#RRRGGGBBB"oder 16 Bit:"#RRRRGGGGBBBB"-Bereiche, wobei R,G,B hier jede gültige Hexadezimalziffer darstellen. Einzelheiten finden Sie auf Seite 160 von Ousterhout's Buch.- cursor
Die Standard-X-Cursor-Namen aus
cursorfont.hkönnen ohne das PräfixXC_verwendet werden. Um beispielsweise einen Hand-Cursor (XC_hand2) zu erhalten, verwenden Sie die Zeichenkette"hand2". Sie können auch eine eigene Bitmap- und Maskendatei angeben. Einzelheiten finden Sie auf Seite 179 von Ousterhout's Buch.- distance
Bildschirmabstände können entweder in Pixeln oder in absoluten Entfernungen angegeben werden. Pixel werden als Zahlen und absolute Entfernungen als Zeichenketten angegeben, wobei das nachgestellte Zeichen die Einheiten bezeichnet:
cfür Zentimeter,ifür Zoll,mfür Millimeter,pfür typografische Punkte. Zum Beispiel werden 3,5 Zoll als"3.5i"angegeben.- font
Tk verwendet ein Listen-Schriftart-Namensformat, wie z. B.
{courier 10 bold}. Schriftgrößen mit positiven Zahlen werden in Punkten gemessen; Größen mit negativen Zahlen werden in Pixeln gemessen.- geometry
Dies ist eine Zeichenkette der Form
widthxheight, wobei Breite und Höhe für die meisten Widgets in Pixeln (für Widgets, die Text anzeigen, in Zeichen) gemessen werden. Zum Beispiel:fred["geometry"] = "200x100".- justify
Gültige Werte sind die Zeichenketten:
"left","center","right"und"fill".- region
Dies ist eine Zeichenkette mit vier durch Leerzeichen getrennten Elementen, von denen jedes eine gültige Distanz ist (siehe oben). Zum Beispiel:
"2 3 4 5"und"3i 2i 4.5i 2i"und"3c 2c 4c 10.43c"sind alles gültige Regionen.- relief
Bestimmt den Randstil eines Widgets. Gültige Werte sind:
"raised","sunken","flat","groove"und"ridge".- scrollcommand
Dies ist fast immer die Methode
set()einer Scrollbar, kann aber jede Widget-Methode sein, die ein einzelnes Argument annimmt.- wrap
Muss einer der folgenden Werte sein:
"none","char"oder"word".
Bindungen und Ereignisse¶
Die Methode bind des Widget-Befehls ermöglicht es Ihnen, auf bestimmte Ereignisse zu warten und eine Callback-Funktion auszulösen, wenn dieser Ereignistyp auftritt. Die Form der bind-Methode ist
def bind(self, sequence, func, add=''):
wobei
- sequenz
eine Zeichenkette ist, die die Zielart des Ereignisses bezeichnet. (Einzelheiten finden Sie in der Manpage bind(3tk) und auf Seite 201 von John Ousterhout's Buch Tcl and the Tk Toolkit (2nd edition)).
- func
eine Python-Funktion ist, die ein Argument entgegennimmt und aufgerufen wird, wenn das Ereignis eintritt. Eine Event-Instanz wird als Argument übergeben. (So eingesetzte Funktionen werden gemeinhin als *Callbacks* bezeichnet.)
- add
optional ist, entweder
''oder'+'. Die Übergabe einer leeren Zeichenkette bedeutet, dass diese Bindung alle anderen mit diesem Ereignis verbundenen Bindungen ersetzen soll. Die Übergabe von'+'bedeutet, dass diese Funktion zur Liste der an diesen Ereignistyp gebundenen Funktionen hinzugefügt werden soll.
Zum Beispiel
def turn_red(self, event):
event.widget["activeforeground"] = "red"
self.button.bind("<Enter>", self.turn_red)
Beachten Sie, wie auf das widget-Feld des Ereignisses in der turn_red()-Callback zugegriffen wird. Dieses Feld enthält das Widget, das das X-Ereignis abgefangen hat. Die folgende Tabelle listet die anderen Ereignisfelder auf, auf die Sie zugreifen können, und wie sie in Tk bezeichnet werden, was beim Nachschlagen in den Tk-Manpages nützlich sein kann.
Tk |
Tkinter-Ereignisfeld |
Tk |
Tkinter-Ereignisfeld |
|---|---|---|---|
%f |
focus |
%A |
char |
%h |
height |
%E |
send_event |
%k |
keycode |
%K |
keysym |
%s |
state |
%N |
keysym_num |
%t |
time |
%T |
type |
%w |
width |
%W |
widget |
%x |
x |
%X |
x_root |
%y |
y |
%Y |
y_root |
Der Index-Parameter¶
Eine Reihe von Widgets erfordert die Übergabe von "Index"-Parametern. Diese werden verwendet, um auf eine bestimmte Stelle in einem Text-Widget, auf einzelne Zeichen in einem Eingabe-Widget oder auf einzelne Menüpunkte in einem Menü-Widget zu verweisen.
- Eingabe-Widget-Indizes (index, view index usw.)
Eingabe-Widgets haben Optionen, die sich auf Zeichenpositionen im angezeigten Text beziehen. Sie können diese
tkinter-Funktionen verwenden, um auf diese speziellen Punkte in Text-Widgets zuzugreifen- Text-Widget-Indizes
Die Index-Notation für Text-Widgets ist sehr reichhaltig und wird am besten in den Tk-Manpages beschrieben.
- Menü-Indizes (menu.invoke(), menu.entryconfig() usw.)
Einige Optionen und Methoden für Menüs manipulieren spezifische Menüeinträge. Wann immer ein Menüindex für eine Option oder einen Parameter benötigt wird, können Sie Folgendes übergeben:
eine Ganzzahl, die sich auf die numerische Position des Eintrags im Widget bezieht, gezählt von oben, beginnend mit 0;
die Zeichenkette
"active", die sich auf die Menüposition bezieht, die sich gerade unter dem Cursor befindet;die Zeichenkette
"last", die sich auf den letzten Menüeintrag bezieht;eine Ganzzahl, der ein
@vorangestellt ist, wie in@6, wobei die Ganzzahl als y-Pixelkoordinate im Koordinatensystem des Menüs interpretiert wird;die Zeichenkette
"none", die keinen Menüeintrag angibt, am häufigsten verwendet mit menu.activate(), um alle Einträge zu deaktivieren, und schließlich,eine Textzeichenkette, die mit dem Label des Menüeintrags abgeglichen wird, gescannt von oben nach unten des Menüs. Beachten Sie, dass dieser Index-Typ nach allen anderen betrachtet wird, was bedeutet, dass Übereinstimmungen für Menüeinträge mit den Labels
last,activeodernonestattdessen als die oben genannten Literale interpretiert werden können.
Bilder¶
Bilder verschiedener Formate können über die entsprechende Unterklasse von tkinter.Image erstellt werden
BitmapImagefür Bilder im XBM-Format.PhotoImagefür Bilder in den Formaten PGM, PPM, GIF und PNG. Letzteres wird ab Tk 8.6 unterstützt.
Jeder Bildtyp wird über die Option file oder data erstellt (andere Optionen sind ebenfalls verfügbar).
Geändert in Version 3.13: Hinzugefügt wurde die Methode PhotoImage copy_replace() zum Kopieren eines Bereichs von einem Bild in ein anderes Bild, möglicherweise mit Pixelzooming und/oder Untersampling. Hinzugefügt wurde der Parameter *from_coords* zu den Methoden PhotoImage copy(), zoom() und subsample(). Hinzugefügt wurden die Parameter *zoom* und *subsample* zur Methode PhotoImage copy().
Das Bildobjekt kann dann überall dort verwendet werden, wo eine image-Option von einem Widget unterstützt wird (z. B. Labels, Buttons, Menüs). In diesen Fällen behält Tk keine Referenz auf das Bild. Wenn die letzte Python-Referenz auf das Bildobjekt gelöscht wird, werden auch die Bilddaten gelöscht, und Tk zeigt eine leere Box an, wo das Bild verwendet wurde.
Siehe auch
Das Paket Pillow fügt Unterstützung für Formate wie BMP, JPEG, TIFF und WebP hinzu.
Datei-Handler¶
Tk erlaubt Ihnen, eine Callback-Funktion zu registrieren und zu de-registrieren, die von der Tk-Mainloop aufgerufen wird, wenn E/A auf einem File-Deskriptor möglich ist. Nur ein Handler kann pro File-Deskriptor registriert werden. Beispielcode
import tkinter
widget = tkinter.Tk()
mask = tkinter.READABLE | tkinter.WRITABLE
widget.tk.createfilehandler(file, mask, callback)
...
widget.tk.deletefilehandler(file)
Diese Funktion ist unter Windows nicht verfügbar.
Da Sie nicht wissen, wie viele Bytes zum Lesen verfügbar sind, möchten Sie vielleicht nicht die Methoden BufferedIOBase oder TextIOBase read() oder readline() verwenden, da diese darauf bestehen, eine vordefinierte Anzahl von Bytes zu lesen. Für Sockets funktionieren die Methoden recv() oder recvfrom() einwandfrei; für andere Dateien verwenden Sie Roh-Reads oder os.read(file.fileno(), maxbytecount).
- Widget.tk.createfilehandler(file, mask, func)¶
Registriert die Callback-Funktion *func* für den Datei-Handler. Das Argument *file* kann entweder ein Objekt mit einer
fileno()-Methode (wie ein Datei- oder Socket-Objekt) oder ein Integer-File-Deskriptor sein. Das Argument *mask* ist eine OR-Kombination der drei unten genannten Konstanten. Der Callback wird wie folgt aufgerufencallback(file, mask)
- Widget.tk.deletefilehandler(file)¶
De-registriert einen Datei-Handler.