This is really useful when building hardware projects and you want 1 button to do 2 things, say turn something on when pressed, and turn off when held down.
I needed this for a project so I thought I would create a new HoldableButton class using gpiozero. Hopefully this will be incorporated into gpiozero, but until then you can use the class below.
The code is also available here as a gist.
You will need to add the HoldableButton class to your Python program:
from gpiozero import Button from threading import Timer class HoldableButton(Button): def __init__(self, pin=None, pull_up=True, bounce_time=None, hold_time=1, repeat=False): super(HoldableButton, self).__init__(pin, pull_up, bounce_time) # Set Button when_pressed and when_released to call local functions # cant use super() as it doesn't support setters Button.when_pressed.fset(self, self._when_button_pressed) Button.when_released.fset(self, self._when_button_released) self._when_held = None self._when_pressed = None self._when_released = None self._is_held = False self.hold_time = hold_time self.repeat = repeat self._held_timer = None #override button when_pressed and when_released @property def when_pressed(self): return self._when_pressed @when_pressed.setter def when_pressed(self, value): self._when_pressed = value @property def when_released(self): return self._when_released @when_released.setter def when_released(self, value): self._when_released = value @property def when_held(self): return self._when_held @when_held.setter def when_held(self, value): self._when_held = value @property def is_held(self): return self._is_held def _when_button_pressed(self): self._start_hold() if self._when_pressed != None: self._when_pressed() def _when_button_released(self): self._is_held = False self._stop_hold() if self._when_released != None: self.when_released() def _start_hold(self): self._held_timer = Timer(self.hold_time, self._button_held) self._held_timer.start() def _stop_hold(self): if self._held_timer != None: self._held_timer.cancel() def _button_held(self): self._is_held = True if self._when_held != None: if self.repeat and self.is_pressed: self._start_hold() self._when_held()Using the HoldableButton class is pretty simple, similar to the gpiozero Button class and can be swapped for the Button class with no other changes.
holdbutton = HoldableButton(pin, hold_time = 1, repeat = False)You have to pass a pin number and optional hold_time and repeat values:
- hold_time - is the number of seconds after the button is pressed before the button is consider 'held'
- repeat - is a boolean and if set to True will occur 'button held' events to be repeated after each hold_time
There are 2 additional properties is_held, which will return a boolean stating whether the button has been held down for the 'hold_time' and when_held which when assigned a function will cause the function to be called when the button is held down.
def myheldfunction(): print("button held") holdbutton.when_held = myheldfunctionNow when a button is held down, the function will be called and "button held" printed.