In tkinter öffnet, würde Ich mag die folgende erstellen:Wie eine kündbare Funktion auszuführen, wenn ein neues Fenster Tkinter
Wenn die Taste foo gedrückt wird, beginnt die Funktion foo sofort ausgeführt wird. Ein neues Fenster öffnet sich mit einem "Abbrechen" -Button, mit dem der Benutzer den Prozess in der Mitte beenden kann (mein tatsächlicher Prozess kann bis zu 30 Minuten dauern). Wenn foo vollständig ausgeführt wird, schließt sich das Fenster selbst und benachrichtigt den Benutzer, dass der Prozess abgeschlossen wurde.
Hier ist Code, mein Spielzeug Problem veranschaulicht:
from tkinter import ttk, messagebox, Toplevel, Tk
import time
import multiprocessing
def foo():
for i in range(100):
print(i)
time.sleep(0.1)
class TerminatedProcess(Exception):
def __init__(self, str = "Process was terminated"):
self.error_str = str
class ProcessWindow(Toplevel):
def __init__(self, parent, process):
Toplevel.__init__(self, parent)
self.parent = parent
self. process = process
terminate_button = ttk.Button(self, text="Cancel", command=self.cancel)
terminate_button.grid(row=0, column=0)
self.grab_set() # so you can't push submit multiple times
def cancel(self):
self.process.terminate()
self.destroy()
raise TerminatedProcess
def launch(self):
self.process.start()
self.process.join()
self.destroy()
class MainApplication(ttk.Frame):
def __init__(self, parent, *args, **kwargs):
ttk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.button = ttk.Button(self, text = "foo", command = self.callback)
self.button.grid(row = 0, column = 0)
def callback(self):
try:
proc = multiprocessing.Process(target=foo)
process_window = ProcessWindow(self, proc)
process_window.launch()
except TerminatedProcess as e: # raised if foo is cancelled in other window
messagebox.showinfo(title="Cancelled", message=e.error_str)
else:
messagebox.showinfo(message="sucessful run", title="Finished")
def main():
root = Tk()
my_app = MainApplication(root, padding=(4))
my_app.grid(column=0, row=0)
root.mainloop()
if __name__ == '__main__':
main()
Mit diesem Code, wenn die Taste foo gedrückt wird, wird process_window in der Tat gemacht, weil die die Funktion foo läuft, und ich erhalte eine „laufen erfolgreich“ Dialogbox, aber das Fenster erscheint nie! Dies ist ein Problem, da der Benutzer die Möglichkeit haben muss, foo zu beenden. Interessanterweise, wenn ich process_window.launch() lösche, bekomme ich immer noch die "run successful" Nachricht (wie erwartet), aber das process_window erscheint.
Ich habe versucht, den Startbefehl innerhalb der Initialisierung zu setzen, aber das hat das Fenster auch nicht angezeigt.
Ich habe auch versucht, den Prozess vor dem Fenster Erklärung begann wie folgt:
proc.start()
process_window = ProcessWindow(self, proc)
proc.join()
Das Fenster zu zeigen, noch immer nicht, aber der Prozess lief.
Meine Frage ist, wie muss ich diese Teile anordnen, um das ProcessWindow UND den Prozess automatisch zu starten, wenn das ProcessWindow öffnet?
UPDATE (Problemumgehung): Ich bin mir bewusst, dass ich eine Startschaltfläche innerhalb des ProcessWindow erstellen konnte, die die Funktion ausführen würde (und deaktivieren Sie die Schaltfläche, nachdem es einmal gedrückt wurde), aber ich möchte immer noch wissen, wie implementieren, was in der ursprünglichen Frage beschrieben wurde.
Sie machen unsere Hilfe Abschnitt lesen a [Minimal komplette Nachweisbare Beispiel] (http://stackoverflow.com/help/mcve) betrachten kann, ich müsste entweder viel Work-Around-Code implementieren, um dies zu testen, und eine Menge irrelevanten Code herausfiltern, um das Grundproblem zu verstehen. –
@ TadhgMcDonald-Jensen Danke für die Köpfe hoch. In dieser neuen Bearbeitung kann der größte Teil des Codes (main, foo, die TerminateProcess-Ausnahme) ignoriert werden, wurde jedoch als ausführbar angegeben, und alles, was nicht wichtig war, wurde entfernt. –