I have quite complex app with two, separated language version. I'm trying to make fluent switch between two versions. I'm trying to make it with multi threding to maintain tkinter GUI.
import time
import threading
from tkinter import *
language = ''
class PolishApp:
def _init__(self):
pass
def do_something(self):
while language == 'polish':
print('working in polish...')
time.sleep(0.5)
class EnglishApp:
def _init__(self):
pass
def do_something(self):
while language == 'english':
print('working in english...')
time.sleep(0.5)
def change_to_polish():
print('change to polish')
langauge = 'polish'
polish_app.do_something()
def change_to_english():
print('change to english')
langauge = 'english'
english_app.do_something()
english_app = EnglishApp()
polish_app = PolishApp()
window = Tk()
window.title("choose language")
window.geometry('350x200')
btn = Button(window, text="ENGLISH", command=threading.Thread(target=change_to_english).start())
btn2 = Button(window, text="POLISH", command=threading.Thread(target=change_to_polish).start())
btn.grid(column=1, row=0)
btn2.grid(column=2, row=0)
print(language)
window.mainloop()
When I run the code, it immediately executes functions: change_to_polish(), change_to_english() and do nothing when I click buttons.
Does anybody know how it is possible? I probably messed something up with multi threading concept.
CodePudding user response:
there are multiple problems with your program, starting from this line
btn = Button(window, text="ENGLISH", command=threading.Thread(target=change_to_english).start())
the command=threading.Thread(target=change_to_english).start()
the right part of the expression is evaluated first, which calls the function, then its return is passed as the command
argument, which is not what you want.
you want the function itself to be the argument, not its return, so you should've removed the ()
brackets at the end so that the function itself is passed as an argument, instead of its return ..... which will still not work as expected because only one instance of threading.Thread
is created, and therefore the function will only work once.
what you instead want is whenever the button is pressed, a new thread would be created to execute this, so you should use lambda functions to do this
btn = Button(window, text="ENGLISH", command=lambda: threading.Thread(target=change_to_english).start())
which is equivalent to:
def func():
threading.Thread(target=change_to_english).start()
btn = Button(window, text="ENGLISH", command=func)
this would work as intended, because each time func
is called, a new threading.Thread
is created, but there's also another typo keeping your program from functioning as you want, which is langauge
and language
are two different variables and are local to the function in which they are called, so instead you should have them named the same, and also make them both global
at the start of the functions using them so that they aren't local to the functions which use them.
CodePudding user response:
As "Ahmed AEK" said there are multiple problems in there. I've come up with the idea where both Apps are running paralell and however the language changes the App does it too.
import time
import threading
from tkinter import *
class PolishApp:
def _init__(self):
pass
def do_something(self):
while True:
if language == 'polish':
print('working in polish...')
time.sleep(0.5)
class EnglishApp:
def _init__(self):
pass
def do_something(self):
while True:
if language == 'english':
print('working in english...')
time.sleep(0.5)
def change_to_polish():
global language
print('change to polish')
language = 'polish'
def change_to_english():
global language
print('change to english')
language = 'english'
language = ''
EN = EnglishApp()
PL = PolishApp()
thread_english = threading.Thread(target=EN.do_something)
thread_english.start()
thread_polish = threading.Thread(target=PL.do_something)
thread_polish.start()
english_app = EnglishApp()
polish_app = PolishApp()
window = Tk()
window.title("choose language")
window.geometry('350x200')
btn = Button(window, text="ENGLISH", command=change_to_english)
btn2 = Button(window, text="POLISH", command=change_to_polish)
btn.grid(column=1, row=0)
btn2.grid(column=2, row=0)
print(language)
window.mainloop()