【问题标题】:python multithreading problem with tkintertkinter的python多线程问题
【发布时间】:2022-08-09 16:44:53
【问题描述】:

我有两个独立的语言版本相当复杂的应用程序。我正在尝试在两个版本之间进行流畅的切换。我正在尝试使用多线程来维护 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\')
    language = \'polish\'
    polish_app.do_something()

def change_to_english():
    print(\'change to english\')
    language = \'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()

当我运行代码时,它立即执行函数:change_to_polish()、change_to_english(),当我单击按钮时什么也不做。

output

有谁知道这怎么可能?我可能把多线程概念搞砸了。

  • 回调应该是函数或方法,而不是线程。

标签: python multithreading tkinter


【解决方案1】:

从这一行开始,您的程序存在多个问题

btn = Button(window, text="ENGLISH", command=threading.Thread(target=change_to_english).start())

command=threading.Thread(target=change_to_english).start() 表达式的右边部分首先被评估,它调用函数,然后它的返回作为 command 参数传递,这不是你想要的。 你希望函数本身是参数,而不是它的返回值,所以你应该删除末尾的 () 括号,以便函数本身作为参数传递,而不是它的 return ..... 这将仍然无法按预期工作,因为只创建了一个 threading.Thread 实例,因此该函数只能工作一次。

相反,您想要的是每当按下按钮时,都会创建一个新线程来执行此操作,因此您应该使用 lambda 函数来执行此操作

btn = Button(window, text="ENGLISH", command=lambda: threading.Thread(target=change_to_english).start())

这相当于:

def func():
    threading.Thread(target=change_to_english).start()
btn = Button(window, text="ENGLISH", command=func)

这将按预期工作,因为每次调用func 时,都会创建一个新的threading.Thread,但还有另一个错字使您的程序无法按您的意愿运行,即langauge 和language 是两个不同的变量并且对于调用它们的函数是本地的,因此您应该将它们命名为相同的名称,并在使用它们的函数的开头将它们都设为global,以便它们不是使用它们的函数的本地他们。

【讨论】:

  • 谢谢!我有一个担心,你写了“每次调用 func,都会创建一个新线程”,所以如果我要在版本之间切换,比如说 10 次,会有 10 个线程?
  • 是的,如果他们没有被终止。当线程执行的函数结束时(因为循环结束),线程被终止并删除,因此可以安全地假设最终只有 2 个线程在运行,一个用于 gui(主线程),另一个用于后端/计算.
【解决方案2】:

正如“Ahmed AEK”所说,那里存在多个问题。我想出了两个应用程序并行运行的想法,但是语言改变了应用程序也会这样做。

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()

【讨论】:

    猜你喜欢
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多