【问题标题】:tkinter not responding when executing command + progressbar. (multi-thread)tkinter 在执行命令 + 进度条时没有响应。 (多线程)
【发布时间】:2021-02-23 23:20:47
【问题描述】:

在我的项目中,我实现了一个与可穿戴传感器交互的图形界面。 我编写了一个直接与 3 个传感器接口的代码 (multi.py)。然后我为图形界面 (GUI.py) 编写了一些代码,当我单击按钮时,它会调用我 multi.py 的不同部分。

当我调用“configure_clicked ()”和“download_clicked ()”形成各自的按钮时,GUI 冻结(继续工作),因为调用函数(multi.configure & multi.dow​​nload)需要一些时间才能完成(连接到设备并从设备下载数据)。我知道我必须做另一个“线程”--> MULTITHREAD。请问,谁能帮我创建一个多线程???

我也有“进度条”,它应该在每个函数的开头开始,但对于“configure_clicked ()”和“download_clicked ()”来说,这不会发生,而我设法在“start_clicked”和“stop_clicked”之间滑动它”。

我附上代码。 提前感谢谁会帮助我。

from tkinter import * 
from tkinter import messagebox, ttk
import multi_sensor_acc_gyro1 as multi 

class GUI:

    def __init__(self,master):
        self.master=master
        self.states=[]

        ...
        ...
        #configure button
        self.btn_configure=Button(self.quadro_pulsanti_sx,relief=RAISED,command=self.configure_clicked)
        #start button
        self.btn_start=Button(self.quadro_pulsanti_dx,command=self.start_clicked,relief=RAISED)
        #stop button 
        self.btn_stop=Button(self.quadro_pulsanti_dx,command=self.stop_clicked,relief=RAISED)
        #download button
        self.btn_download=Button(self.quadro_pulsanti_dx,command=self.download_clicked,relief=RAISED)
        #save button 
        self.btn_save=Button(self.quadro_pulsanti_dx,relief=RAISED,command=self.save_clicked)
        #reset button 
        self.btn_reset=Button(self.quadro_pulsanti_sx,relief=RAISED,command=self.reset_clicked)
        #progress bar 
        self.pb=ttk.Progressbar(self.quadro_pulsanti_basso,orient=HORIZONTAL,length=350,mode="indeterminate")
        self.label_pb=Label(self.quadro_pulsanti_basso,text="")

    def configure_clicked(self):
        mac_address=["F7:64:55:AD:0A:19","F2:A1:3A:E2:F2:ED","F9:8E:32:DD:1A:EB"]
        
        output_1=multi.configure(mac_address) 
        self.states=output_1[0]
        self.loggers_acc=output_1[1]
        self.loggers_gyro=output_1[2]

        self.label_pb.configure(text="")
        messagebox.showinfo("CONFIGURE clicked","the sensors have been configured\n\nclick OK to continue")

    def start_clicked(self):

        multi.start(self.states)
        
        self.pb.start()
        self.label_pb.configure(text="registration in progress...")

    def stop_clicked(self):

        self.pb.stop()
        self.label_pb.configure(text="")

        multi.stop(self.states)
    
    def download_clicked(self):

        #self.pb.start()
        #self.label_pb.configure(text="Download in progress...")

        output_2=multi.download(self.states,self.loggers_acc,self.loggers_gyro) 
        self.df_tr_tot=output_2[0]
        self.df_gd_tot=output_2[1]
        self.df_gs_tot=output_2[2]

        #self.label_pb.configure(text="")
        #self.pb.stop()

        messagebox.showinfo("DOWNLOAD clicked","the data has been downloaded\n\nclick OK to continue")

         
    def save_clicked(self):
        
        #self.txt_pz.focus_set()
        #self.txt_pz.get()
        
        self.txt_pz.focus_set()
        id_pz=self.txt_pz.get()
        
        multi.save(self.df_tr_tot,self.df_gd_tot,self.df_gs_tot,id_pz)

        messagebox.showinfo("SAVE clicked","I dati sono stati salvati\n\ncliccare OK per continuare")

window = Tk()
window.title("   Grafic User Interface for MMR")
window.iconbitmap('C:/Users/salvo/Documents/MetaWear-SDK-Python/examples/favicon.ico')
    
height=560
width=540 
left=(window.winfo_screenwidth()-width)/2 
top=(window.winfo_screenheight()-height)/2 
geometry="%dx%d+%d+%d" % (width,height,left,top) 
window.geometry(geometry)

gui=GUI(window)

window.mainloop()

【问题讨论】:

  • 感谢您解决问题。我需要更多帮助:我通常从命令行运行代码,然后我可以看到任何错误(回溯(最后一次调用):...)。但是,在完成了可执行的 .exe 之后,我无法获得可能的错误的反馈。我想收到一条错误消息(messagebox.showerror)。我该怎么办?

标签: python multithreading tkinter progress-bar freeze


【解决方案1】:

这是确保 tkinter 在运行长任务时不会停止响应的方法:

import threading
from time import sleep

def operation():
    # Create a new thread
    new_thread = threading.Thread(target=_operation, daemon=True)
    # Start the thread
    new_thread.start()
    # continue code or run this:
    while new_thread.is_alive(): # While the new thread is still running
        # Here you can also add a loading screen
        # Make sure tkinter doesn't say that it isn't responding
        tkinter_widget.update() # `tkinter_widget` can be any tkinter widget/window
        sleep(0.1) # A bit of delay so that it doesn't use 300% of your CPU

def _operation()
    # Here you can do the operation that will take a long time
    pass

当您需要运行操作调用operation 时,它将启动新线程。注意:确保您没有在新线程中有任何 tkinter 内容,因为 tkinter 会崩溃。

【讨论】:

    【解决方案2】:

    发生的情况是您的计算和 Tkinter 都存在于同一个线程中,因此为了执行计算,必须暂停 Tkinter 的 mainloop() 的执行,直到这些进程完成。最简单的解决方案是添加一些辅助方法,并在按下按钮时在单独的线程中调用它们:

    from threading import Thread
    
     def configure_clicked(self):
         t = Thread(target=self._configure_clicked)
         t.start()
    
     def _configure_clicked(self):
    
         mac_address=["F7:64:55:AD:0A:19","F2:A1:3A:E2:F2:ED","F9:8E:32:DD:1A:EB"]
            
         output_1=multi.configure(mac_address) 
         self.states=output_1[0]
         self.loggers_acc=output_1[1]
         self.loggers_gyro=output_1[2]
    
         self.label_pb.configure(text="")
         messagebox.showinfo("CONFIGURE clicked","the sensors have been configured\n\nclick OK to continue")
    

    你做的事情与所有其他方法类似。之后一切都会正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      • 2019-03-15
      • 2021-10-07
      相关资源
      最近更新 更多