【问题标题】:How to run a function in the background of tkinter如何在 tkinter 后台运行一个函数
【发布时间】:2011-06-30 04:53:46
【问题描述】:

我是 GUI 编程新手,我想用 tkinter 编写一个 Python 程序。我想要它做的只是在后台运行一个可以通过 GUI 影响的简单函数。

函数从 0 计数到无穷大,直到按下按钮。至少那是我想要它做的。但我不知道如何在后台运行这个函数,因为 tkinter 的 mainloop() 一直都有控制权。如果我在一个无限循环中启动该函数,则 mainloop() 将无法执行并且 GUI 已死。

我想在每个循环后将控制权返回给 mainloop(),但是如何在没有用户触发事件的情况下将控制权从 mainloop() 返回给 runapp 函数?

这是一些杀死 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)

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    您将在另一个问题Tkinter locks python when Icon loaded and tk.mainloop in a thread中找到答案。

    简而言之,你需要有两个线程,一个用于 tkinter,一个用于后台任务。

    【讨论】:

    • 对于这个简单的程序,绝对不需要使用线程。这就像用电锯杀死一只蚂蚁。
    【解决方案2】:

    基于事件的编程在概念上很简单。想象一下,在你的程序文件的末尾是一个简单的无限循环:

    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)
    

    上面将每秒更新一次计数器。当你的程序初始化时,你调用它一次,然后它会导致自己被一次又一次地调用,等等。

    只有当您可以将大问题(在您的情况下为“永远计数”)分解为小步骤(“添加一个”)时,此方法才有效。如果您正在执行诸如慢速数据库查询或大量计算之类的操作,则此技术不一定有效。

    【讨论】:

      【解决方案3】:

      我没有足够的声誉来评论 Bryan Oakley 的回答(我发现它在我的程序中非常有效),所以我将在这里添加我的经验。我发现根据你的后台函数运行多长时间,以及你希望时间间隔有多精确,最好将self.after 调用放在循环函数的开头。在 Bryan 的示例中,这看起来像

      def add_one(self):
          self.after(1000, self.add_one)
          self.counter += 1
      

      这样做可以确保准确地遵守时间间隔,从而消除函数需要很长时间时可能发生的任何间隔漂移。

      【讨论】:

      【解决方案4】:

      试着理解这个例子:在后台更新时钟,更新 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

      【讨论】:

        【解决方案5】:

        如果您不想离开这些线程,我想为您的 GUI 提供一个建议- 将 GUI 的函数放在 root.mainloop() 语句之前。

        例子-

        root = tk.Tk()
        .
        .
        graphicsfunction()     #function for triggering the graphics or any other background 
                               #function
        root.mainloop()
        

        如果你喜欢,请投票。

        【讨论】:

          猜你喜欢
          • 2014-06-15
          • 2015-10-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-06-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多