Fenster erstellen während Töne abspielen

Fragen zu Tkinter.
Antworten
Jones.Indiana
User
Beiträge: 8
Registriert: Sonntag 15. März 2020, 15:18

Hallo an alle,
ich habe folgendes Problem was ich nicht lösen kann.
Ich möchte ein rotes Quadrat darstellen während das Programm ein Ton abspielt und danach ein gelbes Quadrat darstellen während des Programm einen anderen Ton abspielt.
Wenn ich das Programm nun laufen lasse, dann kommen zuerst beide Töne hintereinander und erst dann kommt das Fenster mit beiden Quadraten gleichzeitig.
Hat jemand eine schlaue Idee woran das liegen kann?

from tkinter import *
import time
import winsound

fenster = Tk()
w = Canvas(fenster, width=500, height=500)
w.pack()
w.create_rectangle(65, 35, 135, 65, fill="yellow")
winsound.Beep(1000, 200)
time.sleep(2)
w.create_rectangle(205, 35, 275, 65, fill="red")
winsound.Beep(1000, 200)
time.sleep(2)
fenster.mainloop()

Danke schon mal.
Indy
Benutzeravatar
sparrow
User
Beiträge: 4536
Registriert: Freitag 17. April 2009, 10:28

Grafische Oberflächen funktionieren anders als du denkst. Die laufen nicht einfach nacheinander ab sondern sind ereignisgesteuert.
Der Mainloop ist eine Endlosschleife, der dafür sorgt, dass die GUI gezeichnet wird. Die darfst du auch nicht unterbrechen. Und bevor du da ankommst, wird gar nichts gezeichnet. Es nützt also nichts, vorher zu warten. Und es nützt auch nichts, das "einfach" irgendwie in den mainloop zu schieben, weil der nicht unterbrochen werden darf (und schlafen legen ist unterbrechen).

Ich bin in tkinter nicht so tief drin, aber ich denke wenn du dich etwas mehr einliest und nach der "after"-Methode suchst, wirst du dein Problem lösen können.
Sirius3
User
Beiträge: 18266
Registriert: Sonntag 21. Oktober 2012, 17:20

Man benutzt keine *-Importe, weil die hunderte Namen in den Namensraum schaufeln, und man nicht mehr nachvollziehen kann, woher welcher kommt.
sleep darf in GUI-Programmen nicht vorkommen, dafür kann man after verwenden, wenn man etwas zeitgesteuert ablaufen lassen will.
Zudem blockiert auch diese Beep, so dass man das in einen Hintergrundthread auslagern muß.

Code: Alles auswählen

import tkinter as tk
import winsound
import threading

def beep(frequency, duration):
    threading.Thread(target=winsound.Beep, args=(frequency, duration)).start()

def start(canvas):
    canvas.create_rectangle(65, 35, 135, 65, fill="yellow")
    beep(1000, 200)
    canvas.after(2000, end, canvas)

def end(canvas):
    canvas.create_rectangle(205, 35, 275, 65, fill="red")
    beep(1000, 200)

def main():
    fenster = tk.Tk()
    canvas = tk.Canvas(fenster, width=500, height=500)
    canvas.pack()
    canvas.after(500, start, canvas)
    fenster.mainloop()

if __name__ == '__main__':
    main()
Jones.Indiana
User
Beiträge: 8
Registriert: Sonntag 15. März 2020, 15:18

Danke Dir Sirius3
Damit kann ich was anfangen
Antworten