Home
Navigation
Impressum
Coder Welten - Programmierung und Optimierung
Coder Welten
 
 

 

 

Tkinter: Events bei der Größenänderung von Fenstern binden

Größe von Fenstern und Frames anpassen

Das Modul Tkinter erlaubt Programmierern, gleich ob angehende oder bereits erfahrenen, die relativ einfache Erstellung von Anwendungen mit grafischen Benutzeroberflächen. Dennoch liegt die Tücke oftmals im Detail, zum Beispiel wenn es um die Anpassung von Layouts bei der Größenänderung von Fenstern durch den Nutzer geht. Doch Tkinter stellt auch in dieser Beziehung die eine oder andere nützliche Funktion oder Methode zur Verfügung, wenngleich diese sich dem Ein­steiger nicht unbedingt von selbst erklären.

Nachfolgend einige Beispiele, die mehr bisherigen Experimenten und weniger der Weisheit letzten Schluss entsprechen. Somit sollten diese Beispiele lediglich als eine Anregung verstanden werden, mehr nicht.

Als Ausgangspunkt für die ersten Beispiele dient ein kleines Fenster, welches durch zwei Frames aufgeteilt wird. Beiden Frames wurde zur besseren Unter­scheidung unterschiedliche Farbtöne für den Hintergrund zugwiesen.
Weiterhin soll bei einer Vergrößerung des Fensters der linke Frame seine Aus­gangs­breite ähnlich einer Sidebar beibehalten, der rechte Frame soll sich hingen aus­dehnen, soweit es die nutzbare Fläche innerhalb des Fensters ermöglicht.

Code und Ansicht des ersten Testfensters:

from tkinter import Tk, Frame

fenster=Tk()
fenster.title("Testfenster")
fenster.geometry("250x100")

frame_l = Frame(fenster, width = 125, height = 100, background = "#e68d00")
frame_r = Frame(fenster, width = 125, height = 100, background = "#ffc600")
frame_l.grid(row = 0, column = 0)
frame_r.grid(row = 0, column = 1)

fenster.mainloop()

Ansicht des ersten Testfensters
Ansicht des ersten Testfensters bei 250 x 100 Pixel.

Würde nun ein Nutzer den Wunsch verspüren, dieses Fenster zu vergrößern, wür­den die auf eine feste Anzahl von Pixel formatierten Frames sich nicht auto­matisch mitvergrößern und das Layout und Design einer grafischen Anwendung würde arg leiden. Im Endergebnis würde sich folgendes Bild ergeben.

Ansicht des ersten Testfensters bei Vergrößerung
Ansicht des ersten Testfensters bei größerer Darstellung.

Es gibt unterschiedliche Möglichkeiten, ein Layout und das Design auch bei einer größeren Darstellung der Fenster zu erhalten. Handelt es sich z.B. nur um kleine Abfrage- oder Mitteilungsfenster, lege es weder im Interesse des Entwicklers, noch im Interesse des Nutzers, diese seitenfüllend darzustellen. Um Abfrage- oder Mitteilungsfenster etwas an die Größe des verwendeten Endgerätes anzu­passen, könnte eine Funktion ähnlich der folgenden verwendet werden.

Im Beispiel öffnet das Fenster mit mindestens 250 x 100 Pixel. In den ersten Milli­sekunden erfolgt jedoch eine Abfrage von Screen und falls der Monitor größer als 800 x 600 Pixel ist, wird das Fenster mit 520 x 160 formatiert und mit resizable False auf diese Größe eingefroren.

Code für ein festes, in der Größe jedoch angepasstes Layout.

from tkinter import Tk, Frame

def messe_screen():
    w = int(fenster.winfo_screenwidth())
    h = int(fenster.winfo_screenheight())

    if w > 800 and h > 600:
        fenster.geometry("520x160")
        fenster.resizable(width = False, height = False)
        frame_l.config(width = 125, height = 160)
        frame_r.config(width = 395, height = 160)

fenster=Tk()
fenster.title("Testfenster")
fenster.geometry("250x100")

frame_l = Frame(fenster, width = 125, height = 100, background = "#e68d00")
frame_r = Frame(fenster, width = 125, height = 100, background = "#ffc600")
frame_l.grid(row = 0, column = 0)
frame_r.grid(row = 0, column = 1)

# Funktionsaufruf
messe_screen()

fenster.mainloop()

Soll sich ein mit Tkinter gestaltetes Fenster hingegen flexibel und dynamisch an eine Größenänderung durch den Nutzer anpassen, könnte ein Code ähnlich dem im nächsten Beispiel verwendeten benutzt werden.
In diesem Beispiel öffnet das Fenster in der ersten Millisekunde mit einer Größe von 250 x 100 Pixel, die Funktion "erste_messung" wird einmalig aufgerufen und aus­geführt, wobei die Frames anfänglich formatiert werden. Bei jeder Verän­derung der Position oder Größe des Fensters feuert jedoch die Event-Händler Funktion "neue_messung", wobei geprüft wird, ob das Fenster vergrößert wurde und falls ja, beide Frames in der Höhe und der rechte Frame in der Breite neu angepasst werden.

Code des Testfensters und Ansicht nach einer Vergrößerung durch den Nutzer:

from tkinter import Tk, Frame

def erste_messung():
    frw = int(fenster.winfo_reqwidth())
    frh = int(fenster.winfo_reqheight())

    if frw < 125:
        frame_l.config(width = 125, height = 100)
        frame_r.config(width = 125, height = 100)

def neue_messung(event):
    fw = int(event.width)
    fh = int(event.height)

    if fw > 125:
        frame_l.config(width = 125, height = fh)
        frame_r.config(width = fw,  height = fh)

fenster=Tk()
fenster.title("Testfenster")
fenster.geometry("250x100")

frame_l = Frame(fenster, background = "#e68d00")
frame_r = Frame(fenster, background = "#ffc600")

frame_l.grid(row = 0, column = 0)
frame_r.grid(row = 0, column = 1)

# Funktionsaufrufe
erste_messung()
fenster.bind("<Configure>", neue_messung)

fenster.mainloop()

Ansicht des dritten Testfensters
Ansicht des bei Vergrößerung neu konfigurierten Testfensters.

Bei allen Tests sollte in den Funktionen zur Kontrolle eine Ausgabe der Werte er­folgen. Dabei sollte bedacht werden, dass die Event-Handler Funktion bei Posi­tions­veränderungen und Größenänderungen fortlaufend feuert, doch nicht alle Werte verwendet werden können.

Beispiele:

print("1. erste_messung: " + str(frw)  + " x " + str(frh))

print("2. neue_messung: " + str(fw)  + " x " + str(fh))

Ausgabe:

Anfangswerte:

1. erste_messung: 200 x 200
2. neue_messung: 250 x 100
2. neue_messung: 250 x 100
2. neue_messung: 125 x 100

Bei Vergrößerung:

2. neue_messung: 330 x 246
2. neue_messung: 330 x 246 (Nur diese Werte mit if fw > 125 verwenden.)
2. neue_messung: 125 x 246 (Nicht diese Werte mit if fw > 125 or fh > 100 verwenden!)

Anpassung von Text-Widgets

Wie Textbereiche bei Größenänderungen anpassen und skalieren?

Textbereiche (Text-Widgets) lassen sich wie Frames oder andere Widgets dyna­misch bei Vergrößerung von Fenstern anpassen, nur sollte dabei bedacht werden, es handelt sich nicht um einen Zoom-Wert und auch nicht um Pixel, sondern um Zeilen und Zeichen. Die Grundeinstellung beträgt bei Text 24 Zeilen mit 80 Zeichen pro Zeile.
Wer denn nun unbedingt möchte, könnte in Erfahrung bringen, welcher Font bei welcher Größe wie viele Zeilen und Zeichen auf einem DIN A4 und auf einem DIN A5 Blatt hinterlassen würde und danach die Textfelder formatieren.

Nachfolgende Funktion diente bisher für den einen oder anderen Test mit unse­rem kleinen Notizbuch. Doch mehr als diverse Tests waren es bisher nicht.

Oben: Funktion für eine testweise Erweiterung des Notizbuches:

def neue_messung(event):
    fw = int(event.width)
    if fw > 640:
        textfld.config(width = 98, height = 58)

Unten: Funktionsaufruf vor mainloop:

fenster.bind("<Configure>", neue_messung)

Bei Text-Widgets bitte bedenken, es gibt seit Jahrhunderten einschlägige Erfah­rungen für optimale Satzspiegel (goldener Schnitt) sowie für die Anzahl von Zeilen und Zeichen.

 

Copyright © Verlag Horst Müller - Stendal - 2006 - Impressum - Datenschutz - Nutzungsbedingungen