简体   繁体   中英

Trying to Exit a While True Loop using PySimpleGUI

Here is my Code:

Main.py:

import PySimpleGUI as sg
import Config
import threading


def main():
    layout = [  [sg.Text('Real Time Raspberry Pi Sniffer')],
            [sg.Button('Run While Loop'), sg.Button('Exit')],     # a couple of buttons
            [sg.Output(size=(60,15))] ]         # an output area where all print output will go
            #[sg.Input(key='_IN_')] ]             # input field where you'll type command

    window = sg.Window('Realtime Shell Command Output', layout)

    while True:            # Event Loop
        event, values = window.Read()
        if event == 'Run While Loop':             
            t1 = threading.Thread(target = Config.whileLoop())
            t1.start()
        elif event == 'Exit' or event == WIN_CLOSED:
            print('CLICKED EXIT') 
            window.Close()

if __name__ == '__main__':
    main()

Config.py

from PySimpleGUI.PySimpleGUI import WIN_CLOSED
def whileLoop():
    state = True
    while (state == True):          
        print("It works!")  

I am trying to create GUI window which runs a while loop when a user clicks a button (in this case, when they click "Run While Loop"). However, I am having an issue because my code gets stuck in the nested while loop which is the one in Config.py. I want the code to be able to exit out of the while loop and stop by the program when the 'Exit' Button is clicked. I looked into Threading and am not sure what else to do. Anything helps, thanks!

I import a class Func defined in Config.py , then call method while_loop of instance Func() . Set a flag True or False for while loop keep running or not.

Example Code

# Config.py

from time import sleep
from PySimpleGUI import WIN_CLOSED


class Func():

    def __init__(self):
        self.state = False
        self.count = 0

    def while_loop(self, window):
        while self.state:
            sleep(0.5)                                      # Simulate job done here
            self.count += 1
            window.write_event_value("Done", self.count)    # update GUI by event
# main.py

from time import sleep
from threading import Thread
import PySimpleGUI as sg
import Config


def main():

    layout = [
        [sg.Text('Real Time Raspberry Pi Sniffer')],
        [sg.Button('Start'), sg.Button('Stop'), sg.Button('Exit')],
        [sg.StatusBar('', size=60, key='Status')],
    ]
    window = sg.Window('Realtime Shell Command Output', layout, enable_close_attempted_event=True)
    status = window['Status']
    func = Config.Func()
    thread = None
    while True:

        event, values = window.read()

        if event in (sg.WINDOW_CLOSE_ATTEMPTED_EVENT, 'Exit'):
            func.state = False
            sleep(0.5)  # Wait thread to stop
            break
        elif event == 'Start' and thread is None:
            func.state = True
            func.count = 0
            thread = Thread(target=func.while_loop, args=(window,), daemon=True)
            thread.start()
        elif event == 'Stop':
            func.state = False
            thread = None
        elif event == 'Done':
            count = values[event]
            status.update(f"Job done at #{count:0>3}")

    window.Close()

if __name__ == '__main__':
    main()

This is a guess, as I haven't done what you are trying before.

Perhaps if you change your config.py to be like this:

state=True
def whileLoop():
   while (state == True):          
       print("It works!") 

(making state a module global flag)

And modify your event loop like:

while True:            # Event Loop
    event, values = window.Read()
    if event == 'Run While Loop':             
        t1 = threading.Thread(target = Config.whileLoop)
        t1.start()
    elif event == 'Exit' or event == WIN_CLOSED:
        print('CLICKED EXIT') 
        Config.state = False # set the exit flag
        t1.join() # I'm not sure about this, could try without
        window.Close()

Again, I've use Python a long time, but never like this.

right here: t1 = threading.Thread(target = Config.whileLoop())
you have called Config.whileLoop() while setting up your threading variable. You must write instead t1 = threading.Thread(target = Config.whileLoop)
which doesn't actually call the target function Config.whileLoop . t1.start() will actually call it.

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