Nochmaliges starten eines Fenster geht nicht

Fragen zu Tkinter.
Antworten
WvonRiedi
User
Beiträge: 36
Registriert: Mittwoch 20. Januar 2021, 20:46

Ich starte mit Jupiter Notebook ein Fenster

Code: Alles auswählen


import tkinter as tk

def blinken():
    import blinken
 
fenster = tk.Tk()
fenster.geometry("200x100")
fenster.title("Neues Fenster starten")

button = tk.Button(fenster, text='Neues Fenster', width=20, command = blinken)
button.pack()

fenster.mainloop()
mit dieser Py Datei starte ich das "blinkende" Fenster

Code: Alles auswählen

import time 
import tkinter as tk
start = 0
farbe = 'gelb'

def blinken ():
    global start
    global farbe
    while start <= 5:
        time.sleep(1) 
        if farbe == 'gelb':
            fenster_alarm['bg'] = 'yellow'
            farbe = 'rot'
            start = start + 1
            fenster_alarm.update()
        else:
            fenster_alarm['bg'] = 'red'
            farbe = 'gelb'
            start = start + 1
            fenster_alarm.update()

fenster_alarm= tk.Tk()
fenster_alarm.title('Wechselnde Farbe') 
fenster_alarm.geometry('200x200') 
fenster_alarm.attributes("-topmost", True) 
fenster_alarm['bg'] = 'light blue' # die Hintergrundfarbe 
button = tk.Button(fenster_alarm, text='Beenden', width=10, command=fenster_alarm.destroy)
button.pack()

blinken()

fenster_alarm.mainloop() 
Wenn ich das "blinkende" Fenster schliesse, kann ich danach das "blinkende" Fenster nicht nochmals starten. Warum?

LG Werner
Benutzeravatar
pillmuncher
User
Beiträge: 1485
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Weil import nicht so funktioniert, wie du glaubst. Beim ersten Import eines Moduls während der Laufzeit eines Programms wird dieses Modul einmal ausgeführt und in die Liste der geladenen Module eingetragen. Wenn dasselbe Modul im dann nocheinmal importiert wird, wird es nicht nochmal ausgeführt, sondern einfach aus der Liste herausgesucht und verwendet. Deswegen benutzt man Importe auch nicht so, wie Du das tust. Import Statements stehen am Anfang eines Moduls/Programms und nicht in Funktionen, so wie du das ja auch mit time und tkinter gemacht hast.

global sollte man auch nicht verwenden. Statt dessen solltest du dich mit Klassen und OOP befassen. Wenn du grafische Benutzeroberflächen baust musst du das sowieso tun.

Es sollte außerdem nur eine Instanz von tkinter.Tk geben. Jede solche Instanz startet ihren eigenen Tcl-Interpreter und das braucht man eigentlich nie. In der Dokumentation steht sogar, dass man das tunlichst vermeiden sollte. Statt dessen verwendet man tkinter.Toplevel um zusätzliche Fenster zu erzeugen.

Es können auch nicht zwei mainloops zur selben Zeit im selben Thread laufen, weil dabei immer einer den anderen blockiert.

Statt einer while-Schleife solltest du eine for-Schleife verwenden.

Statt einer for-Schleife solltest du tkinter.after() vewenden, weil du sonst den mainloop blockierst.

Wenn etwas am Anfang oder am Ende jedes Zweiges eines if-else-Statements steht, also immer ausgeführt wird, egal welcher Zweig gewählt wird, braucht es offensichtlich nicht in diesem if-else-Statement zu stehen sondern davor oder danach. In diesem Fall kann man das if-else sogar ganz weglassen.

Wenn ich das alles beherzige, kommt ungefähr sowas raus:

Code: Alles auswählen

import time
import tkinter as tk


class BlinkWindow(tk.Toplevel):

    def __init__(self, master):
        super().__init__(master)
        self.title('Wechselnde Farbe')
        self.geometry('200x200')
        self.attributes("-topmost", True)
        self['bg'] = 'light blue' # die Hintergrundfarbe
        self.button = tk.Button(
                self,
                text='Beenden',
                width=10,
                command=self.destroy)
        self.button.pack()
        self.new_color, self.old_color = 'yellow', 'red'
        self.counter = 5
        self.blink()

    def blink(self):
        if self.counter > 0:
            self['bg'] = self.new_color
            self.update()
            self.new_color, self.old_color = self.old_color, self.new_color
            self.counter -= 1
            self.after(1000, self.blink)


class MainWindow(tk.Tk):

    def __init__(self):
        super().__init__()
        self.geometry("200x100")
        self.title("Neues Fenster starten")
        self.button = tk.Button(
                self,
                text='Neues Fenster',
                width=20,
                command=self.new_blink_window)
        self.button.pack()

    def new_blink_window(self):
        BlinkWindow(self)


main_window = MainWindow()
main_window.mainloop()
In specifications, Murphy's Law supersedes Ohm's.
WvonRiedi
User
Beiträge: 36
Registriert: Mittwoch 20. Januar 2021, 20:46

Danke für die ausführlichen Beschreibung. Da muss ich wohl noch einiges lernen.
Gruss Werner
WvonRiedi
User
Beiträge: 36
Registriert: Mittwoch 20. Januar 2021, 20:46

Nun läuft meine Uhr mit Wecker einwandfrei. Danke
Ich habe auch noch eine Musik beim Alarm hinterlegt (dies starte ich mit pygame). Wenn ich das Programm mit Jupyter Notebook starte höre ich die Musik .
Jedoch starte ich das Programm unter Windows direkt vom Autostart erscheint eine Fehlermeldung dass, das Modul pygame nicht gefunden wurde.
Wie installiere ich pygame richtig damit es auch vom Autostart gefunden wird?

Gruss Werner
Antworten