저는 Windows 10에서 실행되는 tkinter를 사용하여 파이썬 3.6의 버튼으로 while 루프를 멈추는 데 어려움을 겪고 있습니다. 나는 꽤 많은 독서를했으며 모든 것을 넣으려고했습니다. 코드에서 (루트에서 after 메소드를 호출하고, after 메소드에 시간에 대한 int를 제공하고, 함수가 아닌 함수 참조를 호출한다.) 그러나 여전히 나는 그 머리를 아직 둘러 볼 수 없다. 추가 코드 인해 GUI 라인에 다소 긴입니다, 성가신 부분은 헤드 라인으로 표시됩니다 :파이썬 3.6 + tkinter : 버튼을 사용하여 while 루프를 멈추십시오.
#!/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()
내가 클릭하여 stopButton이라는 메소드를 실행하여 StartButton-방법의 동안 루프를 종료 할 정지 버튼. StopButton 메서드는 self.PingPongExec 속성을 FALSE로 설정하지만 루프 때문에 중지 버튼을 클릭 할 수 없습니다.
미안하지만 기본 질문에 대해서는 매듭이 들었다.
종류와 관련,
세바스찬
'RunPingPong'을 실행하기 위해'while' 대신'tkiner.after (milliseconds, function_name)'를 사용하면 tkinter의 모든 작업을 수행하는'mainloop()'을 멈추지 않습니다 - 마우스/키 이벤트를 가져오고, 위젯을 업데이트, 위젯을 다시 그리기, 위젯을 다시 그리기, 버튼에 지정된 기능 실행, after() 등으로 지정된 함수를 실행합니다. – furas