3 回答

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超4個(gè)贊
Tkinter 并非設(shè)計(jì)為由多個(gè)線程訪問(wèn)。這是一位對(duì) tcl 和 tk 的工作原理(tkinter 所依賴的庫(kù))有非常深入了解的人的一個(gè)很好的回答,解釋了為什么會(huì)這樣。
從 Tkinter Tcl 回調(diào)到 python 函數(shù)在 Windows 中崩潰
這是該答案中兩段中的第一段:
每個(gè) Tcl 解釋器對(duì)象(即知道如何運(yùn)行 Tcl 過(guò)程的上下文)只能從創(chuàng)建它的 OS 線程中安全使用。這是因?yàn)?Tcl 不像 Python 那樣使用全局解釋器鎖,而是廣泛使用線程特定數(shù)據(jù)來(lái)減少內(nèi)部所需的鎖數(shù)量。(編寫(xiě)良好的 Tcl 代碼可以利用這一點(diǎn)在合適的硬件上進(jìn)行非常大的擴(kuò)展。)

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超6個(gè)贊
def startUp():
user_input()
thr = threading.Thread(target=user_input)
thr.start()
這看起來(lái)不對(duì)。您正在調(diào)用user_input()主線程和子線程。如果您只希望它在子線程中運(yùn)行,請(qǐng)不要第一次調(diào)用它。
def startUp():
thr = threading.Thread(target=user_input)
thr.start()

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超7個(gè)贊
我建議使用 oo 方法。
在下面的代碼中,我嘗試使功能腳本適應(yīng)您的代碼。
首先,我使用了一個(gè)變量作為
self.nameInput = tk.IntVar()
將用戶輸入存儲(chǔ)在
tk.Entry(w, bg='white', textvariable=self.nameInput).pack()
我使用了 Entry 小部件而不是 Text,但它應(yīng)該是相同的。
此外,我使用一個(gè)類來(lái)管理線程啟動(dòng)和停止操作。
看,我用 'check' 改變了你的 'start' 變量,因?yàn)?start 是一個(gè)保留字
在python線程模塊中。
我試圖重新創(chuàng)建您的代碼的功能。
嘗試導(dǎo)入和使用您的 ApexLegends。
import tkinter as tk
import threading
import queue
import datetime
import time
class MyThread(threading.Thread):
def __init__(self, queue,nameInput):
threading.Thread.__init__(self)
self.queue = queue
self.nameInput = nameInput
self.check = True
def stop(self):
self.check = False
def run(self):
while self.check:
# apex = ApexLegends("APIKey")
#player = apex.player(self.nameInput.get())
x = "Gesamt Kills: " + "player.kills" + "\n" + 'Gesamt Damage: ' + "player.damage"+ "\n"
s = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
msg = "{} datetime: {} nameInput {}".format(x,s,self.nameInput.get())
time.sleep(3)
self.queue.put(msg)
class App(tk.Frame):
def __init__(self,):
super().__init__()
self.master.title("Hello World")
self.master.protocol("WM_DELETE_WINDOW",self.on_close)
self.queue = queue.Queue()
self.my_thread = None
self.nameInput = tk.IntVar()
self.init_ui()
def init_ui(self):
self.f = tk.Frame()
w = tk.Frame()
tk.Label(w, text = "Gib einen Spielernamen ein und drücke Start").pack()
tk.Entry(w, bg='white', textvariable=self.nameInput).pack()
w.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
w = tk.Frame()
tk.Button(w, text="Start", command=self.startUp).pack()
tk.Button(w, text="Stop", command=self.stop_thread).pack()
tk.Button(w, text="Close", command=self.on_close).pack()
w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)
self.f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
def startUp(self):
if (threading.active_count()!=0):
self.my_thread = MyThread(self.queue,self.nameInput)
self.my_thread.start()
self.periodiccall()
def stop_thread(self):
if(threading.active_count()!=1):
self.my_thread.stop()
def periodiccall(self):
self.checkqueue()
if self.my_thread.is_alive():
self.after(1, self.periodiccall)
else:
pass
def checkqueue(self):
while self.queue.qsize():
try:
ret = self.queue.get(0)
msg = "%s"%(ret)
print(msg)
except queue.Empty:
pass
def on_close(self):
if(threading.active_count()!=0):
if self.my_thread is not None:
self.my_thread.stop()
self.master.destroy()
if __name__ == '__main__':
app = App()
app.mainloop()
添加回答
舉報(bào)