gpt4 book ai didi

multithreading - 从 python3 中的 multiprocess.proccess 更新 tk ProgressBar

转载 作者:行者123 更新时间:2023-12-04 21:23:38 34 4
gpt4 key购买 nike

我已经成功创建了一个线程的线程示例,它可以随时更新进度条。然而,到目前为止,对多处理做同样的事情让我望而却步。
我开始怀疑是否可以以这种方式使用 tkinter。有人做过吗?

我在 OS X 10.7 上运行。我环顾四周,知道不同的操作系统可能表现得非常不同,尤其是多处理和 tkinter。

我尝试了一个生产者,它通过命名空间和 event.wait 以及 event.set 直接与小部件对话。我已经对生产者与消费者对话做了同样的事情,消费者是与小部件对话的方法或函数。所有这些事情都成功运行,但没有直观地更新小部件。虽然我已经在 IntVar 上完成了 get(),但在使用 widget.step() 和/或 widget.set() 时,小部件绑定(bind)到并看到它发生了变化。我什至尝试在子进程中运行一个单独的 tk() 实例。没有更新进度条。

这是较简单的版本之一。子进程是对象上的一种方法,它是 Progressbar 小部件的包装器。 tk GUI 作为主进程运行。我还发现小部件在循环结束时没有被破坏有点奇怪,这可能是我不理解其含义的线索。

import multiprocessing
from tkinter import *
from tkinter import ttk
import time

root = Tk()

class main_window:

def __init__(self):
self.dialog_count = 0

self.parent = root
self.parent.title('multiprocessing progess bar')

frame = ttk.Labelframe(self.parent)
frame.pack(pady=10, padx=10)

btn = ttk.Button(frame, text="Cancel")
btn.bind("<Button-1>", self.cancel)
btn.grid(row=0, column=1, pady=10)

btn = ttk.Button(frame, text="progress_bar")
btn.bind("<Button-1>", self.pbar)
btn.grid(row=0, column=2, pady=10)

self.parent.mainloop()

def pbar(self, event):

name="producer %d" % self.dialog_count
self.dialog_count += 1

pbar = pbar_dialog(self.parent, title=name)

event = multiprocessing.Event()
p = multiprocessing.Process(target=pbar.consumer, args=(None, event))

p.start()



def cancel(self, event):
self.parent.destroy()



class pbar_dialog:

toplevel=None
pbar_count = 0

def __init__(self, parent, ns=None, event=None, title=None, max=100):
self.ns = ns
self.pbar_value = IntVar()
self.max = max

pbar_dialog.pbar_count += 1
self.pbar_value.set(0)


if not pbar_dialog.toplevel:
pbar_dialog.toplevel= Toplevel(parent)

self.frame = ttk.Labelframe(pbar_dialog.toplevel, text=title)
#self.frame.pack()
self.pbar = ttk.Progressbar(self.frame, length=300, variable=self.pbar_value)
self.pbar.grid(row=0, column=1, columnspan=2, padx=5, pady=5)

btn = ttk.Button(self.frame, text="Cancel")
btn.bind("<Button-1>", self.cancel)
btn.grid(row=0, column=3, pady=10)
self.frame.pack()


def set(self,value):
self.pbar_value.set(value)

def step(self,increment=1):
self.pbar.step(increment)
print ("Current", self.pbar_value.get())

def cancel(self, event):
self.destroy()

def destroy(self):
self.frame.destroy()
pbar_dialog.pbar_count -= 1
if pbar_dialog.pbar_count == 0:
pbar_dialog.toplevel.destroy()

def consumer(self, ns, event):
for i in range(21):
#event.wait(2)
self.step(5)
#self.set(i)
print("Consumer", i)
self.destroy()



if __name__ == '__main__':
main_window()

相比之下,这里是完美运行的线程版本。
import threading
from tkinter import *
from tkinter import ttk
import time

root = Tk()

class main_window:

def __init__(self):
self.dialog_count = 0

self.parent = root
self.parent.title('multiprocessing progess bar')

frame = ttk.Labelframe(self.parent)
frame.pack(pady=10, padx=10)

btn = ttk.Button(frame, text="Cancel")
btn.bind("<Button-1>", self.cancel)
btn.grid(row=0, column=1, pady=10)

btn = ttk.Button(frame, text="progress_bar")
btn.bind("<Button-1>", self.pbar)
btn.grid(row=0, column=2, pady=10)

self.parent.mainloop()


def producer(self, pbar):
i=0
while i < 101:
time.sleep(1)
pbar.step(1)
i += 1
pbar.destroy()


def pbar(self, event):

name="producer %d" % self.dialog_count
self.dialog_count += 1

pbar = pbar_dialog(self.parent, title=name)

p = threading.Thread(name=name, target=self.producer, args=(pbar,))

p.start()

#p.join()


def cancel(self, event):
self.parent.destroy()



class pbar_dialog:

toplevel=None
pbar_count = 0

def __init__(self, parent, ns=None, event=None, title=None, max=100):
self.ns = ns
self.pbar_value = IntVar()
self.title = title
self.max = max

pbar_dialog.pbar_count += 1

if not pbar_dialog.toplevel:
pbar_dialog.toplevel= Toplevel(parent)

self.frame = ttk.Labelframe(pbar_dialog.toplevel, text=title)
#self.frame.pack()
self.pbar = ttk.Progressbar(self.frame, length=300, variable=self.pbar_value)
self.pbar.grid(row=0, column=1, columnspan=2, padx=5, pady=5)

btn = ttk.Button(self.frame, text="Cancel")
btn.bind("<Button-1>", self.cancel)
btn.grid(row=0, column=3, pady=10)
self.frame.pack()

self.set(0)

def set(self,value):
self.pbar_value.set(value)

def step(self,increment=1):
self.pbar.step(increment)

def cancel(self, event):
self.destroy()

def destroy(self):
self.frame.destroy()
pbar_dialog.pbar_count -= 1
if pbar_dialog.pbar_count == 0:
pbar_dialog.toplevel.destroy()
pbar_dialog.toplevel = None

def automatic(self, ns, event):
for i in range(1,100):
self.step()

if __name__ == '__main__':
main_window()

最佳答案

做类似的事情,我最终不得不使用线程和进程的组合 - GUI 前端有两个线程:一个用于 tkinter,一个从 multiprocessing.Queue 读取并调用 gui.update() - 然后是后端进程会将更新写入该队列

关于multithreading - 从 python3 中的 multiprocess.proccess 更新 tk ProgressBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7576310/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com