我想制作一个电机控制应用程序。我有3个窗口,如下(不幸的是我无法上传图片,我可以用其他方式上传它们):
所以,我想要做的是当用户点击然后“GO”按钮电机旋转时,当用户点击“STOP”按钮时电机停止。按下“GO”按钮后,我还想进入一个不同的窗口,例如顶部和底部图片中的窗口。
但是,单击“开始”按钮后,GUI会冻结。有没有一种方法可以不冻结GUI并允许我获得所需的功能?
#! usr/bin/env python
import threading
import serial
import time
import tkinter as tk
System_State_is_Run=False
class DH_Corp_SCADA2(tk.Tk):
def __init__(self, *args,**kwargs):
tk.Tk.__init__(self, *args, *kwargs)
container=tk.Frame(self)
container.pack(side="top",fill="both",expand=True)
container.grid_rowconfigure(0,weight=10)
container.grid_columnconfigure(0,weight=10)
self.frames={}
for F in (HomePage, ControlPage, Speed1Page):
frame=F(container,self)
self.frames[F]=frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(HomePage)
def show_frame(self,cont):
frame=self.frames[cont]
frame.tkraise()
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
someLabel=tk.Label(self,text='Welcome to the AGC SCADA....')
AGC_Control=tk.Button(self,text='AGC Control & Parameters',
command=lambda:controller.show_frame(ControlPage))
AGC_Speed=tk.Button(self,text='Monitor Speed',command=lambda:
controller.show_frame(Speed1Page))
Exit_Button=tk.Button(self, text='Exit',command=close_window)
someLabel.grid(row=0, sticky="W")
AGC_Control.grid(row=2, column=1, sticky="EW",padx=2,pady=2)
AGC_Speed.grid(row=3,column=1, sticky="EW", padx=2,pady=2)
Exit_Button.grid(row=4,column=1, sticky="EW",padx=2,pady=2)
class ControlPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
someLabel1=tk.Label(self,text='From this page you may change p.')
Go_Home1=tk.Button(self,text='Home Page',command=lambda:controller.show_frame(HomePage))
AGC_Speed=tk.Button(self,text='Monitor Speed',command=lambda:controller.show_frame(Speed1Page))
Exit_Button=tk.Button(self, text='Exit',command=close_window)
Go_Button=tk.Button(self,text='GO',command=System_State_is_RunXY1)
Stop_Button=tk.Button(self,text='STOP', command=System_State_is_RunXY2)
someLabel1.grid(row=0, sticky="W")
Go_Button.grid(row=2,column=1, sticky="EW",padx=2,pady=2)
Stop_Button.grid(row=3,column=1, sticky="EW",padx=2,pady=2)
Go_Home1.grid(row=4, column=1, sticky="EW",padx=2,pady=2)
AGC_Speed.grid(row=5,column=1, sticky="EW", padx=2,pady=2)
Exit_Button.grid(row=6,column=1, sticky="EW",padx=2,pady=2)
class Speed1Page(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
someLabel2=tk.Label(self,text='From this page you can monitor speed parameter in channel 1 or left motor.')
Go_Home2=tk.Button(self,text='Home Page',command=lambda
:controller.show_frame(HomePage))
AGC_Control=tk.Button(self,text='AGC Control & Parameters',command=
lambda:controller.show_frame(ControlPage))
Exit_Button=tk.Button(self, text='Exit',command=close_window)
someLabel2.grid(row=0, sticky="W")
Go_Home2.grid(row=2,column=1, sticky="EW", padx=2,pady=2)
AGC_Control.grid(row=3, column=1, sticky="EW",padx=2,pady=2)
Exit_Button.grid(row=4,column=1, sticky="EW",padx=2,pady=2)
def System_State_is_RunXY1():
global System_State_is_Run
System_State_is_Run=True
print(System_State_is_Run)#check if System_State_is_Run changes
running_car()
def System_State_is_RunXY2():
global System_State_is_Run
System_State_is_Run=False
print(System_State_is_Run)#check if System_State_is_Run changes
running_car()
def running_car():
print(System_State_is_Run)#check if System_State_is_Run changes
if System_State_is_Run==True:
motor_run_callback()
running_car()
else:
motor_off_callback()
return
def motor_run_callback():# set motor speed to 25rpm
ser = serial.Serial('COM6',115200,timeout=0)
time.sleep(0.025)
ser.write(bytes('!G 1 250\r','utf-8'))
ser.close()
return
def motor_off_callback(): #set motor speed to 0
ser = serial.Serial('COM6',115200,timeout=0)
time.sleep(0.025)
ser.write(bytes('!G 1 0\r','utf-8'))
ser.close()
def close_window():
app.destroy()
app=DH_Corp_SCADA2()
app.mainloop()
答案 0 :(得分:0)
System_State_is_RunXY1
。 System_State_is_RunXY1
将System_State_is_Run
设置为True
,然后调用running_car()
。
running_car()
看到System_State_is_Run
为True
,并调用motor_run_callback()
,然后再次调用。 running_car()
看到System_State_is_Run
为True
,并调用motor_run_callback()
,然后再次调用。 running_car()
看到System_State_is_Run
为True
,并调用motor_run_callback()
,然后再次调用。 在该逻辑中,您是否允许GUI处理事件。由于tkinter是单线程的,因此必须允许事件循环处理事件以使GUI保持响应。
无论您是否可视化,您都在有效地制作动画。动画通常使用after
方法完成。你调用的函数可以完成一些工作(动画电机,监视端口等),然后在几毫秒内再次调用自己。在完成之后但在再次调用之前的时间内,事件循环有机会处理诸如点击"停止"之类的事件。按钮。
有关稍长的说明,请参阅https://stackoverflow.com/a/11505034/7432