如何在tkinter后台运行函数

12 投票
5 回答
37379 浏览
提问于 2025-04-16 12:06

我刚开始学习图形用户界面(GUI)编程,想用Python的tkinter库写个程序。我希望这个程序能在后台运行一个简单的功能,并且这个功能可以通过图形界面来影响。

这个功能的主要任务是从0开始数,一直数到无穷大,直到有人按下一个按钮。至少我希望它能这样做。但是我不知道怎么才能让这个功能在后台运行,因为tkinter的主循环(mainloop())一直在控制着程序。如果我让这个功能在一个无限循环中运行,主循环就无法执行,图形界面就会卡死。

我想在每次循环后把控制权还给主循环,但我该怎么在没有用户触发事件的情况下,把控制权从主循环转回到这个运行功能的函数呢?

下面是一些示例代码,这段代码会让图形界面崩溃:

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)

5 个回答

4

试着理解这个例子:时钟在后台更新,同时更新界面(不需要两个线程)。

# 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(  )

来源:链接到网站

12

事件驱动编程的概念其实很简单。你可以想象在你的程序文件的最后,有一个简单的无限循环:

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)

上面的代码每秒会更新一次计数器。当你的程序初始化时,你调用它一次,从那以后它会不断地自己调用自己,循环下去。

这种方法的前提是你能把一个大问题(在这个例子中是“永远计数”)拆分成小步骤(比如“加一”)。如果你在做一些像是慢速数据库查询或者大规模计算的事情,这种方法可能就不太适用了。

4

你可以在这个其他问题中找到答案 Tkinter加载图标时锁定python,以及tk.mainloop在一个线程中

简单来说,你需要有两个线程,一个用来处理tkinter,另一个用来处理后台任务。

撰写回答