我正在使用线程,那么为什么我的 gui 总是被冻结 Oo

好吧,我几天前遇到了这个问题,有人帮我解决了问题,但我的代码真的很丑(我对编码完全陌生)现在我试图以更聪明的方式让它更好,但现在我的 gui 一直都在发狂。我试着像我上次的代码那样做,但这次它不起作用。这次我要做什么我无法理解但想理解它。一些有用的提示和技巧?或者更智能、更快、更强大的方法,或者 mybae the gui more Beautyfule?


import time

import sys

from tkinter import *

import threading



root = Tk()


root.geometry("600x400")



global start

start = 1



def startUp():

    user_input()

    thr = threading.Thread(target=user_input)

    thr.start()




def user_input():

    global nameInput

    global start

    nameInput = textBox.get("1.0","end-1c")

    start = 0

    if start < 1:

        while True:

            apex = ApexLegends("APIKey")

            player = apex.player(nameInput)

            print("Gesamt Kills: " + player.kills + "\n" + 'Gesamt Damage: ' + player.damage)

            time.sleep(3)

    else:

        print("stop")



anleitung=Label(text="Gib einen Spielernamen ein und drücke Start")

anleitung.pack()


textBox=Text(root, height=1, width=30)

textBox.pack()


startButton=Button(root, height=1, width=10, text="Start", command=lambda:startUp())

startButton.pack()


浮云间
浏览 144回答 3
3回答

SMILET

Tkinter 并非设计为由多个线程访问。这是一位对 tcl 和 tk 的工作原理(tkinter 所依赖的库)有非常深入了解的人的一个很好的回答,解释了为什么会这样。从 Tkinter Tcl 回调到 python 函数在 Windows 中崩溃这是该答案中两段中的第一段:每个 Tcl 解释器对象(即知道如何运行 Tcl 过程的上下文)只能从创建它的 OS 线程中安全使用。这是因为 Tcl 不像 Python 那样使用全局解释器锁,而是广泛使用线程特定数据来减少内部所需的锁数量。(编写良好的 Tcl 代码可以利用这一点在合适的硬件上进行非常大的扩展。)

30秒到达战场

def startUp():&nbsp; &nbsp; user_input()&nbsp; &nbsp; thr = threading.Thread(target=user_input)&nbsp; &nbsp; thr.start()这看起来不对。您正在调用user_input()主线程和子线程。如果您只希望它在子线程中运行,请不要第一次调用它。def startUp():&nbsp; &nbsp; thr = threading.Thread(target=user_input)&nbsp; &nbsp; thr.start()

千巷猫影

我建议使用 oo 方法。在下面的代码中,我尝试使功能脚本适应您的代码。首先,我使用了一个变量作为self.nameInput = tk.IntVar()将用户输入存储在tk.Entry(w, bg='white', textvariable=self.nameInput).pack()我使用了 Entry 小部件而不是 Text,但它应该是相同的。此外,我使用一个类来管理线程启动和停止操作。看,我用 'check' 改变了你的 'start' 变量,因为 start 是一个保留字在python线程模块中。我试图重新创建您的代码的功能。尝试导入和使用您的 ApexLegends。import tkinter as tkimport threadingimport queueimport datetimeimport timeclass MyThread(threading.Thread):&nbsp; &nbsp; def __init__(self, queue,nameInput):&nbsp; &nbsp; &nbsp; &nbsp; threading.Thread.__init__(self)&nbsp; &nbsp; &nbsp; &nbsp; self.queue = queue&nbsp; &nbsp; &nbsp; &nbsp; self.nameInput = nameInput&nbsp; &nbsp; &nbsp; &nbsp; self.check = True&nbsp; &nbsp; def stop(self):&nbsp; &nbsp; &nbsp; &nbsp; self.check = False&nbsp; &nbsp; def run(self):&nbsp; &nbsp; &nbsp; &nbsp; while self.check:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # apex = ApexLegends("APIKey")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #player = apex.player(self.nameInput.get())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = "Gesamt Kills: " + "player.kills" + "\n" + 'Gesamt Damage: ' + "player.damage"+ "\n"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg = "{} datetime: {} nameInput {}".format(x,s,self.nameInput.get())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(3)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.queue.put(msg)class App(tk.Frame):&nbsp; &nbsp; def __init__(self,):&nbsp; &nbsp; &nbsp; &nbsp; super().__init__()&nbsp; &nbsp; &nbsp; &nbsp; self.master.title("Hello World")&nbsp; &nbsp; &nbsp; &nbsp; self.master.protocol("WM_DELETE_WINDOW",self.on_close)&nbsp; &nbsp; &nbsp; &nbsp; self.queue = queue.Queue()&nbsp; &nbsp; &nbsp; &nbsp; self.my_thread = None&nbsp; &nbsp; &nbsp; &nbsp; self.nameInput = tk.IntVar()&nbsp; &nbsp; &nbsp; &nbsp; self.init_ui()&nbsp; &nbsp; def init_ui(self):&nbsp; &nbsp; &nbsp; &nbsp; self.f = tk.Frame()&nbsp; &nbsp; &nbsp; &nbsp; w = tk.Frame()&nbsp; &nbsp; &nbsp; &nbsp; tk.Label(w, text = "Gib einen Spielernamen ein und drücke Start").pack()&nbsp; &nbsp; &nbsp; &nbsp; tk.Entry(w, bg='white', textvariable=self.nameInput).pack()&nbsp; &nbsp; &nbsp; &nbsp; w.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)&nbsp; &nbsp; &nbsp; &nbsp; w = tk.Frame()&nbsp; &nbsp; &nbsp; &nbsp; tk.Button(w, text="Start", command=self.startUp).pack()&nbsp; &nbsp; &nbsp; &nbsp; tk.Button(w, text="Stop", command=self.stop_thread).pack()&nbsp; &nbsp; &nbsp; &nbsp; tk.Button(w, text="Close", command=self.on_close).pack()&nbsp; &nbsp; &nbsp; &nbsp; w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)&nbsp; &nbsp; &nbsp; &nbsp; self.f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)&nbsp; &nbsp; def startUp(self):&nbsp; &nbsp; &nbsp; &nbsp; if (threading.active_count()!=0):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.my_thread = MyThread(self.queue,self.nameInput)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.my_thread.start()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.periodiccall()&nbsp; &nbsp; def stop_thread(self):&nbsp; &nbsp; &nbsp;if(threading.active_count()!=1):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self.my_thread.stop()&nbsp; &nbsp; def periodiccall(self):&nbsp; &nbsp; &nbsp; &nbsp; self.checkqueue()&nbsp; &nbsp; &nbsp; &nbsp; if self.my_thread.is_alive():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.after(1, self.periodiccall)&nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pass&nbsp; &nbsp; def checkqueue(self):&nbsp; &nbsp; &nbsp; &nbsp; while self.queue.qsize():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = self.queue.get(0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg = "%s"%(ret)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(msg)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; except queue.Empty:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pass&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; def on_close(self):&nbsp; &nbsp; &nbsp; &nbsp; if(threading.active_count()!=0):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if self.my_thread is not None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.my_thread.stop()&nbsp; &nbsp; &nbsp; &nbsp; self.master.destroy()if __name__ == '__main__':&nbsp; &nbsp; app = App()&nbsp; &nbsp; app.mainloop()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python