【问题标题】:Update a progressbar in a thread更新线程中的进度条
【发布时间】:2017-11-26 00:31:25
【问题描述】:

我有一个 Python 代码,可以在其中创建一个进度条。 Tkinter 环境是在带有进度条的 Gui 函数中创建的,它作为线程启动。然后在另一个线程中,我计算了进度条必须具有的值,但问题是我不知道如何使用进度条的新值更新 Gui 线程。这是我的代码:

import tkinter as tk
from tkinter import ttk
import thread

def Gui(): 
   root = tk.Tk()
   root.geometry('450x450')
   root.title('Hanix Downloader')

   button1 = tk.Button(root, text='Salir', width=25,command=root.destroy)
   button1.pack()

   s = ttk.Style()
   s.theme_use('clam')
   s.configure("green.Horizontal.TProgressbar", foreground='green', background='green')

   mpb = ttk.Progressbar(root,style="green.Horizontal.TProgressbar",orient ="horizontal",length = 200, mode ="determinate")
   mpb.pack()
   mpb["maximum"] = 3620
   mpb["value"] = 1000

   root.mainloop()

def main():
while True:
    #Calculate the new value of the progress bar.
    mpb["value"] = 100 #Does not work
    root.update_idletasks()#Does not work
    #Do some other tasks.


if __name__ == '__main__':
thread.start_new_thread( Gui,() )
thread.start_new_thread( main,() )

我得到的错误是 mpb 和 root 不存在。提前致谢。

【问题讨论】:

  • 本站有很多关于 tkinter、线程和进度条的问题和答案。在问这个问题之前你没有任何研究吗?此外,您需要修复代码示例中的缩进。
  • 是的,我查看了一些帖子和问题,但我无法解决,抱歉……我已经花了 5 个小时来解决这个问题。
  • 在控制台运行时是否收到错误消息(回溯)?总是有问题地显示它。你应该得到错误,因为mpbroot 是局部变量,它们只存在于Gui() 而不是main()
  • 是的,我收到一条错误消息,提示 mpb 和 root 不退出。
  • @Andermutu 你总是在问题中添加错误信息 - 它解释了你所有的问题。

标签: multithreading python-2.7 tkinter


【解决方案1】:

您应该得到错误,因为mpbroot 是仅存在于Gui 中而不存在于main 中的局部变量。您必须使用global 通知两个函数使用全局变量 - 然后main 将有权访问在Gui 中创建的mpb

我还在while True: 之前添加time.sleep(1),因为有时main 可能比Gui 启动得更快,并且它可能找不到mpb(因为Gui 没有时间创建进度条)

import tkinter as tk
from tkinter import ttk
import _thread
import time

def Gui():
   global root, mpb

   root = tk.Tk()

   button1 = tk.Button(root, text='Exit', command=root.destroy)
   button1.pack()

   mpb = ttk.Progressbar(root, mode="determinate")
   mpb.pack()

   mpb["maximum"] = 3000
   mpb["value"] = 1000

   root.mainloop()


def main():
    global root, mpb

    time.sleep(1)

    while True:
        mpb["value"] += 100
        #root.update_idletasks() # works without it

        #Do some other tasks.
        time.sleep(0.2)


if __name__ == '__main__':
    _thread.start_new_thread(Gui, ())
    _thread.start_new_thread(main, ())

在 Python 3.6.2、Linux Mint 18.2 上测试


编辑:更准确地说:您只需要在Gui 中使用global,因为它将值分配给变量
root = ...mpb = ...

【讨论】:

  • 谢谢你的回答,你太棒了。但是,当我按下退出按钮时,我在控制台中收到此错误消息: RuntimeError: main thread is not in main loop
  • exit 关闭窗口但线程 main 仍在运行 - 您必须在 root.destroy 之前停止此线程。您可以在main 中使用while running: 并在Gui 中设置runnig = False。使用线程可能很复杂,有时使用root.after() 代替线程更容易。
  • 非常感谢...你是最棒的。
猜你喜欢
  • 2015-04-18
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
  • 2015-07-30
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多