Fenster aus Liste öffnen

Fragen zu Tkinter.
Antworten
WaltherDasSchaf
User
Beiträge: 2
Registriert: Montag 29. August 2022, 20:06

In meinem Programm will ich Fenster durch das Klicken eines Buttons öffnen, diese Fenster befinden sich in einer Liste. Sie werden auch direkt beim Start des Programmes geöffnet, aber nicht, wenn man den Button betätigt. Gibt es einen Weg die Fenster aus der Liste auf Klick des Buttons zu öffnen? Bin noch neu mit Python, es kann aber auch sein, dass ich einfach etwas offensichtliches übersehe
vielen Dank im Voraus :)

Code: Alles auswählen

import tkinter as tk

root = tk.Tk()
root.geometry("300x300")


def btn_1_click(fenster_name):
    fenster_liste[fenster_name]


btn_1 = tk.Button(root, width="5")
btn_1.pack(side="left")
fenster_liste = [tk.Tk().title("fenster1"), tk.Tk().title("fenster2")]
for idx, fenster in enumerate(fenster_liste):
    btn_1.config(command=btn_1_click(idx))

root.mainloop()
Sirius3
User
Beiträge: 18051
Registriert: Sonntag 21. Oktober 2012, 17:20

Es darf im gesamten Programm nur ein Tk-Exemplar geben. Weitere Fenster werden mit TopLevel erzeugt. Standardmäßig sind diese Fenster dann sichtbar. Man muß sie also explizit verstecken (withdraw).
Es darf keine globalen Variablen geben und Variablennamen sollten keine kryptischen Abkürzungen oder nichtssagende Nummern enthalten.
`command` muß eine Funktionsobjekt erhalten, und nicht den Rückgabewert nachdem die Funktion aufgerufen worden ist. Wenn eine Funktion Parameter braucht, benutzt man dafür functools.partial.
Ein Button kann nur ein `command` haben, also ist nur der letzte Wert der for-Schleife relevant.
Die Funktion btn_1_click macht nichts, denn mit dem Wert aus der Liste wird nichts gemacht. `fenster_name` ist eigentlich ein Index.
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ergänzend: `fenster_liste` Enthält keine Fenster. Ich hätte spontan vermutet es wären `None`-Werte, aber wir haben hier Tk, also sind es leere Zeichenketten. Was letztlich egal ist, es sind jedenfalls keine Fenster. Wären es auch nicht wenn man `Toplevel` verwendet.

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
WaltherDasSchaf
User
Beiträge: 2
Registriert: Montag 29. August 2022, 20:06

Vielen Dank für die schnellen und konkreten Antworten, ich werde versuchen das umzusetzen :)
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@WaltherDasSchaf: Noch ergänzend zu den Anmerkungen: `width` würde ich als Zahl angeben. Letztendlich geht das an Tcl/Tk was im Grunde nur Zeichenketten kann („stringly typed“ 🙂) aber es ist ja auch implizit Dokumentation für den Leser, das die Breite etwas ist mit dem man rechnen oder das man berechnen könnte.

Grunddatentypen haben in Namen nichts zu suchen. Den Typ ändert man öfter mal während der Programmentwicklung und dann hat man entweder falsche, irreführende Namen oder muss durch das Programm gehen und alle betroffenen Namen anpassen.

Da kommen wir dann auch gleich zu einem meiner Hauptgründe keine deutschsprachigen Bezeichner zu verwenden: Die Mehrzahl von einem Wort ist viel zu oft identisch mit der Einzahl, und dann bekommt man Probleme für eine Datenstruktur wie eine Liste und ein einzelnes Element daraus Namen zu finden, weil die Liste mit Fenstern `fenster` heissen müsste, und ein einzelnes Element daraus dann auch `fenster` was nicht geht oder zumindest sehr verwirrend ist. Im Englischen hat man dieses Problem nur sehr selten. Hier wäre es dann `windows` für die Liste und `window` für ein einzelnes Fenster.

Wenn es im `tkinter`-Modul eine Konstante für eine Zeichenkettenwert mit einer besonderen Bedeutung gibt, würde ich diese Konstante benutzen. Also hier ``tk.LEFT`` statt ``"left"``. Wenn man sich verschreibt, bekommt man einen `NameError`, den die IDE oder ein entsprechendes Editorplugin schon anzeigen kann.

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
from functools import partial


def show_windows(windows):
    for window in windows:
        window.wm_deiconify()


def main():
    root = tk.Tk()

    windows = []
    for i in range(2):
        window = tk.Toplevel()
        window.title(f"fenster{i + 1}")
        window.withdraw()
        windows.append(window)

    tk.Button(root, width=5, command=partial(show_windows, windows)).pack(
        side=tk.LEFT
    )
    root.mainloop()


if __name__ == "__main__":
    main()

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
Benutzeravatar
Dennis89
User
Beiträge: 1376
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

mir ist noch aufgefallen, dass man die 'for'-Schleife mit einem Startwert angeben könnte, dann muss man bei dem Fenstertitel nicht rechnen.

Code: Alles auswählen

    for window_number in range(1, 3):
        window = tk.Toplevel()
        window.title(f"fenster{window_number}")
        window.withdraw()
        windows.append(window)
Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten