Ned Hulton
Ned Hulton

Reputation: 678

Tkinter and threading to control continuous background process

I want to use Tkinter to interact with another thread. The output (assuming the user clicks the button after two seconds) should be:

Steve
Steve
Joline
Joline
Joline

Where am I going wrong?

from Tkinter import *
import time
import threading
from threading import Thread


def changeName():
    person = "Joline"


def controls():
    root = Tk()
    button = Button(text="Change Name", command=changeName)
    button.pack(side=LEFT)
    root.mainloop()


def work():
    person = "Steve"
    for _ in range(5):
        print("hello " + person)
        time.sleep(1)


Thread(target = controls).start()
Thread(target = work).start()

Upvotes: 0

Views: 377

Answers (2)

Ned Hulton
Ned Hulton

Reputation: 678

I had forgotten to make the "person" variable global. Here is what I should have done to get the desired result:

from Tkinter import *
import time
import threading
from threading import Thread

person = ""

def changeName():
    global person
    person = "Sonia"


def controls():
    root = Tk()
    button = Button(text="Change Name", command=changeName)
    button.pack(side=LEFT)
    root.mainloop()


def work():
    for _ in range(10):
        print("hello " + person)
        time.sleep(1)


Thread(target = controls).start()
Thread(target = work).start()

Upvotes: 0

Pythonista
Pythonista

Reputation: 11615

Edit: Your name variables are never changed because they are local to the respective functions they are in. This is a bad approach even if it does work. Tkinter is already one giant thread loop (what do you think mainloop is doing, it's looping checking for events in the queue to process) you shouldn't be putting it inside another loop and we can use built-in methods to achieve this.

Just for kicks I imported string and random to create random strings so you could see it working.

The changeName function could use sleep but we already have tkinter imported and it already has built-in functionality / event queue so why not use it...

I just added the name as an attribute to the Tk class rather than having to worry about globals, locals, etc.

import tkinter as tk, string, random

root = tk.Tk()
root.name = "a name"

def changeName(shouldRun=False):

    if not shouldRun:
        root.after(2000, changeName, True)
    else:
        root.name = "".join([random.choice(string.ascii_letters) for _ in range(10)])

def printName():

    print(root.name)
    root.after(1000, printName)

btn = tk.Button(root, text="Change Name", command=changeName)
btn.pack()
printName()
root.mainloop()

Upvotes: 1

Related Questions