Skip to content

Instantly share code, notes, and snippets.

@MaxBarraclough
Created January 5, 2021 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MaxBarraclough/1d2a17f5683b6449d29ba4ea464ff946 to your computer and use it in GitHub Desktop.
Save MaxBarraclough/1d2a17f5683b6449d29ba4ea464ff946 to your computer and use it in GitHub Desktop.
asciimatics_button_bug_demo.py
#!/usr/bin/env python3
## This simple application demonstrates a bug in
## the mouse-click handling for buttons, in asciimatics:
## mouse-clicks on the right side of buttons, fail to register.
## It seems especially evident in buttons with short label strings.
## Dependency:
## pip install asciimatics
## Loosely based on the quick_model.py example script.
## See also the similar contact_list.py example script (which uses sqlite).
## asciimatics toolkit tutorial:
## https://asciimatics.readthedocs.io/en/stable/widgets.html
from asciimatics.widgets import Frame, ListBox, Layout, Divider, Text, \
Button, TextBox, Widget
from asciimatics.scene import Scene
from asciimatics.screen import Screen
from asciimatics.exceptions import ResizeScreenError, NextScene, StopApplication
from asciimatics.event import KeyboardEvent
import sys
## We don't use a proper model, just a placeholder
class DemoModel(object):
def __init__(self):
pass
class DemoView(Frame):
def __init__(self, screen, model):
super(DemoView, self).__init__(screen,
screen.height * 2 // 3,
screen.width * 2 // 3,
hover_focus=True,
can_scroll=False,
title="Demo Application")
# reduce_cpu=True)
self._model = model ## Placeholder model object
## Create the form
layout = Layout([100], fill_frame=True) # single column occupying 100% of available width
self.add_layout(layout)
layout.add_widget(Button("Overwrite text in text box (1)", self._button1_clicked))
layout.add_widget(Button("Overwrite text in text box (2)", self._button2_clicked))
## Clicking on the right side of this button doesn't work
layout.add_widget(Button("Short one", self._shortButton_clicked))
layout.add_widget(Button("Overwrite text in text box (3)", self._button3_clicked))
layout.add_widget(Button("Overwrite text in text box (4)", self._button4_clicked))
layout.add_widget(Button("Click here to exit", self._quit))
self.text_widget = Text(label="Status", name="status_text", readonly=True)
self.text_widget.value = "[ Ready ]"
layout.add_widget(self.text_widget)
self.fix()
def _button1_clicked(self):
self.text_widget.value = "BUTTON 1 CLICKED"
return
def _button2_clicked(self):
self.text_widget.value = "BUTTON 2 CLICKED"
return
def _shortButton_clicked(self):
self.text_widget.value = "SHORT BUTTON CLICKED"
return
def _button3_clicked(self):
self.text_widget.value = "BUTTON 3 CLICKED"
return
def _button4_clicked(self):
self.text_widget.value = "BUTTON 4 CLICKED"
return
@staticmethod
def _quit():
exit(0)
# raise StopApplication("User pressed quit")
def process_event(self, event):
# Allow standard event processing first
if super(DemoView, self).process_event(event) is None:
return
# If that didn't handle it, check for a key that this demo understands.
if isinstance(event, KeyboardEvent):
c = event.key_code
if c in (ord("q"), ord("Q")):
raise StopApplication("User exit")
else:
# Not a recognised key - pass on to other handlers.
return event
else:
# Ignore other types of events.
return event
the_model = DemoModel()
def demo(screen, scene):
scenes = [
Scene([DemoView(screen, the_model)], -1, name="Demo")
]
screen.play(scenes, stop_on_resize=True, start_scene=scene, allow_int=True)
last_scene = None
while True:
try:
Screen.wrapper(demo, catch_interrupt=True, arguments=[last_scene])
sys.exit(0)
except ResizeScreenError as e:
last_scene = e.scene
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment