简体   繁体   中英

Python Tkinter - closing a child window with an exit button

I have a Raspberry Pi with the Piface adaptor board. I have made a GUI which controls the LED's on the Piface board. One button on the GUI opens a new window which, on the press of a button, starts and stops running a small piece of code to make the LED's run up and down continuously, like Knight Riders car, using a While loop in a thread. In this new window I have added a EXIT button. I want to add a piece of code that will close the new window when I click the EXIT button, and then return to the main window. I have looked up many examples but just can't quite see what I should put or where. I have tried the 'quit' but it closed the whole program. Having looked at many examples I maybe creating my new window in not quite the right way so feel free to tell me if there are better ways.

So is there a better way of doing it? Any pointers would be appreciated.

Thanks in advance.

Heres a piece of the code....

   def new_window(self):
        print('New Window')
        self.newWindow = tk.Toplevel(self.master)
        self.app = App2(self.newWindow)
        self.newWindow.grab_set()   # I added this line to stop opening multiple new windows

class App2:


    def __init__(self, master):

            frame = Frame(master)
            frame.pack()
            Label(frame, text='Turn LED ON').grid(row=0, column=0)
            Label(frame, text='Turn LED OFF').grid(row=0, column=1)

            self.button0 = Button(frame, text='Knight Rider OFF', command=self.convert0)
            self.button0.grid(row=2, column=0)
            self.LED0 = Label(frame, image=logo2)
            self.LED0.grid(row=2, column=1)

            self.button9 = Button(frame, text='Exit', command=self.close_window)
            self.button9.grid(row=3, column=0)


    def convert0(self, tog=[0]):

        tog[0] = not tog[0]
        if tog[0]:
            print('Knight Rider ON')
            self.button0.config(text='Knight Rider ON')
            t=threading.Thread(target=self.LED)
            t.start()
            self.signal = True    #added to stop thread
            self.LED0.config(image = logo)
        else:
            print('Knight Rider OFF')
            self.button0.config(text='Knight Rider OFF')
            self.signal = False   #added to stop thread
            self.LED0.config(image = logo2)

    def LED(self):
            while self.signal:   #added to stop thread

                a=0

                while self.signal:   #added to stop thread
                        pfio.digital_write(a,1) #turn on
                        sleep(0.05)
                        pfio.digital_write(a,0) #turn off
                        sleep(0.05)
                        a=a+1

                        if a==7:
                                break

                while self.signal:   #added to stop thread

                        pfio.digital_write(a,1) #turn on
                        sleep(0.05)
                        pfio.digital_write(a,0) #turn off
                        sleep(0.05)
                        a=a-1

                        if a==0:
                                break

    def close_window(self):
        print('Close Child window')
        #self.newWindow.destroy()   Not sure what to put here?

If you put the new_window into your App2 then you should be fine.

self.newWindow.destroy() 

Destroys the window. This is the right call. The window is closed then and all widgets in the window also get destroyed.

quit() will stop the mainloop() In this case the the program ends at the last line and also destroys everything.

You definitely want to use destroy .

class App2:

    newWindow = None

    def close_window(self):
        print('Close Child window')
        if self.newWindow:
            try: self.newWindow.destroy()   
            except (): pass # fill in the error here
            self.newWindow = None

   def new_window(self):
        print('New Window')
        self.close_window()
        self.newWindow = tk.Toplevel(self.master)
        self.app = App2(self.newWindow)
        self.newWindow.grab_set()

    @classmethod
    def start_app(cls):
        window = tk.Tk(self.master)
        app = App2(window)
        return app

You should not acces Tkinter from threads. Have a look at alternatives

I was confused by quit and destroy , too, when I was starting with Tkinter.

In Tk windows are destroyed using the destroy method. So if you have a dialog toplevel and you want to get rid of it you call its destroy() method. Or you can withdraw it in which case the object continues to exist but is no longer on-screen and to re-show it you deiconify() the toplevel frame. It's more common to destroy them though. Here is a simple example creating and destroying a child dialog:

import sys
from Tkinter import *

class App(Frame):
    def __init__(self, parent = None):
        Frame.__init__(self, parent)
        self.grid()

        self.button = Button(self, text = "Create Dialog", command=self.CreateDialog)
        self.button.grid()

    def CreateDialog(self):
        dialog = Toplevel(self)
        dialog.wm_title("Dialog window")
        dialog.wm_transient(self)
        dialog.wm_protocol("WM_DELETE_WINDOW", lambda: self.onDeleteChild(dialog))
        button = Button(dialog, text="Close", command=lambda: self.onDeleteChild(dialog))
        button.grid()

    def onDeleteChild(self, w):
        w.destroy()


def main():
    app = App()
    app.mainloop()

if __name__ == "__main__":
    sys.exit(main())

You should also consider looking at using a timer in the code to drive the LED loop rather than a while loop. Take a look at this answer using Tk's after function to run code after an interval. If you re-schedule another after call in the handler, then you can arrange a function to be run at regular intervals and avoid blocking the event handling without requiring additional threads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM