执行命令 + 进度条时 tkinter 没有响应。 (多线程)
tkinter not responding when executing command + progressbar. (multi-thread)
对于我的项目,我实现了一个与可穿戴传感器连接的图形界面。
我编写了一个直接与 3 个传感器接口的代码 (multi.py)。然后我为图形界面 (GUI.py) 编写了一些代码,当我单击按钮时,它会调用 multi.py 的不同部分。
当我调用“configure_clicked ()”和“download_clicked ()”形成各自的按钮时,GUI 冻结(继续工作),因为函数被调用(multi.configure & multi.download ) 需要一些时间才能完成(连接到设备并从设备下载数据)。我知道我必须做另一个“线程”--> 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()
这就是确保 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 会崩溃。
发生的事情是您的计算和 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")
并且您对所有其他方法执行类似的操作。之后一切正常。
对于我的项目,我实现了一个与可穿戴传感器连接的图形界面。 我编写了一个直接与 3 个传感器接口的代码 (multi.py)。然后我为图形界面 (GUI.py) 编写了一些代码,当我单击按钮时,它会调用 multi.py 的不同部分。
当我调用“configure_clicked ()”和“download_clicked ()”形成各自的按钮时,GUI 冻结(继续工作),因为函数被调用(multi.configure & multi.download ) 需要一些时间才能完成(连接到设备并从设备下载数据)。我知道我必须做另一个“线程”--> 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()
这就是确保 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 会崩溃。
发生的事情是您的计算和 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")
并且您对所有其他方法执行类似的操作。之后一切正常。