运行电机直到按下停止按钮,但能够在窗口之间切换

时间:2015-09-21 12:08:22

标签: python tkinter

我想制作一个电机控制应用程序。我有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()

1 个答案:

答案 0 :(得分:0)

  • 按钮调用System_State_is_RunXY1
  • System_State_is_RunXY1System_State_is_Run设置为True,然后调用running_car()
    • running_car()看到System_State_is_RunTrue,并调用motor_run_callback(),然后再次调用
    • running_car()看到System_State_is_RunTrue,并调用motor_run_callback(),然后再次调用
    • running_car()看到System_State_is_RunTrue,并调用motor_run_callback(),然后再次调用
    • ......等等

在该逻辑中,您是否允许GUI处理事件。由于tkinter是单线程的,因此必须允许事件循环处理事件以使GUI保持响应。

无论您是否可视化,您都在有效地制作动画。动画通常使用after方法完成。你调用的函数可以完成一些工作(动画电机,监视端口等),然后在几毫秒内再次调用自己。在完成之后但在再次调用之前的时间内,事件循环有机会处理诸如点击"停止"之类的事件。按钮。

有关稍长的说明,请参阅https://stackoverflow.com/a/11505034/7432