5 months ago

Python-Tk: Ein Neofetch-GUI selbst schreiben Teil 2



Der zweite Teil einer Einführung in die Python3-Bibliothek Tkinter und der lange Weg zum perfekten GUI.

Im ersten Teil dieser Serie habe ich mit einem Code-Beispiel abgeschlossen. Führen wir es aus, erhalten wir ein Fenster mit den Abmessungen 600×400 Pixel – mehr nicht. 

Es gibt mehrere Toolkits, um eine GUI-Anwendung zu schreiben. Wir verwenden Tkinter, das auf Tcl basiert. Daneben gibt es PyQt, das auf dem Qt-Framework aufbaut. Erwähnenswert ist auch PyGTK, das sich optisch perfekt in Gnome-basierte Umgebungen integriert.

Nun ist es verständlich, wenn beim Lesen Fragen aufkommen. "Warum sehen wir uns nicht gleich PyGTK an?" wäre eine berechtigte Frage. Die Antwort lautet, dass es nicht besonders einsteigerfreundlich ist. Vom Aufbau und der Syntax gibt es zu Tkinter einige Ähnlichkeiten, was das Lesen und Verstehen erleichtert, wenn man eines der beiden Toolkits beherrscht.

Ein großer Vorteil von Tkinter ist seine Flexibilität. Die Optik kann maximal konfiguriert und angepasst werden. Mit PyGTK sind wir hingegen an das strenge Korsett von Gnome gebunden.

Ein Nachteil von Tkinter ist, dass es sich nicht automatisch an die Systemoptik anpasst, wie z. B. an den Dark- und Light-Mode oder allgemeine farbliche Anpassungen. Es gibt jedoch einige Möglichkeiten und Tricks, mit denen man der Systemoptik näherkommen kann. Dazu mehr im weiteren Verlauf dieser Serie.

Das Grundgerüst

Jetzt schauen wir uns aber endlich den Code vom letzten Mal an.

import tkinter as tk # Erstelle das Hauptfenster root = tk.Tk() root.title("Neofetch-Tk") root.geometry("600x400") # Starte die Hauptschleife root.mainloop()

Erläuterung

import tkinter as tk
  • Importiert das tkinter-Modul und weist ihm das Alias tk zu. Dies ermöglicht es, auf Tkinter-Komponenten zuzugreifen, indem wir das Präfix tk. verwenden. Beispiel: tk.Button, tk.Label, tk.Tk usw. verwenden.
# Erstelle das Hauptfenster root = tk.Tk() root.title("Neofetch-Tk") root.geometry("600x400")
  • root = tk.Tk(): Diese Zeile erstellt das Hauptfenster der Anwendung und speichert es in der Variable root. tk.Tk() ist der Konstruktor für das Hauptfenster.
  • root.title("Neofetch-Tk"): Diese Zeile setzt den Titel des Fensters auf "Neofetch-Tk".
  • root.geometry("600x400"): Diese Zeile legt die Größe des Fensters auf 600x400 Pixel fest.
# Starte die Hauptschleife root.mainloop()
  • root.mainloop(): Diese Zeile startet die Haupt-Ereignisschleife der GUI. Diese Schleife wartet auf Benutzerinteraktionen wie Mausklicks oder Tastatureingaben und bleibt aktiv, bis das Fenster geschlossen wird. Ohne diese Schleife würde das Fenster sofort nach dem Öffnen wieder geschlossen werden.

Übrigens: Die Variable `root` kann jede beliebige Bezeichnung haben. Es ist egal, ob `main`, `mywindow`, usw. Die meisten Tutorials verwenden `root`.

Zwischenspiel: Zahlen, If-Statements und f-Strings

Python ist eine Sprache mit Konventionen. Variablennamen werden in Kleinbuchstaben geschrieben und Wörter werden mit Unterstrichen ("_") getrennt.

Richtig:
my_fav_int = 1234

Falsch:
MyFAV Int = 1234
MyFAVInt = 1234

Hier geht es um Leserlichkeit. Das erste falsche Beispiel wird außerdem einen Fehler erzeugen, da Variablennamen keine Leerzeichen enthalten dürfen.

Zahlen können als ganze Zahlen (int) oder Gleitkommazahlen (float) dargestellt werden. Eine Zahl in Anführungszeichen wird als String (Zeichenkette) behandelt und kann nicht direkt für mathematische Operationen verwendet werden.

Beispiele:

  • Ganze Zahl (int): my_integer = 1234
  • Gleitkommazahl (float): my_float = 12.34
  • Zeichenkette (String): my_string = "1234"

zahl = 1234 print(type(zahl)) zahl = 12.34 print(type(zahl)) zahl = "1234" print(type(zahl))

Ausgabe:

>>> <class 'int'> <class 'float'> <class 'str'>

Wir werden uns im Verlauf dieser Serie mit komplexeren Abläufen auseinandersetzen müssen. Das folgende Beispiel ist relativ einfach, aber amüsant genug, um im Gedächtnis zu bleiben.

Stellt euch vor, ihr habt ein Ei im Kühlschrank und möchtet das der Welt mitteilen (eier_menge = 1). Seit Python 3 ist es möglich, mit f-Strings zu arbeiten.

Ein String ist eine quotierte Zeichenfolge: "Hallo World". Wenn man ein "f" vor die Quotierung setzt und einen Inhalt in Klammern setzt, wird dieser in den String eingefügt. Hier die Variable "eier_menge".

eier_menge = 1 print(f"Ich hab {eier_menge} Ei im Kühlschrank")

Ausgabe:

>>> Ich hab 1 Ei im Kühlschrank

Wenn uns jemand ein weiteres Ei schenkt, haben wir ein Problem. Grammatikalisch korrekt ist "Ich habe 2 Ei im Kühlschrank" nämlich nicht!

Also fügen wir die Variable "check_plural" hinzu, sowie ein if-Statement: Wenn "eier_menge" 2 oder mehr entspricht, soll es Eier heißen. Statt "Ei" im String fest zu codieren, setzen wir die Variable "check_plural".

eier_menge = 2 check_plural = "Ei" if eier_menge >=2: check_plural = "Eier" print(f"Ich hab {eier_menge} {check_plural} im Kühlschrank")

Ausgabe:

>>> Ich hab 2 Eier im Kühlschrank

Wir werden aber noch etwas mehr Mathematik benötigen. Hier eine Textaufgabe:

print("Jutta hat doppelt so viele Eier wie Achim. Er besitzt genau 6 Eier. Jutta schenkt Achim die Hälfte ihrer Eier.\n\nFrage: Wie viele Eier hat Achim?") achims_eier = 6 juttas_eier = achims_eier * 2 check_plural = "Ei" if achims_eier >=2: check_plural = "Eier" print("\nLösung:\n") #print(f"Achim hat {achims_eier} {check_plural}") #print(f"Jutta hat {juttas_eier} {check_plural}") print(f"Achim hat die Hälfte von Juttas {juttas_eier} Eiern bekommen.\nEs sind genau {juttas_eier / 2 } {check_plural}.\nDas heißt, Achim hat jetzt {achims_eier + juttas_eier / 2} {check_plural}.")

Ausgabe:

Jutta hat doppelt so viele Eier wie Achim. Er besitzt genau 6 Eier. Jutta schenkt Achim die Hälfte ihrer Eier. Frage: Wie viele Eier hat Achim? Lösung: Achim hat die Hälfte von Juttas 12 Eiern bekommen. Es sind genau 6.0 Eier. Das heißt, Achim hat jetzt 12.0 Eier.

Wir haben hier die Variable "achims_eier" genommen. Diese wurde mit "juttas_eiern" gleichgesetzt und mit 2 multipliziert. Innerhalb des Ausgabetextes werden Juttas Eier innerhalb des f-Strings ausgegeben. Außerdem haben wir Juttas Eier durch 2 dividiert (juttas_eier / 2) und diesen Wert anschließend zu Achims Eiern addiert (achims_eier + juttas_eier / 2).

Zu beachten wäre noch der Escape-Character "\n", mit dem innerhalb eines Strings ein Absatz erzeugt werden kann.

Die Spalten

Wir erinnern uns: Das Schaubild aus Teil 1 hat das Fenster in zwei Spalten geteilt. Wir reden ab jetzt von Frames.

Read The Docs: Tkinter Frame Tutorial

Einen Frame Zeichnen

logo_frame = tk.Frame(root) logo_frame.pack()

Nun müsste der Code so aussehen:

import tkinter as tk # Erstelle das Hauptfenster root = tk.Tk() root.title("Neofetch-Tk") root.geometry("600x400") # Einen Frame Zeichen logo_frame = tk.Frame(root) logo_frame.pack() # Starte die Hauptschleife root.mainloop()

Starten wir den Code, so fällt auf, dass sich nichts verändert hat. Das liegt daran, dass der Frame die gleiche Farbe wie das Hauptfenster hat. Außerdem hat der Frame keinen Inhalt und deswegen die Größe eines Pixels. Um besser arbeiten zu können, fügen wir dem Frame, wie im Schaubild, die Farbe Gelb hinzu sowie die Eigenschaften "fill" und "expand".

logo_frame = tk.Frame(root,background="yellow") logo_frame.pack(fill="both", expand=True)

Die Logik:

  • Die Variable heißt "logo_frame"
  • Sie ist ein Frame
  • Der Frame ist in "root"
  • Der Hintergrund ist "yellow"
  • logo_frame.pack() weist an den Frame in root zu packen
  • fill="both" füllt die x- und y-Achse
  • expand=True sagt das soviel Raum wie möglich eingenommen werden soll

Wir benötigen aber noch einen zweiten Frame, und zwar auf der rechten Seite. Wir machen einfach Copy&Paste und ändern ein paar Kleinigkeiten.

# Einen Frame Zeichen logo_frame = tk.Frame(root,background="yellow") logo_frame.pack(fill="both",expand=True,side='left') # Zweiten Frame Zeichen stat_frame = tk.Frame(root,background="cyan") stat_frame.pack(fill="both",expand=True,side='left')

Die Logik:

  • side="left" oder LEFT lässt die Fenster nach LINKS ausrichten (nebeneinander)
  • Der Platz wird gleichmäßig aufgeteilt

Der ganze Code:

import tkinter as tk # Erstelle das Hauptfenster root = tk.Tk() root.title("Neofetch-Tk") root.geometry("600x400") # Einen Frame Zeichen logo_frame = tk.Frame(root,background="yellow") logo_frame.pack(fill="both",expand=True,side='left') # Zweiten Frame Zeichen stat_frame = tk.Frame(root,background="cyan") stat_frame.pack(fill="both",expand=True,side='left') # Starte die Hauptschleife root.mainloop()

Zum Schluss

Spielt ruhig ein wenig mit diesen Mechaniken herum.

Hier ist der gesamte Code auf Github.

Im nächsten Teil werden wir Informationen in das Fenster einbauen. Unser Code hat jetzt 16 Zeilen.


GNU/Linux.ch ist ein Community-Projekt. Bei uns kannst du nicht nur mitlesen, sondern auch selbst aktiv werden. Wir freuen uns, wenn du mit uns über die Artikel in unseren Chat-Gruppen oder im Fediverse diskutierst. Auch du selbst kannst Autor werden. Reiche uns deinen Artikelvorschlag über das Formular auf unserer Webseite ein.
Gesamten Artikel lesen

© Varient 2024. All rights are reserved