![]() |
[Tkinter] Updating Tkinter label using multiprocessing - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: [Tkinter] Updating Tkinter label using multiprocessing (/thread-37947.html) |
Updating Tkinter label using multiprocessing - Agusms - Aug-12-2022 Hi! I'm having trouble updating a label depending on a result from a function from one of the two processes I'm running. I'm trying using Queues, but can't make it work. This is a simplified example of the code: import multiprocessing as mp from tkinter import DISABLED, NORMAL, Label, LabelFrame, Tk import queue class Gui(object): def __init__(self, q): self.root = Tk() self.root.geometry('150x100') self.frameP1 = LabelFrame(self.root, text="Process1", font=("Helvetica", 14, "bold"), bd=0) self.frameP1.pack(padx=12) self.currentUserProcess1 = Label(self.frameP1, text="Current User p1", font=("Helvetica", 10, "bold")) self.currentUserProcess1.pack() self.frameP2 = LabelFrame(self.root, text="Process2", font=("Helvetica", 14, "bold"), bd=0) self.frameP2.pack() self.currentUserProcess2 = Label(self.frameP2, text="Current User p2", font=("Helvetica", 10, "bold")) self.currentUserProcess2.pack() self.root.after(100,self.CheckQueuePoll,q) def CheckQueuePoll(self, c_queue): try: str = c_queue(0) self.currentUserProcess2.configure(text=str) except queue.Empty: pass finally: self.root.after(100, self.CheckQueuePoll, q) def process1(): print("Executing process1") #doSomething def process2(): print("Executing process2") log = "Current User Process 2" q.put(log) def startProcesses(): global p1 global p2 p1 = mp.Process(target = process1) p2 = mp.Process(target = process2) p1.start() p2.start() def stopProcesses(): p1.terminate() p2.terminate() if __name__ == '__main__': q = mp.Queue() gui = Gui(q) p1 = mp.Process(target = process1, args=(q,)) p2 = mp.Process(target = process2, args=(q,)) p1.start() p2.start() gui.root.mainloop()This is giving me this error: This happens when trying to execute "str = c_queue(0)" on CheckQueuePoll function.I tried different ways of importing Queue, but I always get errors. I'd appreciate any help or hint in what I'm doing wrong. Thanks in advance! RE: Updating Tkinter label using multiprocessing - Gribouillis - Aug-12-2022 The object c_queue is not callable. Try this perhapsdef CheckQueuePoll(self, c_queue): try: str = c_queue.get_nowait() c_queue.task_done() self.currentUserProcess2.configure(text=str) except queue.Empty: pass finally: self.root.after(100, self.CheckQueuePoll, q) RE: Updating Tkinter label using multiprocessing - woooee - Aug-12-2022 Pass gui.currentUserProcess 1 or 2 to the process as an arg. Each process can then update it. RE: Updating Tkinter label using multiprocessing - Agusms - Aug-12-2022 (Aug-12-2022, 02:37 PM)Gribouillis Wrote: The object I tried it but now it gives me this errors:
So I tried passing the "q" as an argument to process1() and process2() and now I have this error: There is maybe a problem with the import? I tried importing queue in different ways though.
RE: Updating Tkinter label using multiprocessing - Agusms - Aug-12-2022 (Aug-12-2022, 07:04 PM)woooee Wrote: Pass gui.currentUserProcess 1 or 2 to the process as an arg. Each process can then update it. I tried it. This is the code I got, in case I did something wrong: class Gui(object): def __init__(self, q): self.root = Tk() self.root.geometry('150x100') self.frameP1 = LabelFrame(self.root, text="Process1", font=("Helvetica", 14, "bold"), bd=0) self.frameP1.pack(padx=12) self.currentUserProcess1 = Label(self.frameP1, text="Current User p1", font=("Helvetica", 10, "bold")) self.currentUserProcess1.pack() self.frameP2 = LabelFrame(self.root, text="Process2", font=("Helvetica", 14, "bold"), bd=0) self.frameP2.pack() self.currentUserProcess2 = Label(self.frameP2, text="Current User p2", font=("Helvetica", 10, "bold")) self.currentUserProcess2.pack() def process1(): print("Executing process1") #doSomething def process2(currentUserProcess2): print("Executing process2") log = "Current user process 2" currentUserProcess2.configure(text=log) def startProcesses(): global p1 global p2 p1 = mp.Process(target = process1, args=(gui.currentUserProcess2,)) p2 = mp.Process(target = process2, args=(gui.currentUserProcess2,)) p1.start() p2.start() def stopProcesses(): p1.terminate() p2.terminate() if __name__ == '__main__': q = mp.Queue() gui = Gui(q) p1 = mp.Process(target = process1, args=(gui.currentUserProcess2,)) p2 = mp.Process(target = process2, args=(gui.currentUserProcess2,)) p1.start() p2.start() gui.root.mainloop()I got this: I deleted CheckQueuePoll function as I understand it wouldn't be needed if I'm passing "gui.CurrenUserProcess2" in the parameters.
RE: Updating Tkinter label using multiprocessing - woooee - Aug-12-2022 I see at least 2 problems self.currentUserProcess1 = Label(self.frameP1, text="Current User p1", font=("Helvetica", 10, "bold")) self.currentUserProcess2 = Label(self.frameP2, text="Current User p2", font=("Helvetica", 10, "bold")) p1 = mp.Process(target = process1, args=(gui.currentUserProcess2,)) p2 = mp.Process(target = process2, args=(gui.currentUserProcess2,)) === def process1(): RE: Updating Tkinter label using multiprocessing - menator01 - Aug-15-2022 Are you trying to do something like this? import multiprocessing as mp import random as rnd import tkinter as tk ''' Function for updating labels Creates the que Add to the que Set label text for que Call root.after for continuous call ''' def get_num(root, label): myque = mp.Queue() myque.put(rnd.randint(1, 100)) label['text'] = f'Process {myque.get()} running...' root.after(1000, lambda: get_num(root, label)) ''' Tkinter window ''' root = tk.Tk() root.title('Running Processes') root.columnconfigure(0, weight=1) root.geometry('+300+300') ''' Two list, one to hold labelframes and one to hold labels ''' labels = [] labelframes = [] ''' Set variable j to for labelframe numbers ''' j = 1 ''' Using for loop to add 10 labels using j to number labelframes create and append labelframes to the labelframes list ''' for i in range(10): j = j if i % 2 == 0 else(j if i % 3 == 0 else j+1) labelframes.append(tk.LabelFrame(root, text=f'Processes for frame {j}')) labelframes[i].grid(column=0, row=i, sticky='new', pady=5, padx=5) ''' parent is used to place labels in the labelframes. Using i % n in this example ''' parent = labelframes[0] if i % 2 == 0 else(labelframes[1] if i % 3 == 0 else labelframes[i]) ''' Create and append labels to the labels list Using parent to color background of grouped labels in labelframe ''' labels.append(tk.Label(parent, anchor='w', padx=5, width=50)) labels[i]['bg'] = 'sandybrown' if parent == labelframes[0] \ else('tan' if parent == labelframes[1] else 'ivory2') labels[i]['relief'] = 'ridge' labels[i].grid(column=0, row=i, sticky='new', pady=5, padx=5) ''' Create and start the process ''' process = mp.Process(target=get_num, args=(root, labels[i],)) process.start() process.join() ''' Use root.after to call the get_num function ''' root.after(1, get_num, root, labels[i]) root.mainloop() |