简体   繁体   中英

Sharing variables between threads in Python tkinter

Is it possible to get the GUI to update variable 'a' to update in real time while 'thread2' increments the value?

import tkinter as tk
from threading import Thread
import time


a = 0  # global variable

def thread1(threadname):
    root = tk.Tk()
    w = tk.Label(root, text=a)
    w.pack()
    root.mainloop()


def thread2(threadname):
    global a
    while True:
        a += 1
        time.sleep(1)


thread1 = Thread( target=thread1, args=("Thread-1", ) )
thread2 = Thread( target=thread2, args=("Thread-2", ) )

thread1.start()
thread2.start()

If I create a loop and print 'a' I get the correct result.

def thread1(threadname):
    global a
    while True:
        print(a)
 #   root = tk.Tk()
 #   w = tk.Label(root, text=a)
 #   w.pack()
 #   root.mainloop()

Any help would be appreciated

Try using a <tkinter.Tk>.after loop like this:

import tkinter as tk

def loop():
    global a
    a += 1
    label.config(text=a)
    # run `loop` again in 1000 ms
    root.after(1000, loop)

a = 0
root = tk.Tk()
label = tk.Label(root, text=a)
label.pack()
loop() # Start the loop
root.mainloop()

I used a .after script because tkinter and threading don't go together very well. Sometimes tkinter can crash without even giving you an error message if you try to call some tkinter commands from the second thread.

When you create your label, that's not a "live" connection. That passes the current value of the variable a . You then enter your main loop, and that thread does nothing else until the application exits. You need to send the new value to a function that executes as part of the main thread, and that function will need access to the label.

This works:

import tkinter as tk
from threading import Thread
import time


class GUI(object):
    def __init__(self):
        self.a = 0 
        self.w = tk.Label(root, text=self.a)
        self.w.pack()
        thread2 = Thread( target=self.thread2, args=("Thread-2", ) )
        thread2.start()

    def thread2(self,threadname):
        while True:
            self.a += 1
            root.after_idle(self.update)
            time.sleep(1)

    def update(self):
        self.w.config(text=self.a)

root = tk.Tk()
gui = GUI()
root.mainloop()

It is possible to make a live connection using textvariable , but then you have to change the type of a to a tkinter.StringVariable . Check here: Update Tkinter Label from variable

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM