当前位置: 首页 > 知识库问答 >
问题:

在后台从另一个类运行函数

燕嘉熙
2023-03-14

我有工人班

class Parser: #(threading.Thread)
    ...
    def longTask(self,...)
        ...
        return
    ...

还有一个窗口类,它使用tkinter

class Window:
    ...
    def startProcess(self,...):
        p = Parser()
        t= threading.Thread(target=p.longTask())
        t.start()
        return
    ...

但是,即使长任务()是在一个单独的线程中运行,我的GUI冻结-为什么?

我的目标是更新窗口中的一个进度条,而长任务()正在运行。长任务()内部更新一个数字,范围从0到100。

问题:在longTask()运行时,如何实现这一点并防止GUI冻结?

注意:显然线程不是在我调用t.start()时启动的,而是在我通过t=线程启动线程时启动的。线程...

共有1个答案

束敏学
2023-03-14

虽然注释中的解决方案可能有效,但我发现在过去,线程技术与tkinter的做法并不一致,tkinter有自己的虚拟事件管理器。我写这篇文章是为了,如果你尝试的东西不起作用,你应该能够以这种方式实现它。

import tkinter
import tkinter.ttk
import threading
import queue
import time

def long(steps):
    time.sleep(1)
    for i in range(20):
        steps.put(5)
        time.sleep(0.2)

class Window:

    def __init__(self):
        self.steps = queue.Queue()

        self.root = tkinter.Tk()
        self.root.title("Loading")
        self.progressbar = tkinter.ttk.Progressbar(self.root)
        self.progressbar.pack(fill="both", padx=10, pady=10)

    def update(self):
        if self.progressbar["value"] == 100:
            self.root.quit()
            self.root.destroy()
        elif not self.steps.empty():
            step = self.steps.get()
            self.progressbar["value"] += step  # Not progressbar.step because it loops
        self.root.after(100, self.update)

    def main(self):
        self.update()
        self.root.mainloop()


window = Window()
t = threading.Thread(target=long, args=(window.steps,))
t.start()
window.main()

当试图让线程对象与tkinter对象进行交互时,使用某种可供两者使用的可变介质效果更好。因为增加加载条的步骤数可以改变,所以我使用了一个队列(它也是线程安全的)。每次发生某些事情时,函数都会将步骤放入队列中,tkinter应用程序有自己的循环来检查是否有任何新步骤,从而有效地调节线程和tkinter之间的交互。

这只是防止GUI冻结的另一种方法,而不是修复现有算法的方法。

 类似资料:
  • 我的Java包中有四个类。只有一个类具有方法。 当我运行方法时,我如何运行这四个类中的所有方法? 以下是我的课程: 第一类。JAVA 第二类。爪哇 第三类。JAVA 样品。JAVA

  • 我有一个函数/GUI问题。我正在编码一个轻函数,它开始一个例程,并检查时间是否在上午8点和一些停止时间之间。这个例程从早上8点开始,在那个任意的时间结束。问题是,一旦我点击这个例程的开始,图形用户界面就不会让我带着开始按钮离开窗口,因为它卡在定时例程里面了。我真的希望能够设置计时器在后台运行,然后能够离开图形用户界面的窗口。看起来线程是做到这一点的关键,但我不确定。 我将GUI代码放在一个单独的文

  • 我有一个背景图像滚动不断,但我放置了一个菜单在它上面,需要一个按键和音乐在上面。但是,我似乎无法启动keylistener。我的假设是,这是由于for循环,它在到达它的终点之前重新设置了自己。 我希望输出在for循环中运行背景图像,当按下向下箭头时,标题屏幕会改变,但它只运行背景循环

  • 假设我们的系统中有4个不同的图像,它们的名称如下: 假设我们运行container\u 1。我的问题是:container\u 1运行是否可能会保留container\u 2这样的容器?我搜索了一下,发现的问题和文章是:docker在另一个docker中运行?但这不是我的情况,我需要在container\u 1旁边运行其他容器。我对码头工人的了解很少。

  • 我使用NoSQL数据库Tarantool,并尝试使用Lua存储过程在数据库端做一些复杂的工作。我认为这是个好主意,因为我可以做更少的数据库调用,网络数据传输的开销也更小。 我有一些表格: 用户计数器:id,计数器a,计数器b,分数 例如,我有一些函数来计算字段分数: 我有另一个功能字段counter_a和counter_b更新: 如何调用recalc_score(id)函数并返回user_coun

  • 问题内容: 我想从Java代码运行另一个应用程序。 进程已启动,但在后台运行。如何使其在前台运行? 问题答案: 您应该告诉cmd.exe您希望它在新窗口中打开: