Seite 2 von 2

Re: Methode von Objekt B aus Objekt A aufrufen funktioniert nicht

Verfasst: Samstag 13. Oktober 2018, 20:56
von Atalanttore
@__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

Re: Methode von Objekt B aus Objekt A aufrufen funktioniert nicht

Verfasst: Samstag 13. Oktober 2018, 21:07
von Sirius3
Wie kommst Du zu Deinem Verständnis, anstatt einfach in die Hilfe zu schauen:
Quit the Tcl interpreter. All widgets will be destroyed.
Du suchst `destroy`.

Re: Methode von Objekt B aus Objekt A aufrufen funktioniert nicht

Verfasst: Samstag 13. Oktober 2018, 21:26
von Atalanttore
@Sirius3: Kurze Zwischenfrage: Welche Hilfe verwendest du für Tkinter?

`results_window.destroy` funktioniert schon besser. Allerdings bleibt das `game_window` weiterhin im Vollbildmodus geöffnet, obwohl es durch `self.game_window.destroy()` in Zeile 40 doch eigentlich beendet werden sollte, wenn `self.stop_test` nach einem Druck auf die ESC-Taste wahr wird.

Gruß
Atalanttore