在Tkinter中循环使用after()

时间:2014-01-14 21:56:46

标签: python tkinter

我是Tkinter的新手,我仍然不确定我想要做的事情,希望这不是愚蠢的。欢迎各方面的帮助。

我想用我的Rasberry Pi控制一些电机。这些电机将配料放在一起。它在Python中运行良好,但我希望有一个带有几个按钮的GUI。每个按钮都应该在功能makerecipe中放置一个配方。配方包括应激活不同电机的时间列表。 Makerecipe将激活GPIO引脚。

然后应启动新功能电机。在此检查何时停用电机。这是一个简单的技巧,适用于Python,但我不知道如何使它在Tkinter中工作。每秒循环检查时间是否等于配方中的时间。如果是这样,则电机停用。

from Tkinter import *
import ttk
import time

root = Tk()
var = StringVar()
uitput = StringVar() #I want to print what is happening to label L2
uitput.set('Nothing')  #when program starts it says 
conversie = [7, 11, 15] #I will use pins 7, 11 and 15 on the RPi, 
moj = [0, 0, 2] #recipe 1, through Button 1, number of seconds the pins are True
sob = [4, 0, 0] #recipe 2, through Button 2, number of seconds the pins are True

#The following function activates the pins which are used in making the recipe
#later this will just activate the pins, for now it shows it in a label on screen.
#this seems to work

def makerecipe(argu): 
    aa=[]
    for i in range(len(argu)):
        if argu[i]==0:
            a=('GPIO.output(', str(conversie[i]), 'False)')
            aa.append(a)
        else:
            b=('GPIO.output(', str(conversie[i]), 'True)')
            aa.append(b)
    uitput.set(aa)
    root.update_idletasks()
    root.motor(argu)

#Next I want to have a function that looks at recipe and reads how long the
#GPIO pins should be active. Then turns them off one at a time. I just don't
#understand the after function. 
#I think, but probably wrong, that my recipe was loaded in makerecipe and argu
#has the value of the recipe because of the button, and I hoped I could pass argu
#along to the function motor.


def motor(motorinput):
    resultaat=('bla')
    uitput.set(resultaat)
`enter code here`    cc=[]
    for MotorNum in range(max(motorinput)+1):
        if MotorNum in motorinput:
            if motorinput.index(MotorNum)==0:
                c=("GPIO.output(",conversie[motorinput.index(MotorNum)],", False)")
                cc.append(c)
            elif motorinput.index(MotorNum)==1:
                d=("GPIO.output(",conversie[motorinput.index(MotorNum)],", False)")
                cc.append(d)
            elif motorinput.index(MotorNum)==2:
                e=("GPIO.output(",conversie[motorinput.index(MotorNum)],", False)")
                cc.append(e)
        uitput.set(cc)
        root.update_idletasks()
        #root.after(1000, motor(alfa)) #This goes wrong. 

B= Button(root, text="optie 1", command=lambda: makerecipe(moj))
B.pack()
L2=Label(root, textvariable=uitput, width=100)
L2.pack()
root.mainloop()

我在这里打印我的整个代码的原因是它可能有助于知道我到底在想什么,它可能看起来很可怕,但我正在努力改善它。

第一个问题是我显然不明白如何在我的第一个函数中调用下一个函数motor。它停在那里并给我:AttributeError:motor

第二个问题是我知道如何使用time.sleep,但我在这个论坛上到处都读到你不应该这样做。所以我试图使用之后,但不知道如何正确使用它。

我希望有人可以帮助这个新手。我非常了解Python的逻辑,但是Tkinter是一种新的思维方式。

1 个答案:

答案 0 :(得分:1)

  

第一个问题是我显然不明白如何在我的第一个函数中调用下一个函数motor。它停在那里并给我:AttributeError:motor

问题出现在 makerecipe 函数的最后一行:

root.motor(argu)

变量 root 是一个没有运动功能的TK对象。这就是AttributeError的原因。将此行更改为:

motor(argu)

会删除此错误。

  

第二个问题是我知道如何使用time.sleep,但我在这个论坛上到处都读到你不应该这样做。所以我试图使用之后,但不知道如何正确使用它。

你应该使用after,因为Tk有一个运行的eventloop( root.mainloop()调用)根据事件做出反应(比如点击按钮时调用你的函数,或者某个时间有通过)。但是如果你在代码中使用 time.sleep ,你可能会干扰这个eventloop。

修复是你应该在之后将函数引用传递给,所以Tk eventloop会在合适的时间调用该函数。但是在这里,你正在立即调用这个函数:

root.after(1000, motor(alfa)) #This goes wrong.

此行调用 motor (并将 alfa 作为参数传递),然后将motor的返回值(可能是任何内容)传递给 root.after

这一行应该是这样的:

root.after(1000, motor, alfa)

现在我们告诉 root 在1秒后使用 alfa 参数调用 motor