Как создать кнопку для завершения программы, не заканчивая GUI? - PullRequest
1 голос
/ 03 июля 2019

Я пытаюсь сделать графический интерфейс пользователя более удобным для пользователя, но они запросили кнопку остановки, которая завершит текущую программу, не закрывая фактическое окно графического интерфейса пользователя.

Я понимаю, что многопоточность может быть способом сделать это, поскольку, когда нажата кнопка «Пуск», она занимает все окно графического интерфейса и ничего не может быть нажата, но я не уверен, как на самом деле реализовать это в моем коде.

Я ожидаю, что смогу нажать кнопку остановки и вернуть GPIO в отключенное состояние, а затем снова нажать кнопку запуска и снова запустить программу в начале.

import tkinter as tk
import RPi.GPIO as GPIO
import time as time
from time import sleep                                                           

#sets GPIO pin numbers#
GPIO4 = 4
GPIO17 = 17
GPIO27 = 27
GPIO22 = 22
GPIO23 = 23
GPIO24 = 24

#sets the initial state of the start button#
Start_state = True

#sets GPIOs to GPIO pin numbers#
GPIO.setmode(GPIO.BCM)

#sets warnings to not show#
GPIO.setwarnings(False)

#sets up GPIOs as outputs#
GPIO.setup(GPIO4, GPIO.OUT)                                                      
GPIO.setup(GPIO17, GPIO.OUT)
GPIO.setup(GPIO27, GPIO.OUT)
GPIO.setup(GPIO22, GPIO.OUT)
GPIO.setup(GPIO23, GPIO.OUT)
GPIO.setup(GPIO24, GPIO.OUT)

#sets initial states of the pins#
GPIO.output(GPIO4, False)                                                                
GPIO.output(GPIO17, False)
GPIO.output(GPIO27, False)
GPIO.output(GPIO22, False)
GPIO.output(GPIO23, False)
GPIO.output(GPIO24, False)

#start of main.loop()#
try:

####sets GUI window####
    master = tk.Tk()

####name of GUI####
    master.title("SOLENOID CONTROL")

####sets size of window (widthxheight)####
    master.geometry  ("650x150")                                                    

####sets initial states of GPIOs to 'off'####
    GPIO4_state = False
    GPIO17_state = False
    GPIO27_state = False
    GPIO22_state = False
    GPIO23_state = False
    GPIO24_state = False                                                          

####defines checkbutton states and relates them to individual GPIOs####
    def GPIO4button():                                                            
        global GPIO4_state
        GPIO4_state = not GPIO4_state

    def GPIO17button():                                                           
        global GPIO17_state
        GPIO17_state = not GPIO17_state

    def GPIO27button():                                                           
        global GPIO27_state
        GPIO27_state = not GPIO27_state

    def GPIO22button():                                                           
        global GPIO22_state
        GPIO22_state = not GPIO22_state

    def GPIO23button():                                                          
        global GPIO23_state
        GPIO23_state = not GPIO23_state

    def GPIO24button():                                                           
        global GPIO24_state
        GPIO24_state = not GPIO24_state

####defines dwell, spray times, and number of repititions (runs) from entry boxes####
    def dwell():
        dwell = e1.get()

    def spray():
        spray = e2.get()

    def runs():
        runs = e3.get()

####defines the start buttons actions####
    def Start():

########gets input from entry boxes to be used in while loop#########
        dwell = int(e1.get())
        print('dwell: ' + str(dwell))
        if e1.get() == 0:
            time.sleep(e1.get())
        else:
            pass

        spray = int(e2.get())
        print('spray: ' + str(spray))
        if e2.get() == 0:
            time.sleep(e2.get())
        else:
            pass

        runs = int(e3.get())
        print('runs: ' + str(runs))
        if e3.get() == 0:
            runs = e3.get()
        else:
            pass

########defines the start buttons state and sets i = 0 for the 'runs' counter########
        global Start_state
        i = 0

########when the button is pushed do:########
        if Start_state == True:
############starts loop for 'runs' counter############
            while i < runs:

################prints states of GPIOs and sets state based on checkbutton input, sets dwell and spray time based on entry box input, runs sequentially################
                print('gpio4: ' + str(GPIO4_state))                
                if GPIO4_state == True:
                    GPIO.output(GPIO4, True)
                    time.sleep(spray)
                    GPIO.output(GPIO4, False)
                    Start_state == False
                    time.sleep(dwell)

                print('gpio17: ' + str(GPIO17_state))                
                if GPIO17_state == True:
                    GPIO.output(GPIO17, True)
                    time.sleep(spray)
                    GPIO.output(GPIO17, False)
                    Start_state == False
                    time.sleep(dwell)

                print('gpio27: ' + str(GPIO27_state))    
                if GPIO27_state == True:
                    GPIO.output(GPIO27, True)
                    time.sleep(spray)
                    GPIO.output(GPIO27, False)
                    Start_state == False
                    time.sleep(dwell)

                print('gpio22: ' + str(GPIO22_state))
                if GPIO22_state == True:
                    GPIO.output(GPIO22, True)
                    time.sleep(spray)
                    GPIO.output(GPIO22, False)
                    Start_state == False
                    time.sleep(dwell)

                print('gpio23: ' + str(GPIO23_state))    
                if GPIO23_state == True:
                    GPIO.output(GPIO23, True)
                    time.sleep(spray)
                    GPIO.output(GPIO23, False)
                    Start_state == False
                    time.sleep(dwell)

                print('gpio24: ' + str(GPIO24_state))    
                if GPIO24_state == True:
                    GPIO.output(GPIO24, True)
                    time.sleep(spray)
                    GPIO.output(GPIO24, False)
                    Start_state == False
                    time.sleep(dwell)
                else:
                    pass

################prints end of run + run number for east debug################
                print('end: ' + str(i))

################adds 1 to the 'runs' to reach entry box value################
                i += 1

############end of while loop############
            else:
                pass

####creates checkbutton and links it to button command####
####positions checkbutton in GUI window####
    checkbutton1 = tk.Checkbutton(master, text="1", command=GPIO4button)
    checkbutton1.grid(row=1, column=1)

    checkbutton2 = tk.Checkbutton(master, text="2", command=GPIO17button)
    checkbutton2.grid(row=1, column=2)

    checkbutton3 = tk.Checkbutton(master, text="3", command=GPIO27button)
    checkbutton3.grid(row=1, column=3)

    checkbutton4 = tk.Checkbutton(master, text="4", command=GPIO22button)
    checkbutton4.grid(row=1, column=4)

    checkbutton5 = tk.Checkbutton(master, text="5", command=GPIO23button)
    checkbutton5.grid(row=1, column=5)

    checkbutton6 = tk.Checkbutton(master, text="6", command=GPIO24button)
    checkbutton6.grid(row=1, column=6)

####labels checkbutton rows####
    tk.Label(master, text="SOLENOIDS").grid(row=1, column=0)

####creates entry boxes and links them to entry variable####
####positions entry boxes in GUI window####
    tk.Label(master, text="DWELL TIME").grid(row=6,column=7)
    e1 = tk.Entry(master)
    e1.grid(row=6, column=8)

    tk.Label(master, text="SPRAY TIME").grid(row=7,column=7)
    e2 = tk.Entry(master)
    e2.grid(row=7, column=8)

    tk.Label(master, text="RUNS").grid(row=8,column=7)
    e3 = tk.Entry(master)
    e3.grid(row=8, column=8)

####creates start, stop, and exit buttons and links them to respective commands####
####starts while loop####
    Startbutton = tk.Button(master, text="START", bg="green", command=Start) 
    Startbutton.grid(row=10, column=7)

####stops current 'run'####
    Stopbutton = tk.Button(master, text="STOP", bg="red", command=Start) 
    Stopbutton.grid(row=10, column=8)

####exits GUI window####
    Exitbutton = tk.Button(master, text="EXIT", bg="red", command=master.destroy)
    Exitbutton.grid(row=10, column=9)

####still no real idea####
    master.mainloop()                                                            

#sets all GPIO back to original 'off' state#
finally:
    GPIO.cleanup()                                                                

Я ожидаю, что смогу нажать кнопку остановки и вернуть GPIO в отключенное состояние, а затем снова нажать кнопку запуска и снова запустить программу в начале.

1 Ответ

0 голосов
/ 03 июля 2019

Если вы запускаете долгосрочную функцию, то вам нужно запустить ее в потоке, но она может не иметь доступа к GUI.

Если вы можете разделить функцию на более мелкие части, вы можете использовать master.after(time, next_part) для запуска следующей части, а затем mainloop() успеет обновить графический интерфейс - т.е. у него есть время для запуска функции, назначенной кнопке STOP - и она не останавливается. master.after() можно использовать вместо sleep().

Или вы можете использовать master.update() во многих местах вашей функции, чтобы обновить GUI - mainloop() успеет запустить функцию, назначенную кнопке STOP. Это не будет нуждаться в нити.

Для завершения программы вы можете использовать логическую переменную (т. Е. if is_running:) во многих местах. Кнопка STOP должна установить is_running = False, и она должна прекратить работу функции на if is_running:.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...