Как обрабатывать неожиданное нажатие клавиши

#python #tkinter #event-handling

#python #tkinter #обработка событий

Вопрос:

Я разработал приложение, в котором есть две кнопки, то есть CALи .SAV Соответственно, у меня есть две функции, но проблема иногда в том, что оператор производственной линии по ошибке нажимает SAVкнопку. Таким образом, возникает ошибка атрибута и программа застревает.

Как преодолеть эту проблему? Пожалуйста, направьте меня.

Вот мой код:

 class ADS1x15:
    """Base functionality for ADS1x15 analog to digital converters."""

class ADS1115(ADS1x15):
    """Class for the ADS1115 16 bit ADC."""

class AnalogIn:
    """AnalogIn Mock Implementation for ADC Reads."""

import RPi.GPIO as GPIO
import tkinter as tk

GPIO.setmode(GPIO.BCM)
GPIO.setup(12,GPIO.IN)  #Save Button
GPIO.setup(5,GPIO.IN)  #Cal  Button

root=tk.Tk()
root.geometry("1000x600")

file = open("/home/pi/data_log.txt", "r")
   f = file.read().split(',')
   rangeh = int(f[3])
   offset = int(f[4])
   fullScale = int(f[5])

chan=AnalogIn(ads,P0,P1)

def cal(channel):
       global Dsel,cal_c,rangeh,offset,fullScale,chan
       cal_c = cal_c   1

       if cal_c == 1:
          root.L1 = tk.Label(root,text="Put Zero Weight and Press CAL btn",fg="brown",font="bold")
          root.L1.pack()
          root.L1.place(x=1,y=1)
       elif cal_c == 2:
          root.L1.destroy()
          offset = chan.value
          file = open("/home/pi/data_log.txt", "w")
          if os.stat("/home/pi/data_log.txt").st_size == 0:
             file.write("rangeh,offset,Full_Scale,n")

          file.write(str(rangeh) "," str(offset) "," str(fullScale))
          file.flush()

          root.L2 = tk.Label(root,text="Put Full Weight and Press SAV btn",fg="brown",font="bold")
          root.L2.pack()
          root.L2.place(x=1,y=1)

       


   def sav(channel):
       global rangeh,offset,fullScale
       file = open("/home/pi/data_log.txt", "w")
       if os.stat("/home/pi/data_log.txt").st_size == 0:
          file.write("rangeh,offset,Full_Scale,n")

       file.write(str(rangeh) "," str(offset) "," str(fullScale))
       file.flush() 
       
       root.L2.destroy()

def update():
  """ function for continuous show value in every 500ms in tkinter window""" 

GPIO.add_event_detect(5,GPIO.RISING,callback=cal,bouncetime=1000)
GPIO.add_event_detect(12,GPIO.RISING,callback=sav,bouncetime=1000)

root.after(500,update)
root.mainloop()

  

Эта ошибка возникла из-за root.L2.destroy() этой строки.

Могу ли я заблокировать или отключить эту sav функцию, чтобы без вызова cal функции она не выполнялась?

Комментарии:

1. @acw1668, это не кнопка tkinter . Это физическая кнопка, связанная с функцией обратного вызова. Могу ли я сделать то же самое для физической кнопки?

2. Тогда вы должны выполнять требуемую работу только cal_c == 2 внутри sav() .

Ответ №1:

Решением грубой силы было бы проверить, имеет ли root атрибут L2 или нет

 from tkinter import messagebox    
def sav(channel):
    if hasattr(root, 'L2'):
        global rangeh, offset, fullScale
        file = open("/home/pi/data_log.txt", "w")
        if os.stat("/home/pi/data_log.txt").st_size == 0:
            file.write("rangeh,offset,Full_Scale,n")
        file.write(str(rangeh)   ","   str(offset)   ","   str(fullScale))
        file.flush()

        root.L2.destroy()
    else:
        messagebox.showinfo('Unable to save', 'No data was generated yet')
  

Более элегантным подходом было бы отключить кнопку сохранения при запуске и включить ее только после выполнения функции cal.

Я не очень хорошо знаком с реализациями Raspberry Pi, так что это лишь приблизительный набросок того, как добиться отключения кнопки: судя по всему, кнопки «подключены» через функции GPIO.add_event_detect.

Поэтому я бы удалил sav-обратный вызов из основного скрипта и динамически добавил его после cal-скрипта, что-то вроде этого:

 # [...] beginning of your script [...]
def cal(channel):
    # [...] original body of cal function [...]
    activate_save_button()

def activate_save_button():
    GPIO.add_event_detect(12, GPIO.RISING, callback=sav, bouncetime=1000)
    
def deactivate_save_button():
    GPIO.remove_event_detect(12)

def sav(channel):
    # [...] original body of sav function [...]
    # remove save button functionality after saving
    deactivate_save_button()

def update():
    """ function for continuous show value in every 500ms in tkinter window"""


GPIO.add_event_detect(5, GPIO.RISING, callback=cal, bouncetime=1000)
# line with callback=sav is deleted here

root.after(500, update)
root.mainloop()
  

Комментарии:

1. На самом деле я хочу отключить кнопку сохранения при запуске и включить ее только после выполнения функции cal. Но я совсем новичок в python, поэтому немного путаю, как использовать логику. Не могли бы вы дать мне демонстрацию

2. отредактировал мой ответ с предложением о деактивации кнопки

3. Но проблема с этим «элегантным» подходом заключается в том, что при нажатии кнопки sav перед кнопкой cal ничего не произойдет, что может сбить с толку оператора. так что, возможно, в этом случае лучше использовать метод грубой силы, чтобы иметь некоторую «обратную связь с кнопкой», даже когда вы нажимаете «неправильную».

4. Большое вам спасибо за вашу ценную поддержку.