我是GUI编程的新手,我想用tkinter编写一个Python程序。我想要它做的就是在后台运行一个可以通过GUI影响的简单函数。
该功能从0到无穷大计数,直到按下按钮。至少这就是我想要的。但我不知道如何在后台运行此函数,因为tkinter的mainloop()始终具有控制权。如果我在无限循环中启动该函数,则无法执行mainloop()并且GUI已死。
我希望在每个循环后将控制权返回给mainloop(),但是如何在没有用户触发事件的情况下将控制从mainloop()恢复到runapp-function?
以下是一些杀死GUI的示例代码:
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="START", command=self.runapp)
self.button.pack(side=LEFT)
self.hi_there = Button(frame, text="RESTART", command=self.restart)
self.hi_there.pack(side=LEFT)
self.runapp()
def restart(self):
print "Now we are restarting..."
def runapp(self):
counter = 0
while (1):
counter =+ 1
time.sleep(0.1)
答案 0 :(得分:8)
基于事件的编程在概念上很简单。试想一下,在程序文件的末尾是一个简单的无限循环:
while <we have not been told to exit>:
<pull an event off of the queue>
<process the event>
所以,你需要做的就是不断地运行一些小任务,把它分解成一口大小的部分并将这些部分放在事件队列中。每次循环时,计算的下一次迭代都将自动执行。
您可以使用after方法在事件队列中放置对象。因此,创建一个递增数字的方法,然后重新安排自己在几毫秒后运行。它看起来像是:
def add_one(self):
self.counter += 1
self.after(1000, self.add_one)
以上将每秒更新一次计数器。当你的程序初始化时,你只需要调用一次,然后再一次又一次地调用它,等等。
此方法仅在您将大问题(在您的情况下“永远计算”)分解为小步骤(“添加一个”)时才有效。如果您正在执行类似慢速数据库查询或大量计算的操作,则此技术不一定有效。
答案 1 :(得分:4)
您将在另一个问题Tkinter locks python when Icon loaded and tk.mainloop in a thread中找到答案。
简而言之,您需要有两个线程,一个用于tkinter,另一个用于后台任务。
答案 2 :(得分:2)
我没有足够的声誉来评论Bryan Oakley的答案(我发现它在我的程序中非常有效),所以我会在这里添加我的经验。我发现,根据你的后台函数运行的时间长度,以及你想要的时间间隔精确度,最好在循环函数的开头加上self.after
调用。在布莱恩的例子中,这看起来像
def add_one(self):
self.after(1000, self.add_one)
self.counter += 1
这样做可以确保精确地遵守时间间隔,从而消除在功能需要很长时间时可能出现的间隔漂移。
答案 3 :(得分:2)
尝试理解这个例子:在backgroud中更新时钟,并更新GUI(不需要2个线程)。
# use Tkinter to show a digital clock
# tested with Python24 vegaseat 10sep2006
from Tkinter import *
import time
root = Tk()
time1 = ''
clock = Label(root, font=('times', 20, 'bold'), bg='green')
clock.pack(fill=BOTH, expand=1)
def tick():
global time1
# get the current local time from the PC
time2 = time.strftime('%H:%M:%S')
# if time string has changed, update it
if time2 != time1:
time1 = time2
clock.config(text=time2)
# calls itself every 200 milliseconds
# to update the time display as needed
# could use >200 ms, but display gets jerky
clock.after(200, tick)
tick()
root.mainloop( )
信用:link to site
答案 4 :(得分:0)
如果您不想离开这些线程,我想为您的GUI提供一个建议- 将您的GUI的函数放在root.mainloop()语句之前。
示例-
root = tk.Tk()
.
.
graphicsfunction() #function for triggering the graphics or any other background
#function
root.mainloop()
如果愿意,请投票。