简体   繁体   中英

Python - Tkinter exit button on a child window and how it affects a toggle button state

I'm a newbie trying to learn Python with the Raspberry Pi. I've been writing some code to try to make a simple emulator for the piFace add on board.

There are a few issues with it and I'm learning as I work my way through them.

My code opens a window and shows a toggle button which toggles an LED image on/off. I also added a button that opens a child window. The child window has two buttons. One is a on/off toggle button that toggles an LED image on/off, the other is an Exit button.

My problem is that when the LED is 'on' if I use the Exit button the child window closes, as it should. But if I re-open the child window and use the toggle button to turn the LED on, nothing happens. If I press the toggle button again the LED then comes on.

I kind of understand what the problem is. Because I close the child window when the LED is 'on' the toggle button state is still in the ON state. And, when I re-open the window and click the toggle button I'm just setting the toggle button state to OFF.

I'm not sure how to address the problem. Should I look at closing the window a different and probably correct way? Should I look at a way of presetting the state of the toggle switch each time the child window is open? Should I try something completely different? Should I stop altogether? :-)

I hope that makes some sense.

Thanks for any help.

Here's my code....

# Idle 10_01_2014_GUI label image toggle
from time import sleep
from Tkinter import *
import Tkinter as tk
import threading

class App:

    def __init__(self, master):
            self.master=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='LED 0 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.buttonnewwindow = Button(frame, text='Knight Rider TEST', command=self.new_window)
            self.buttonnewwindow.grid(row=10, column=0)

            self.button8 = Button(frame, text='Exit', command=quit)
            self.button8.grid(row=11, column=0)

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

        tog[0] = not tog[0]
        if tog[0]:
            print('LED 0 ON')
            self.button0.config(text='LED 0 ON')
            self.LED0.config(image = logo)
            self.LED0.grid(row=2, column=1)

        else:
            print('LED 0 OFF')
            self.button0.config(text='LED 0 OFF')
            self.LED0.config(image = logo2)
            self.LED0.grid(row=2, column=1)


    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):
            self.signal = False    
            print('self.signal', self.signal)
            self.master=master    # I added this line to make the exit button work
            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')
            self.signal = True   
            print('self.signal', self.signal)
            print('tog[0]', tog[0])
            self.LED0.config(image = logo)
        else:
            print('Knight Rider OFF')
            self.button0.config(text='Knight Rider OFF')
            self.signal = False   
            print('self.signal', self.signal)
            print('tog[0]', tog[0])
            self.LED0.config(image = logo2)


    def close_window(self):
            print('Knight Rider OFF')
            print('self.signal', self.signal)
            self.button0.config(text='Knight Rider OFF')
            self.LED0.config(image = logo2)
            self.signal = False   
            print('self.signal', self.signal)

            sleep(.5)
            print('Close Child window')
            self.master.destroy()   # I added this line to make the exit button work

root = Tk()
logo2 = PhotoImage(file="c:\\Users\\joebloggs\\Downloads\\led-off.gif")
logo = PhotoImage(file="c:\\Users\\joebloggs\\Downloads\\led-on.gif")

root.wm_title('LED on & off program')
app = App(root)

root.mainloop()

The roots of the problem come from the fact that you start the child window assuming that self.signal = False . I you have a way of detecting the state of the LED, put it here and the problem will solve itself, ie self.signal = get_led_state() .

Now, if getting the genuine LED state is not possible, then you would need to store that state somewhere else, so that it is preserved between opening and closing the child window. One way would be simply putting the signal field into the App class. But I would go as follows: creating a State class, which will hold the state of the LED for me, eg:

class State:
    LED_ON = true

You will then control the State.LED_ON field instead of self.signal to get or set the LED state. Note, that it is not thread-safe, but I believe you don't have to worry about that right now :)

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