@__blackjack__: Okay, jetzt funktioniert `after_cancel()` so wie es soll. Danke für die Erklärung.
Die nächste Macke, die ich dem Programm gerne austreiben würde, ist, dass sich das Programm nach einem Klick auf "OK" im Ergebnisfenster (`results_window`) komplett beendet.
Dieser "OK"-Button wird im Programm mit folgendem Code erzeugt:
Code: Alles auswählen
ok_button = Button(results_window, text="OK", padx=10, pady=10, command=results_window.quit)
Nach meinem Verständnis müsste sich beim Aufruf von `results_window.quit` nur das Ergebnisfenster (`results_window`) schließen und nicht das komplette Programm, aber offensichtlich liege ich da etwas falsch. Wie macht man das richtig?
 Aktueller Code:
Code: Alles auswählen
from tkinter import Tk, Canvas, Toplevel, Frame, Label, Button, Listbox
from random import choice
import time
from statistics import mean
DESIGNATED_COLOR = "red"
SWITCH_TIME = 1000
class Game:
    def __init__(self, main_window):
        self.main_window = main_window
        self.colors = ["green", "red", "blue", "yellow", "black"]
        self.color = None
        self.reaction_times = []
        self.false_positives = 0
        self.color_missed = 0
        self.key_too_often_pressed = 0
        self.stop_test = False
        self.color_locked = False
        self.id_value_change_bg_color = 0
    def start_game(self):
        self.game_window = Toplevel(self.main_window)
        self.game_window.attributes("-fullscreen", True)
        self.canvas = Canvas(self.game_window,
                             width=self.game_window.winfo_screenwidth(),
                             height=self.game_window.winfo_screenheight(),
                             highlightthickness=0)
        self.canvas.pack()
        self.change_bg_color()
    def change_bg_color(self, color_locked = False):
        if self.stop_test:
            self.game_window.destroy()
        if not self.color_locked and self.color == DESIGNATED_COLOR:
            self.color_missed += 1
        self.color_locked = color_locked
        current_color = self.color
        while self.color == current_color:
            self.color = choice(self.colors)
        self.canvas.config(bg=self.color)
        self.start_time = time.monotonic() # Ereignis Timer
        self.id_value_change_bg_color = self.game_window.after(SWITCH_TIME, self.change_bg_color)
    def key_pressed(self):
        if self.color == DESIGNATED_COLOR:
            if self.color_locked:
                self.key_too_often_pressed += 1
            else:
                reaction_time = time.monotonic() - self.start_time
                self.reaction_times.append(reaction_time)
                self.color_locked = True
        else:
            self.false_positives += 1
    def show_results(self, event=None):
        self.game_window.after_cancel(self.id_value_change_bg_color)
        self.stop_test = True
        results_window = Toplevel(self.main_window)
        results_frame = Frame(results_window)
        results_window.title("Ergebnisse")
        if self.reaction_times:
            # mean() auf Liste ohne Einträge führt zu einem Fehler
            desc_mean_reaction_time = Label(results_frame, text="Gemittelte Reaktionszeit:")
            desc_reaction_times = Label(results_frame, text="Reaktionszeit pro richtiger Farbe:")
            result_mean_reaction_time = Label(results_frame, text=mean(self.reaction_times))
            result_reaction_times = Listbox(results_frame)
            for item in self.reaction_times:
                result_reaction_times.insert('end', item)
            desc_mean_reaction_time.grid(row=0, column=0)
            desc_reaction_times.grid(row=1, column=0)
            result_mean_reaction_time.grid(row=0, column=1)
            result_reaction_times.grid(row=1, column=1)
        desc_too_often = Label(results_frame, text="Bei richtiger Farbe zu oft gedrückt:")
        desc_color_missed = Label(results_frame, text="Bei richtiger Farbe nicht gedrückt:")
        desc_false_positives = Label(results_frame, text="Bei falscher Farbe gedrückt:")
        result_too_often = Label(results_frame, text=self.key_too_often_pressed)
        result_color_missed = Label(results_frame, text=self.color_missed)
        result_false_positives = Label(results_frame, text=self.false_positives)
        desc_too_often.grid(row=2, column=0)
        desc_color_missed.grid(row=3, column=0)
        desc_false_positives.grid(row=4, column=0)
        result_too_often.grid(row=2, column=1)
        result_color_missed.grid(row=3, column=1)
        result_false_positives.grid(row=4, column=1)
        results_frame.grid(row=0, column=0)
        ok_button = Button(results_window, text="OK", padx=10, pady=10, command=results_window.quit)
        ok_button.grid(row=1, column=0)
def main():
    main_window = Tk()
    game = Game(main_window)
    main_window.bind_all("<Escape>", lambda e: game.show_results())
    main_window.bind_all("<space>", lambda e: game.key_pressed()) # Ereignis Tastendruck
    main_window.title("Spiel")
    main_window.geometry('640x480')
    start_button = Button(main_window, text="Start", padx=10, pady=10, command=game.start_game)
    start_button.pack()
    close_button = Button(main_window, text="Schließen", padx=10, pady=10, command=main_window.quit)
    close_button.pack()
    main_window.mainloop()
if __name__ == '__main__':
    main()
 
Gruß
Atalanttore