MacOS Schließen über das App-Menü verhindern

Fragen zu Tkinter.
Antworten
Haiko
User
Beiträge: 1
Registriert: Sonntag 5. September 2021, 18:54

Ich habe eine Python-App erstellt, die einen länger laufenden Prozess ausführt. Der Prozess wird in einem Thread ausgeführt. Während des Prozesses soll ein schließen der App verhindert werden. Folgenden Code habe ich implementiert:

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk, messagebox
import threading
import time

class App:
    def __init__(self, root):
        self.root = root
        self.root.title("Tkinter Thread Example")

        self.message = tk.Label(root, text="Press the button to start the process")
        self.message.pack(pady=10)
        self.progress = ttk.Progressbar(root, orient="horizontal", length=300, mode="determinate")
        self.progress.pack(pady=20)

        menubar = tk.Menu(root)
        root.config(menu=menubar)

        self.file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=self.file_menu)
        self.file_menu.add_command(label="Start Process", command=self.start_process)

        self.process_running = False
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def start_process(self):
        self.progress["value"] = 0
        self.max_value = 100
        self.progress["maximum"] = self.max_value
        self.process_running = True
        self.file_menu.entryconfig("Start Process", state="disabled")
        threading.Thread(target=self.long_process).start()

    def long_process(self):
        for i in range(1, self.max_value + 1):
            time.sleep(0.1)  # Simulate a long process
            if i == 50:
                self.root.after(0, lambda: self.report_error("An error occurred"))
            self.update_progress(i)
            print(i)
        self.process_running = False
        self.root.after(0, lambda: self.file_menu.entryconfig("Start Process", state="normal"))

    def update_progress(self, value):
        self.root.after(0, lambda: self.progress.config(value=value))

    def report_error(self, error):
        self.root.after(0, lambda: (self.message.config(text=error), self.root.bell()))

    def on_closing(self):
        if self.process_running:
            messagebox.showwarning("Warning", "The process is still running. Please wait until it finishes.")
        else:
            self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()
Das funktioniert, wenn die App über den Schließen Knopf des Fensters beendet wird. Wenn man aber die App über das App-Menü oder den Cmd-Q Button schließt, beendet sich die App trotzdem. Wer hat eine Idee?

Danke und viele Grüße

Haiko
Antworten