停止线程而不关闭GUI窗口



我自己在学习python,我的水平可能是我理解的"脚本小子"的一个糟糕借口,大多数情况下,我会借用不同的脚本并将其混合在一起,直到它达到我想要的效果。然而,这是我第一次尝试为我拥有的一个脚本创建GUI。我正在使用PySimpleGUI,并且我已经能够非常好地理解它。除了一件事之外,所有的事情都按照我想要的方式进行。

问题是我想在不退出GUI的情况下停止正在运行的守护进程线程。如果我按下停止按钮,GUI就会关闭,如果GUI没有关闭,它也不会停止线程。问题在第64-68行之间。我尝试了一些事情,只是在"65"行放了一个占位符,以记住我试图保持GUI(我头脑中的"主线程"(的运行。脚本将在此状态下运行,但"停止"按钮不起作用。

注意:我在剧本里放了很多评论,所以我记得每一部分是什么,它做了什么,我需要清理什么。如果我打算共享一个脚本,我不知道这是否是一个好的做法。此外,如果重要的话,我使用Visual Studio代码。

#!/usr/local/bin/python3
import PySimpleGUI as sg
import pyautogui
import queue
import threading
import time
import sys
from datetime import datetime
from idlelib import window
pyautogui.FAILSAFE = False
numMin = None
# ------------------ Thread ---------------------
def move_cursor(gui_queue):
if ((len(sys.argv)<2) or sys.argv[1].isalpha() or int(sys.argv[1])<1):
numMin = 3
else:
numMin = int(sys.argv[1])
while(True):
x=0
while(x<numMin):
time.sleep(5)                   # Set short for debugging (will set to '60' later)
x+=1
for i in range(0,50):
pyautogui.moveTo(0,i*4)
pyautogui.moveTo(1,1)
for i in range(0,3):
pyautogui.press("shift")
print("Movement made at {}".format(datetime.now().time()))  
# --------------------- GUI ---------------------
def the_gui():
sg.theme('LightGrey1')                  # Add a touch of color
gui_queue = queue.Queue()               # Used to communicate between GUI and thread

layout = [  [sg.Text('Execution Log')],
[sg.Output(size=(30, 6))],
[sg.Button('Start'), sg.Button('Stop'), sg.Button('Click Me'), sg.Button('Close')]  ]
window = sg.Window('Stay Available', layout)
# -------------- EVENT LOOP ---------------------
# Event Loop to process "events"
while True:
event, values = window.read(timeout=100)
if event in (None,'Close'):
break
elif event.startswith('Start'):     # Start button event
try:
print('Starting "Stay Available" app')
threading.Thread(target=move_cursor,
args=(gui_queue,), daemon=True).start()
except queue.Empty:
print('App did not run')
elif event.startswith('Stop'):      # Stop button event
try:
print('Stopping "Stay Available" app')
threading.main_thread       # To remind me I want to go back to the original state
except queue.Empty:
print('App did not stop')
elif event == 'Click Me':           # To see if GUI is responding (will be removed later)
print('Your GUI is alive and well')
window.close(); del window
if __name__ == '__main__':
gui_queue = queue.Queue()               # Not sure if it goes here or where it is above
the_gui()
print('Exiting Program')

根据这个答案:创建类stoppable_thread

然后:将线程存储在全局变量上

# [...]
# store the threads on a global variable or somewhere
all_threads = []
# Create the function that will send events to the ui loop
def start_reading(window, sudo_password = ""):
While True:
window.write_event_value('-THREAD-', 'event')
time.sleep(.5)

# Create start and stop threads function
def start_thread(window):
t1 = Stoppable_Thread(target=start_reading,  args=(window,), daemon=True)
t1.start()
all_threads.append(t1)
def stop_all_threads():
for thread in all_threads:
thread.terminate()

最后,在主窗口循环中,处理启动、停止或从线程获取信息的事件。

最新更新