在GUI中在后台运行功能

时间:2019-04-08 19:15:15

标签: python multithreading time

我遇到功能/ GUI问题。我正在编写一个轻量函数,该函数将启动例程并检查时间是否在8am至某个停止时间之间。该例程在上午8点开始,并在该任意时间结束。问题是,一旦我在该例程中单击了“开始”,GUI就不会让我离开带有该“开始”按钮的窗口,因为它卡在了定时例程中。我真的很想能够将计时器设置为在后台运行,然后能够离开该GUI的窗口。看起来线程是执行此操作的关键,但是我不确定。

我在单独的文件中包含GUI代码,以简化工作。我还没有探索任何GUI中断工具。

这是我的代码

import datetime
from threading import Timer
import tkinter as tk
import time

# =============================================================================
# userInput takes a formatted input and passes it back to main.
# =============================================================================
def userInput():
        try:
            startTime = datetime.datetime.strptime(input('When would you like the routine to start in HH:MM 24 hour format: '), "%H:%M").time()
            print (startTime.strftime("%H:%M"))
        except:
            print ("Please enter correct time in HHMM format")

        try:
            redTime = datetime.datetime.strptime(input('When would you to start the red shift in HH:MM 24 hour format: '), "%H:%M").time()
            print (redTime.strftime("%H:%M"))
        except:
            print ("Please enter correct time in HHMM format")

        return startTime, redTime

# =============================================================================
# timeComparator is a function which, if the user changes any settings or chooses
# start in the middle of a cycle, implements the correct routine depending on 
# where in the cycle it's in. Right now, it's being utitilized to just test.
# The actual function of this will be adjusted later.
# =============================================================================            
def timeComparator(startTimered, redTime):
    now = datetime.datetime.now().time()
    #this obtains the current time
    #if statement compares input from 
    print("The current time is: ", now)
    if (now < startTime):
        print ("hello human")
    elif (now > startTime):
        print ("hello plant")

# =============================================================================
# This routine is intended to be controlled by the user in the manual portion
# of the GUI. This receives the start time and returns secs to initiate the 
# timer.
# =============================================================================
def manualRoutine(startTime, redTime):

    now = datetime.datetime.now().time()
    nowSeconds = (((now.hour * 60) + now.minute) * 60) + now.second

    startSeconds = ((startTime.hour * 60) + startTime.minute) * 60
    secsStart = startSeconds - nowSeconds

    redSeconds = ((redTime.hour * 60) + redTime.minute) * 60
    nowSeconds = (((now.hour * 60) + now.minute) * 60) + now.second
    secsRed = redSeconds - nowSeconds

    return secsStart, secsRed

# =============================================================================
# This function references 8am and 8pm and checks to see if the current time is
# between these two time anchors. If it is, it'll implement the lights in the
# while loop. This is meant to be implemented for both the plant life and
# the automatic human routine.
# =============================================================================
def autoRoutine():
    now = datetime.datetime.now().time()
    autoStart = now.replace(hour=8, minute=0)

    stoptime = datetime.datetime.now().time()
    autoStop = stoptime.replace(hour=12, minute=29)
    #WS2812 code here that  the autoStart and autoStop

    if (now > autoStart and now < autoStop):
            keepprint = False 
#    
    while (keepprint == False):

        nowloop = datetime.datetime.now().time()
        #nowloop keeps track of the current time through each loop

        print("the lights are starting")
        time.sleep (1.0)
        if (nowloop >= autoStop):
            keepprint = True
        #this breaks the loop after the stop time

    print(autoStart.strftime("%H:%M"))

    return autoStart
# =============================================================================
# blueFade is the function call for the beginning of the day light start up and
# midday light continuity. This function will end at the end of the cycle and 
# will immediately be followed by the orangeFade() function. Also, this will 
# receive the redTime to determine when to stop the function right before the 
# red shift
# =============================================================================
def blueFade(redTime):    

    print("sanity")
    keepprint = False

    while (keepprint == False):
            nowloop = datetime.datetime.now().time()

            print("manual routine lights are on")
            time.sleep(1.0)
            if (nowloop >= redTime):
                keepprint = True

    print("the manual routine has stopped")

    #WS2812 code here
    #redTime will be used to end this code before redFade begins




# =============================================================================
# redFade is a function in where the fade from blue to a more reddish hue starts.
# Depending on when the user stated they wanted the red shift to start, this will
# begin at that time and then fade from blue, to a reddish hue, then to completely
# off. This will take exactly 30 minutes
# =============================================================================
def redFade():

    print("the red hue is being imprinted")

# =============================================================================
# Main function. Will be used to call all other functions. The 
# =============================================================================
if __name__=="__main__":

#    autoRoutine()

    startTime, redTime = userInput()

    timeComparator(startTime, redTime)

    secsBlue, secsRed = manualRoutine(startTime, redTime)

    bluelights = Timer(secsBlue, lambda: blueFade(redTime))
    redlights = Timer(secsRed, redTime)

    bluelights.start()
    redlights.start()

在上面的代码中,我想在后台以及蓝灯和红灯中运行autoRoutine()。现在,如果我知道如何在后面运行autoRoutine(),我可能可以将其修复为同时执行蓝色和红色指示灯。预先感谢。

1 个答案:

答案 0 :(得分:0)

您可以通过实现threading.Thread()在后​​台运行事物,该while True:传递任何需要的参数。在大多数情况下,我发现.join()循环效果最好,因此线程将永远运行,但是在某些情况下,您可能希望将while some_global_variable == 1线程返回到主执行流程中。我通常使用import threading # standard library, no pip-install import tkinter as tk import time start = time.time() win = tk.Tk() label = tk.Label() label.grid() def worker_function(): while True: now = time.time() elapsed = now - start label.configure(text='{:5.2}'.format(elapsed)) t = threading.Thread(target=worker_function, args=[]) t.daemon = True t.start() # our thread will run until the end of the assigned function (worker_function here) # this will never end because there is a while True: within worker_function win.mainloop() 进行此操作,然后可以从函数外部进行编辑,或者仅等待线程自己到达分配的函数的末尾。主要流程如下所示:

def worker_function(a, b, c, d):

此外,您可以在提供的[]中为线程提供参数(即使只有1个参数,它也需要一个列表)。因此,如果我们的功能是:

t = threading.Thread(target=worker_function, args=[a, b, c, d])

我们的线程将创建为:

target=worker_function

还要注意,它是target=worker_function()而不是@KafkaListener(topics = "input") @SendTo("output") public ConsumerRecords consume(ConsumerRecords records) { // Do things return records; }