Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Tkinter Gui有时会因运行更多线程而冻结_Python_Python 3.x_Tkinter_Python Multithreading - Fatal编程技术网

Python Tkinter Gui有时会因运行更多线程而冻结

Python Tkinter Gui有时会因运行更多线程而冻结,python,python-3.x,tkinter,python-multithreading,Python,Python 3.x,Tkinter,Python Multithreading,目前我有3个函数作为线程运行,其中两个只有在按下按钮时才运行。现在如果我把代码放大 添加更多线程和函数 创建更多标签和按钮 增加函数的大小 Tkinter窗口将冻结并“滞后”。我已经从在线资源中实现了线程,但不确定是否以最有效的方式实现了GUI 下面是如何做一些类似于我的文章的事情,在你询问一个例子后,我在评论中提到了你 import tkinter as tk import tkinter.font import threading import time def funct1(): i

目前我有3个函数作为线程运行,其中两个只有在按下按钮时才运行。现在如果我把代码放大

  • 添加更多线程和函数
  • 创建更多标签和按钮
  • 增加函数的大小 Tkinter窗口将冻结并“滞后”。我已经从在线资源中实现了线程,但不确定是否以最有效的方式实现了GUI

  • 下面是如何做一些类似于我的文章的事情,在你询问一个例子后,我在评论中提到了你

    import tkinter as tk
    import tkinter.font
    import threading
    import time
    def funct1():
       i = 0
       while True:
           i+=1
           time.sleep(5)
    
    
    def funct2():
       i = 0
       while True:
           i+=2
           time.sleep(5)
           label2.config(text=i)
    
    def funct3():
       i = 0
       while True:
           time.sleep(5)
           i+=2
           label3.config(text=i)
    
    thread1 = threading.Thread(target=funct1)
    thread2 = threading.Thread(target=funct2)
    thread3 = threading.Thread(target=funct3)
    
    thread1.start()
    
    mainwindow = tk.Tk()
    
    HEIGHT = 700
    WIDTH = 800
    
    canvas = tk.Canvas(mainwindow, height = HEIGHT, width = WIDTH)
    canvas.pack()
    frame = tk.Frame(mainwindow, bg='#08030D')  #inside box
    frame.place(relx=0, rely=0.1, relwidth = 0.95, relheight = 0.6)
    
    start2=tk.Button(frame, text = "to Start 2", bg='#292230',fg='white',command = thread2.start)
    start2.place(relx=0, rely=0.06, relwidth = 0.2, relheight = 0.05)
    label2 = tk.Label(frame,text = "state", bg='gray')  
    label2.place(relx=0.45, rely=0.12, relwidth = 0.07, relheight = 0.05)
    
    start3=tk.Button(frame, text = "to Start 3", bg='#292230',fg='white',command = thread3.start)
    start3.place(relx=0, rely=0.12, relwidth = 0.2, relheight = 0.05)
    label3 = tk.Label(frame,text = "state ", bg='gray')  
    label3.place(relx=0.45, rely=0.18, relwidth = 0.07, relheight = 0.05)
    mainwindow.mainloop()
    

    为什么您希望标签或按钮定期显示?换言之,你的代码的哪一部分应该实现这一点?很抱歉造成混淆,我编辑了标题。我的意思是当添加更多线程时,Tkinter会冻结。这段代码中没有添加任何标签,但当我实际添加标签时,它也会随着按钮一起冻结。我没有看到可能冻结或变得无响应的元素。我能看到的唯一错误是
    RuntimeError:通过多次单击按钮,线程只能启动一次。这个GUI还有其他组件没有提到吗?您的完整代码是否从线程发出了与Tkinter相关的调用?这是不允许的,你必须从主线程开始做所有的事情。我的实际代码只是这个版本的一个放大版本,有更多的标签和按钮来启动更多的线程。同样在我的实际代码中,threads函数正在执行更多的任务,比如从thread函数中重命名标签。
    
    import queue
    import sys
    import tkinter as tk
    import tkinter.font
    import threading
    import time
    
    WIDTH, HEIGHT = 800, 700
    LABEL2_MSGID, LABEL3_MSGID = 2, 3
    
    def funct1():
       i = 0
       while True:
           i += 1
           time.sleep(5)
    
    def funct2():
       i = 0
       while True:
           i += 2
           time.sleep(5)
           msg_queue.put((LABEL2_MSGID, i))  # Put a message in queue.
    
    def funct3():
       i = 0
       while True:
           time.sleep(5)
           i += 2
           msg_queue.put((LABEL3_MSGID, i))  # Put a message in queue.
    
    
    def process_incoming():
        """ Handle any messages currently in the queue. """
        while msg_queue.qsize():
            try:
                msg = msg_queue.get_nowait()
                # Check contents of message and do whatever is needed to the GUI.
                msg_id, text = msg
                if msg_id == LABEL2_MSGID:
                   label2.config(text=text)
                elif msg_id == LABEL3_MSGID:
                   label3.config(text=text)
                else:
                    pass  # Unknown identifier.
            except queue.Empty:
                # Shouldn't happen, but if it does, just ignore it.
                pass
    
    def periodic_call():
        """ Check every 200 ms if there is something new in the queue. """
        mainwindow.after(200, periodic_call)
        process_incoming()
        if not running:
            # This is the brutal stop of the system.  You may want to do some
            # cleanup before actually shutting it down.
            sys.exit(1)
    
    thread1 = threading.Thread(target=funct1, daemon=True)
    thread2 = threading.Thread(target=funct2, daemon=True)
    thread3 = threading.Thread(target=funct3, daemon=True)
    
    mainwindow = tk.Tk()
    msg_queue = queue.Queue()  # For inter-thread communications.
    
    canvas = tk.Canvas(mainwindow, height=HEIGHT, width=WIDTH)
    canvas.pack()
    
    frame = tk.Frame(mainwindow, bg='#08030D')  # Inside box.
    frame.place(relx=0, rely=0.1, relwidth=0.95, relheight=0.6)
    
    start2 = tk.Button(frame, text="to Start 2", bg='#292230', fg='white', command=thread2.start)
    start2.place(relx=0, rely=0.06, relwidth=0.2, relheight=0.05)
    label2 = tk.Label(frame, text="state", bg='gray')
    label2.place(relx=0.45, rely=0.12, relwidth=0.07, relheight=0.05)
    
    start3 = tk.Button(frame, text="to Start 3", bg='#292230', fg='white', command=thread3.start)
    start3.place(relx=0, rely=0.12, relwidth=0.2, relheight=0.05)
    label3 = tk.Label(frame, text="state ", bg='gray')
    label3.place(relx=0.45, rely=0.18, relwidth=0.07, relheight=0.05)
    
    running = True
    thread1.start()  # Start background thread that doesn't affect the GUI.
    periodic_call()  # Start checking and processing messages from other threads.
    mainwindow.mainloop()