Home > Blockchain >  tkinter executes one more time the function after using after_cancel()
tkinter executes one more time the function after using after_cancel()

Time:05-16

So I have a button that in a cyle way execute a function as soon as the buttom is pressed down. Once released the function stops its execution.

Now, for some reason, once I released the button, the function is executed one more time.

Below you can find the code I'm uing to create the button

self.sch_minus_button = tk.Button(self, text="S-", command=lambda: self.button_hold_callback('sch_minus'))
self.sch_minus_button.bind('<Button-1>', lambda event: self.button_hold_callback('sch_minus', event))
self.sch_minus_button.bind('<ButtonRelease-1>', self.button_stop_callback)

The button_hold_callback is the function that manages the function that must cycle as soon as I've the button pressed

def button_hold_callback(self, *args):
    global repeat
    global last_call

    try:
        repeat = self.after(250, self.button_hold_callback, args[0], args[1])
    except IndexError:
        pass

    self.ser.reset_input_buffer()
    self.ser.reset_output_buffer()
    if not last_call:
        self.ser.write(self.message_to_send(args[0]))
        logging.info('Sent message '   str(self.message_to_send(args[0])))
    # logging.info("write on serial")
    self.ser.reset_input_buffer()
    self.ser.reset_output_buffer()

button_stop_callback instead block the cycle as soon as the button is released

def button_stop_callback(self, event):
    last_call = True
    for x in range(0,10):
        self.ser.write(b'\x02\x56\xff\xff\xff\xff\xff\xff\x32\x35\x04')
        time.sleep(0.01)
    logging.debug("Written stop on the serial")
    self.after_cancel(repeat)

For some reason, even the button_stop_callback function is executed correctly, it seems that button_hold_callback is executed one more time.

I found out this strange behavior with the logging as, as soon as I release the button I have another log that tells me anothe packet has been sent on the serial

2022-05-13 11:19:23,956 - root - INFO - created serial port (GUI.py:43)
2022-05-13 11:19:25,107 - root - INFO - Sent message b'\x02V\x81\x80\x80\x80\x80\x8095\x04' (GUI.py:84)
2022-05-13 11:19:25,373 - root - INFO - Sent message b'\x02V\x81\x80\x80\x80\x80\x8095\x04' (GUI.py:84)
2022-05-13 11:19:25,623 - root - INFO - Sent message b'\x02V\x81\x80\x80\x80\x80\x8095\x04' (GUI.py:84)
2022-05-13 11:19:25,888 - root - INFO - Sent message b'\x02V\x81\x80\x80\x80\x80\x8095\x04' (GUI.py:84)
2022-05-13 11:19:26,136 - root - DEBUG - Written stop on the serial (GUI.py:67)
2022-05-13 11:19:26,136 - root - INFO - Sent message b'\x02V\x81\x80\x80\x80\x80\x8095\x04' (GUI.py:84)

I've entered the code in debug mode and for some reason, everything works smooth if I breakpoint every step of my code. In production it has the issue stated below

Any idea?

CodePudding user response:

So, I've found out a sort of workaround killing the serial once the release button callback is called and opening again with a try except once the function button_hold_callback is called for the last time

def button_stop_callback(self, event):
    self.ser.reset_output_buffer()
    self.ser.write(b'\x02\x56\xff\xff\xff\xff\xff\xff\x32\x35\x04')
    logging.debug("Written stop on the serial")
    self.ser.close()
    self.after_cancel(repeat)

# ---- CALLBACK MANTIENE L'ESECUZIONE DELLA FUNZIONE CON TASTO PREMUTO
def button_hold_callback(self, *args):
    global repeat

    try:
        repeat = self.after(250, self.button_hold_callback, args[0], args[1])
    except IndexError:
        pass

    try:
        self.ser.reset_input_buffer()
        self.ser.reset_output_buffer()

        self.ser.write(self.message_to_send(args[0]))
        logging.info('Sent message '   str(self.message_to_send(args[0])))

        # logging.info("write on serial")
        self.ser.reset_input_buffer()
        self.ser.reset_output_buffer()
    # ---- SE FALLISCE PORTA SERIALE CHIUSA
    except:
        self.ser.open()
  • Related