目前我正在努力停止使用Python 3.6中的按钮停止while循环,我在Windows 10上运行tkinter。 我做了一些阅读并尝试将所有内容放在代码中(在root上调用after方法;在时间方法中为after方法提供一个int;调用函数引用,而不是函数),但我仍然无法做到让我的头围绕它。 附加的代码由于GUI线而有些冗长,麻烦的部分标有标题:
#!/usr/bin/python3
# GUI for Servotester with Arduino
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import serial
import serial.tools.list_ports
from time import time
# Servo Handler Object
class ServoLine:
def __init__(self, ServoNumber, frame_body, COMPort, master):
### Setting up the Technical Components
# GUI Basic Components
self.master = master
self.frame_body = frame_body
self.COMPort = COMPort
# Technical Components
self.PingPongExec = False # Toggle to run Ping Pong Command
self.PingPongDirect = False # Direction of Ping Pong Servo Travel
self.SleepTime = 1000 # Time to next command
self.Min = 1020
self.Max = 1980
# GUI Components
self.Place = ServoNumber
self.Mode = StringVar()
self.ServoPos = ttk.Entry(self.frame_body, width=15)
self.ServoPos.insert(0, '1500')
self.ServoMin = ttk.Entry(self.frame_body, width=15)
self.ServoMin.insert(0, '1020')
self.ServoMax = ttk.Entry(self.frame_body, width=15)
self.ServoMax.insert(0, '1980')
self.PingPongTime = ttk.Entry(self.frame_body, width=15)
self.PingPongTime.insert(0, '1000')
self.ComboMode = ttk.Combobox(self.frame_body, textvariable=self.Mode, values=('Go Straight', 'Ping Pong'), width=10)
self.Mode.set('Go Straight')
self.Start = ttk.Button(self.frame_body, text='Start', command=self.StartButton)
self.Stop = ttk.Button(self.frame_body, text='Stop', command=self.StopButton)
# Now build the GUI
ttk.Label(self.frame_body, text='{}'.format(ServoNumber)).grid(row=ServoNumber, column=0, sticky='w', padx=5)
self.ServoPos.grid(row=ServoNumber, column=1, sticky='w', padx=5)
self.ServoMin.grid(row=ServoNumber, column=2, sticky='w', padx=5)
self.ServoMax.grid(row=ServoNumber, column=3, sticky='w', padx=5)
self.PingPongTime.grid(row=ServoNumber, column=4, sticky='w', padx=5)
self.ComboMode.grid(row=ServoNumber, column=5, padx=5)
self.Start.grid(row=ServoNumber, column=6)
self.Stop.grid(row=ServoNumber, column=7)
###### TROUBLESOME PART START ######
def StartButton(self):
# GOING STRAIGHT Execution
if self.Mode.get() == 'Go Straight':
print('Servo {} is going straight to Position {}'.format(self.Place, self.ServoPos.get()))
print('The COMPort is: {}'.format(self.COMPort))
# PING PONG Execution
else:
self.PingPongExec = True
self.SleepTime = int(self.PingPongTime.get()) # Most likely not the most elegant, but I dont want to call .get() in while loop...
self.Min = self.ServoMin.get()
self.Max = self.ServoMax.get()
# Looping
while self.PingPongExec: self.RunPingPong()
def RunPingPong(self):
if self.PingPongDirect: # self.PingPongDirect is either True or False
print('Servo {} is going up to Position {}'.format(self.Place, self.Max))
self.PingPongDirect = False
self.master.after(self.SleepTime, self.RunPingPong)
print(time())
else:
print('Servo {} is going down to Position {}'.format(self.Place, self.Min))
self.PingPongDirect = True
self.master.after(self.SleepTime, self.RunPingPong)
print(time())
def StopButton(self):
self.PingPongExec = False
print('Setting PingPongExec to 0')
###### TROUBLESOME PART END ######
class ServoGUI:
def __init__(self, master):
self.master = master
self.master.resizable('false', 'false')
self.master.title('nanoServo-Driver')
# COM-Port Handling and Auto-Connecting
self.COMPortList = list()
self.COMPort = 'COM1'
self.COMPortsList = list(serial.tools.list_ports.comports()) # Get names of all COMPorts
# Try except block to be able to test programm without a Arduino attached
try:
for p in self.COMPortsList:
if "CH340" in p[1]: # Looking for a Arduino Clone
self.COMPort = p[0]
print(self.COMPort)
break
else:
pass
self.Ser = serial.Serial(self.COMPort, 57600)
self.Ser.write(2000)
except: print('Connection setup failed!')
### Frame with choice of COM-Port
frame_header=ttk.Frame(self.master)
frame_header.pack(anchor='w')
message = 'Arduino found on {}. '.format(self.COMPort)
ttk.Label(frame_header, text=message).grid(row=0, column=0, sticky='w')
ttk.Button(frame_header, text='Disconnect', command=self.Disconnect).grid(row=0, column=2, sticky='w')
# Giving connection status to the user
### Frame with Servo configuration
# Table Header
frame_body=ttk.Frame(self.master)
frame_body.pack(anchor='w')
ttk.Label(frame_body, text='Servo').grid(row=0, column=0, sticky='w', padx=5, pady=10) # Column 'Servo'
ttk.Label(frame_body, text='Servoposition [mu_s]'). grid(row=0, column=1, padx=5) # Column 'Servoposition'
ttk.Label(frame_body, text='Lower Position [mu_s]').grid(row=0, column=2, padx=5) # Column 'Lower Position'
ttk.Label(frame_body, text='Upper Position [mu_s]').grid(row=0, column=3, padx=5) # Column 'Lower Position'
ttk.Label(frame_body, text='Ping Pong Time [ms]').grid(row=0, column=4, padx=5) # Column 'Time Ping Pong'
ttk.Label(frame_body, text='Mode').grid(row=0, column=5, padx=5, sticky='w') # Column 'Lower Position'
# Calling the Objects for the Servos. Per Servo one line.
self.Servo1 = ServoLine(1, frame_body, self.COMPort, self.master)
# Disconnect Method
def Disconnect(self):
self.Ser.close()
### MAIN-Function
def main():
root = Tk()
Servo = ServoGUI(root)
root.mainloop()
if __name__ == "__main__": main()
我想通过单击Stop-Button运行StopButton方法退出StartButton方法中的while循环。 StopButton方法将属性self.PingPongExec设置为FALSE,但由于循环,它不会让我点击停止按钮。
对不起基本问题,但我脑袋里有个结。
亲切的问候,
塞巴斯蒂安
答案 0 :(得分:0)
你应该不在事件处理程序方法或函数StartButton
中运行循环!
当某些事件发生时,正在从主循环调用事件处理程序。当您的事件处理程序正在运行时,不会再进行任何事件处理。
在事件处理程序StartButton
中,只需使用after
方法来安排RunPingPong
。