Python GUI线程

时间:2016-02-08 17:10:39

标签: python multithreading user-interface tkinter

我希望在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()

1 个答案:

答案 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()