我希望在tkinter GUI中连续运行一个函数。我附上了一些shell代码:
#!/usr/bin/env python3
import tkinter as tk
from time import sleep
import os
import sys
class Application(Frame):
def __init__(self, master):
super(Application, self).__init__(master)
self.grid()
self.create_widgets()
def create_widgets(self):
......
root = Tk()
def run_continously:
... -- calls sleep -- ...
root.after(3000, run_continuously)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
app = Application(root)
root.after(3000, run_continuously)
root.mainloop()
运行GUI时,它往往会运行'run_continuously'函数一次,GUI会冻结。我怀疑这是因为睡眠功能(我在run_continuously函数中调用)所致。
我如何在一个非常简单的线程中实现'run_continuously'函数来解决这个问题?在一个线程中运行该函数甚至可以解决问题吗? 'run_continuously'函数不需要与Application类进行交互。我希望它只在后台运行,并在主循环结束时停止。
以下是代码的结尾:
def run_continuously(quit_flag):
print("in it")
if not quit_flag:
GPIO.output(DIR_PIN, True)
for i in range(steps):
print("in loop")
GPIO.output(STEP_PIN, True)
sleep(sDelay)
GPIO.output(STEP_PIN, False)
sleep(sDelay)
sleep(wait_time)
GPIO.output(DIR_PIN, False)
for i in range(steps):
GPIO.output(STEP_PIN, True)
sleep(sDelay)
GPIO.output(STEP_PIN, False)
sleep(sDelay)
print("run motor")
root.after(1000, run_continuously(quit_flag,))
#=================================================================
# main
#=================================================================
root = Tk() # Create the GUI root object
press1 = StringVar()
press2 = StringVar()
x = 275
y = 50
w = 580
h = 250
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
app = Application(root) # Create the root application window
quit_flag = False
root.after(0, app.read_pressure)
motor_thread = threading.Thread(target=run_continuously, args=(quit_flag,)).start()
root.mainloop()
quit_flag=True
motor_thread.join()
答案 0 :(得分:0)
如果按下'QUIT'按钮或按下Ctrl-C,这是一个干净地退出的minimal, complete, and verifiable example:
from Tkinter import *
import multiprocessing
import threading
import time
import logging
class Application(Frame):
def create_widgets(self):
self.quit_button = Button(self)
self.quit_button['text'] = 'QUIT'
self.quit_button['fg'] = 'red'
self.quit_button['command'] = self.quit
self.quit_button.pack({'side': 'left'})
def __init__(self, master=None):
Frame.__init__(self, master)
self.quit_button = None
self.pack()
self.create_widgets()
self.poll()
def poll(self):
"""
This method is required to allow the mainloop to receive keyboard
interrupts when the frame does not have the focus
"""
self.master.after(250, self.poll)
def worker_function(quit_flag):
counter = 0
while not quit_flag.value:
counter += 1
logging.info("Work # %d" % counter)
time.sleep(1.0)
format = '%(levelname)s: %(filename)s: %(lineno)d: %(message)s'
logging.basicConfig(level=logging.DEBUG, format=format)
root = Tk()
app = Application(master=root)
quit_flag = multiprocessing.Value('i', int(False))
worker_thread = threading.Thread(target=worker_function, args=(quit_flag,))
worker_thread.start()
logging.info("quit_flag.value = %s" % bool(quit_flag.value))
try:
app.mainloop()
except KeyboardInterrupt:
logging.info("Keyboard interrupt")
quit_flag.value = True
logging.info("quit_flag.value = %s" % bool(quit_flag.value))
worker_thread.join()