2017-02-23 1 views
2

Ich möchte ein Hauptfenster und ein oder mehrere Toplevel() Fenster haben, die bei Bedarf geöffnet werden können. Ich bin in der Lage, die Fenster zu erstellen und sogar zu zerstören.In Python3/tkinter, wie abzufangen, wenn der Benutzer auf die Schließen-Schaltfläche in einem Toplevel-Fenster klickt

Ich versuche jedoch, eine Schaltfläche im Hauptfenster zu implementieren, die das zweite Fenster öffnet und schließt (dieses zweite Fenster sollte immer eindeutig sein, d. H. Niemals zweimal gleichzeitig öffnen). Das ist, was ich habe jetzt, nach ein wenig das Hantieren:

#!/usr/bin/python3 

import tkinter as tk 
from tkinter import ttk 
import tkinter.font 


class baseApp(ttk.Frame): 
    def __init__(self,master,*args,**kwargs): 
     super().__init__(master,*args,**kwargs) 
     self.master = master 

     self.mainframe = ttk.Frame(master) 
     self.topframe = ttk.Frame(self.mainframe, padding="5 8 5 5") 

     self.topframe.pack(side=tk.TOP, fill=tk.X) 
     self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH) 


class App(baseApp): 
    def __init__(self,master,*args,**kwargs): 
     super().__init__(master,*args,**kwargs) 
     self.master = master 
     self.button1 = ttk.Button(self.topframe,text="One",command=self.button_one) 
     self.btn_remessas = ttk.Button(self.topframe,text="Open/close Toplevel window",command=self.create_window1) 
     self.button1.grid(row=0,column=0) 
     self.btn_remessas.grid(row=0,column=1) 
     self.topframe.pack(side=tk.TOP, fill=tk.X) 
     self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH) 

    def create_window1(self): 
     if current_state.window2_open == False: 
      self.newWindow2 = tk.Toplevel(self.master) 
      self.newWindow2.geometry('600x500+680+0') 
      self.newWindow2.title('Second window') 
      self.janela_remessas = SecondWindow(self.newWindow2) 
      current_state.window2_open = True    
     else: 
      self.newWindow2.destroy() 
      root.update_idletasks() 
      current_state.window2_open = False 

    def button_one(self): 
     print("button 1 pressed") 


class SecondWindow: 
    def __init__(self,master,*args,**kwargs): 
     #super().__init__(master,*args,**kwargs) 
     self.mainframe = ttk.Frame(master, padding="5 8 5 5") 
     self.topframe = ttk.Frame(self.mainframe) 
     self.button1 = ttk.Button(self.topframe,text="button",command=self.button_function) 
     self.button1.pack()     
     self.topframe.pack(side=tk.TOP, fill=tk.X) 
     self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH) 

    def button_function(self, *event): 
     print("user just pressed button") 

    def close_window(self, *event): #Please fix me! 
     current_state.window2_open = False 
     self.destroy() 


class AppStatus: 
    def __init__(self): 
     self.window2_open = False 


if __name__ == "__main__": 
    root = tk.Tk() 
    app = App(root) 
    current_state = AppStatus() 
    root.configure(background='grey95') 
    root.title('Application window') 
    root.geometry('1000x760+0+0') 
    root.bind_all("<Mod2-q>", exit) 
    root.mainloop() 

Gerade jetzt, wenn der Benutzer das Fenster schließen Schaltfläche klickt, oder die entsprechende Tastenkombination, wird die App nicht wissen, dass das zweite Fenster nicht mehr existiert Wenn wir die Taste zum Öffnen/Schließen des Fensters drücken, passiert nichts. Wenn wir weiterhin die Öffnen/Schließen-Taste drücken, gibt es einige Male, wenn die Taste das zweite Fenster nicht öffnet. Was mache ich falsch?

Antwort

4

Sie möchten die Methode wm_protocol des Toplevel-Widgets verwenden. Speziell mit dem Protokoll WM_DELETE_WINDOW.

>>> import tkinter as tk 
>>> root = tk.Tk() 
>>> dlg = tk.Toplevel(root) 
>>> dlg.wm_title("dialog") 
'' 
>>> root.wm_protocol("WM_DELETE_WINDOW", lambda: print("close root")) 
'' 
>>> dlg.wm_protocol("WM_DELETE_WINDOW", lambda: print("close dialog")) 
'' 
>>> root.mainloop() 
close dialog 
close root 

Die letzten Zeilen werden ausgegeben, wenn ich die Fensterrahmen Schließen-Schaltfläche klicken (das große rote X). Dies wird jetzt nicht beendet, wenn ich darauf klicke und auch auf einem der Tk-Fenster für Alt-F4 aufgerufen wird.

Die Tk documentation hat mehr zu sagen. Die Python-Dokumentation, die ich fand, schien eher spärlich.

+0

Das scheint nur für das Hauptfenster (Root) zu funktionieren. Es würde beispielsweise ermöglichen, einen Bestätigungsdialog zu erhalten, bevor die Anwendung beendet wird. Aber ich kann keine Methode oder Funktion aufrufen, wenn der Benutzer das zweite Fenster schließt. Gibt es einen Weg, es zu tun? –

+1

Die gleiche Technik funktioniert für jedes Toplevel-Widget. Sie müssen 'wm_protocol' für jeden Toplevel aufrufen. Der Stamm-Toplevel fängt die Nachricht für ein anderes Dialogfeld nicht ab. – patthoyts

+0

Was wäre die Syntax, um es für jede Toplevel aufzurufen? Wenn ich es wie 'self.wm_protocol (" WM_DELETE_WINDOW ", lambda: print (" oww "))' hinzufüge, bekomme ich eine Fehlermeldung, dass das Objekt dieses Attribut nicht hat ... –

0

Einfach den vollen Arbeitscode posten, nachdem Sie den Ratschlägen von pathoyts gefolgt sind.

#!/usr/bin/python3 

import tkinter as tk 
from tkinter import ttk 
import tkinter.font 


class baseApp(ttk.Frame): 
    def __init__(self,master,*args,**kwargs): 
     super().__init__(master,*args,**kwargs) 
     self.master = master 

     self.mainframe = ttk.Frame(master) 
     self.topframe = ttk.Frame(self.mainframe, padding="5 8 5 5") 

     self.topframe.pack(side=tk.TOP, fill=tk.X) 
     self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH) 


class App(baseApp): 
    def __init__(self,master,*args,**kwargs): 
     super().__init__(master,*args,**kwargs) 
     self.master = master 
     self.button1 = ttk.Button(self.topframe,text="One",command=self.button_one) 
     self.btn_remessas = ttk.Button(self.topframe,text="Open/close Toplevel window",command=self.create_window2) 
     self.button1.grid(row=0,column=0) 
     self.btn_remessas.grid(row=0,column=1) 
     self.topframe.pack(side=tk.TOP, fill=tk.X) 
     self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH) 

    def create_window2(self): 
     if current_state.window2_open == False: 
      self.newWindow2 = tk.Toplevel(self.master) 
      self.newWindow2.geometry('600x500+680+0') 
      self.newWindow2.title('Second window') 
      self.janela_remessas = SecondWindow(self.newWindow2) 
      current_state.window2_open = True 
      self.newWindow2.wm_protocol("WM_DELETE_WINDOW", lambda: self.close_window2())   
     else: 
      self.close_window2() 

    def close_window2(self, *event): 
     print("closing window") 
     root.update_idletasks() 
     current_state.window2_open = False 
     self.newWindow2.destroy() 

    def button_one(self): 
     print("button 1 pressed") 


class SecondWindow: 
    def __init__(self,master,*args,**kwargs): 
     #super().__init__(master,*args,**kwargs) 
     self.mainframe = ttk.Frame(master, padding="5 8 5 5") 
     self.topframe = ttk.Frame(self.mainframe) 
     self.button1 = ttk.Button(self.topframe,text="button",command=self.button_function) 
     self.button1.pack()     
     self.topframe.pack(side=tk.TOP, fill=tk.X) 
     self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH) 

    def button_function(self, *event): 
     print("user just pressed button") 

    def close_window(self, *event): #Please fix me! 
     current_state.window2_open = False 
     self.destroy() 


class AppStatus: 
    def __init__(self): 
     self.window2_open = False 


if __name__ == "__main__": 
    root = tk.Tk() 
    app = App(root) 
    current_state = AppStatus() 
    root.configure(background='grey95') 
    root.title('Application window') 
    root.geometry('1000x760+0+0') 
    root.bind_all("<Mod2-q>", exit) 
    root.mainloop() 
Verwandte Themen