Squash bugs in Pushbutton and ScaleLog widgets.

pull/8/head
Peter Hinch 2021-07-08 13:18:05 +01:00
rodzic a75eda8e85
commit ccaa1d1797
5 zmienionych plików z 26 dodań i 31 usunięć

Wyświetl plik

@ -1,9 +1,12 @@
# micropython-micro-gui # micropython-micro-gui
This is a lightweight, portable, MicroPython GUI library for displays with This is a lightweight, portable, MicroPython GUI library for displays having
drivers subclassed from `framebuf`. It allows input via pushbuttons or via a drivers subclassed from `framebuf`. Written in Python it runs under a standard
switch joystick. Written in Python it runs under a standard MicroPython MicroPython firmware build. Options for data input comprise
firmware build. * Via from two to five pushbuttons depending on the application.
* Via a switch-based navigation joystick.
* Via two pushbuttons and a rotary encoder such as
[this one](https://www.adafruit.com/product/377).
It is larger and more complex than `nano-gui` owing to the support for input. It is larger and more complex than `nano-gui` owing to the support for input.
It enables switching between screens and launching modal windows. In addition It enables switching between screens and launching modal windows. In addition
@ -19,9 +22,6 @@ to a wide range of displays. It is also portable between hosts.
![Image](./images/ttgo.JPG) TTGO T-Display. Add a joystick switch and an SIL ![Image](./images/ttgo.JPG) TTGO T-Display. Add a joystick switch and an SIL
resistor for a simple, inexpensive, WiFi capable system. resistor for a simple, inexpensive, WiFi capable system.
An alternative interface consists of two pushbuttons and an encoder such as
[this one](https://www.adafruit.com/product/377).
# Rationale # Rationale
Touch GUI's have many advantages, however they have drawbacks, principally cost Touch GUI's have many advantages, however they have drawbacks, principally cost
@ -30,7 +30,7 @@ and the need for calibration (although the
factory calibrated). Another problem is that there are various types of touch factory calibrated). Another problem is that there are various types of touch
controller, magnifying the difficulty of writing a portable GUI. controller, magnifying the difficulty of writing a portable GUI.
Pushbutton input works well and yields astonishingly low cost solutions. A The input options work well and yield astonishingly low cost solutions. A
network-connected board with a 135x240 color display can be built for under £20 network-connected board with a 135x240 color display can be built for under £20
($20?) using the ($20?) using the
[TTGO T-Display](http://www.lilygo.cn/prod_view.aspx?TypeId=50044&Id=1126). The [TTGO T-Display](http://www.lilygo.cn/prod_view.aspx?TypeId=50044&Id=1126). The

Wyświetl plik

@ -539,7 +539,8 @@ class Widget:
self.draw = True # Signals that obect must be redrawn self.draw = True # Signals that obect must be redrawn
self._value = value self._value = value
# Current colors # Set colors. Writer colors cannot be None:
# bg == 0, fg == 1 are ultimate (monochrome) defaults.
if fgcolor is None: if fgcolor is None:
fgcolor = writer.fgcolor fgcolor = writer.fgcolor
if bgcolor is None: if bgcolor is None:

Wyświetl plik

@ -25,9 +25,10 @@ from gui.core.colors import *
class BaseScreen(Screen): class BaseScreen(Screen):
def __init__(self): def __init__(self):
def btncb(btn, reg, low, high): def btncb(btn, reg, low, high): # Button callbck
reg.adjust(low, high) reg.adjust(low, high)
def rats(btn, ts, reg):
def delete_alarm(btn, ts, reg):
ts.del_region(reg) ts.del_region(reg)
super().__init__() super().__init__()
@ -39,7 +40,7 @@ class BaseScreen(Screen):
legends=('0.0', '0.5', '1.0')) legends=('0.0', '0.5', '1.0'))
self.ts = Tstat(wri, row, sl.mcol + 5, divisions = 4, ptcolor=YELLOW, height=100, width=15, self.ts = Tstat(wri, row, sl.mcol + 5, divisions = 4, ptcolor=YELLOW, height=100, width=15,
style=Tstat.BAR, legends=('0.0', '0.5', '1.0')) style=Tstat.BAR, legends=('0.0', '0.5', '1.0'))
reg = Region(self.ts, 0.4, 0.6, MAGENTA, self.ts_cb) reg = Region(self.ts, 0.4, 0.55, MAGENTA, self.ts_cb)
al = Region(self.ts, 0.9, 1.0, RED, self.al_cb) al = Region(self.ts, 0.9, 1.0, RED, self.al_cb)
col = self.ts.mcol + 5 col = self.ts.mcol + 5
self.lbl = Label(wri, row, col, 35, bdcolor=RED, bgcolor=BLACK) self.lbl = Label(wri, row, col, 35, bdcolor=RED, bgcolor=BLACK)
@ -48,14 +49,14 @@ class BaseScreen(Screen):
self.grn = LED(wri, self.led.mrow + 5, col, height=20, color=GREEN, bdcolor=BLACK) self.grn = LED(wri, self.led.mrow + 5, col, height=20, color=GREEN, bdcolor=BLACK)
col = self.lbl.mcol + 5 col = self.lbl.mcol + 5
btn = Button(wri, row + 30, col, width=0, btn = Button(wri, row + 30, col, width=0,
text='down', litcolor=RED, bgcolor=DARKGREEN, text='down', litcolor=RED,
callback=btncb, args=(reg, 0.2, 0.3)) callback=btncb, args=(reg, 0.2, 0.3))
btn1 = Button(wri, btn.mrow + 5, col, width=btn.width, btn1 = Button(wri, btn.mrow + 5, col, width=btn.width,
text='up', litcolor=RED, bgcolor=DARKGREEN, text='up', litcolor=RED,
callback=btncb, args=(reg, 0.5, 0.6)) callback=btncb, args=(reg, 0.5, 0.6))
Button(wri, btn1.mrow + 5, col, width=btn.width, Button(wri, btn1.mrow + 5, col, width=btn.width,
text='del', litcolor=RED, bgcolor=DARKGREEN, text='del', litcolor=RED,
callback=rats, args=(self.ts, al)) callback=delete_alarm, args=(self.ts, al))
CloseButton(wri) CloseButton(wri)
def after_open(self): def after_open(self):

Wyświetl plik

@ -25,18 +25,14 @@ class Button(Widget):
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, False, True) super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, False, True)
self.shape = shape self.shape = shape
self.radius = height // 2 self.radius = height // 2
self.fill = bgcolor is not None # Draw background if color specified
self.litcolor = litcolor self.litcolor = litcolor
self.textcolor = self.fgcolor if textcolor is None else textcolor self.textcolor = self.fgcolor if textcolor is None else textcolor
self.orig_fgcolor = self.fgcolor
self.orig_bgcolor = self.bgcolor
self.text = text self.text = text
self.callback = callback self.callback = callback
self.callback_args = args self.callback_args = args
self.onrelease = onrelease self.onrelease = onrelease
if self.litcolor is not None: if self.litcolor is not None:
self.delay = Delay_ms(self.shownormal) self.delay = Delay_ms(self.shownormal)
self.litcolor = litcolor if self.fgcolor is not None else None
def show(self): def show(self):
if self.screen is not Screen.current_screen: if self.screen is not Screen.current_screen:
@ -53,8 +49,7 @@ class Button(Widget):
if self.shape == CIRCLE: # Button coords are of top left corner of bounding box if self.shape == CIRCLE: # Button coords are of top left corner of bounding box
x += self.radius x += self.radius
y += self.radius y += self.radius
if self.fill: display.fillcircle(x, y, self.radius, self.bgcolor)
display.fillcircle(x, y, self.radius, self.bgcolor)
display.circle(x, y, self.radius, self.fgcolor) display.circle(x, y, self.radius, self.fgcolor)
if len(self.text): if len(self.text):
display.print_centred(self.writer, x, y, self.text, self.textcolor, self.bgcolor) display.print_centred(self.writer, x, y, self.text, self.textcolor, self.bgcolor)
@ -62,14 +57,12 @@ class Button(Widget):
xc = x + w // 2 xc = x + w // 2
yc = y + h // 2 yc = y + h // 2
if self.shape == RECTANGLE: # rectangle if self.shape == RECTANGLE: # rectangle
if self.fill: display.fill_rect(x, y, w, h, self.bgcolor)
display.fill_rect(x, y, w, h, self.bgcolor)
display.rect(x, y, w, h, self.fgcolor) display.rect(x, y, w, h, self.fgcolor)
if len(self.text): if len(self.text):
display.print_centred(self.writer, xc, yc, self.text, self.textcolor, self.bgcolor) display.print_centred(self.writer, xc, yc, self.text, self.textcolor, self.bgcolor)
elif self.shape == CLIPPED_RECT: # clipped rectangle elif self.shape == CLIPPED_RECT: # clipped rectangle
if self.fill: display.fill_clip_rect(x, y, w, h, self.bgcolor)
display.fill_clip_rect(x, y, w, h, self.bgcolor)
display.clip_rect(x, y, w, h, self.fgcolor) display.clip_rect(x, y, w, h, self.fgcolor)
if len(self.text): if len(self.text):
display.print_centred(self.writer, xc, yc, self.text, self.textcolor, self.bgcolor) display.print_centred(self.writer, xc, yc, self.text, self.textcolor, self.bgcolor)
@ -80,7 +73,7 @@ class Button(Widget):
# control caused a screen change while timer running. # control caused a screen change while timer running.
while self.screen is not Screen.current_screen: while self.screen is not Screen.current_screen:
await asyncio.sleep_ms(500) await asyncio.sleep_ms(500)
self.bgcolor = self.orig_bgcolor self.bgcolor = self.def_bgcolor
self.draw = True # Redisplay self.draw = True # Redisplay
def do_sel(self): # Select was pushed def do_sel(self): # Select was pushed
@ -186,7 +179,7 @@ class RadioButtons:
self.lstbuttons.append(button) self.lstbuttons.append(button)
button.callback = self._callback button.callback = self._callback
active = len(self.lstbuttons) == self.selected + 1 active = len(self.lstbuttons) == self.selected + 1
button.bgcolor = self.highlight if active else button.orig_bgcolor button.bgcolor = self.highlight if active else button.def_bgcolor
if active: if active:
self.current = button self.current = button
return button return button
@ -209,6 +202,6 @@ class RadioButtons:
but.bgcolor = self.highlight but.bgcolor = self.highlight
self.current = button self.current = button
else: else:
but.bgcolor = but.orig_bgcolor but.bgcolor = but.def_bgcolor
but.draw = True but.draw = True
self.user_callback(button, *args) # user gets button with args they specified self.user_callback(button, *args) # user gets button with args they specified

Wyświetl plik

@ -147,8 +147,8 @@ class ScaleLog(LinearIO):
if isinstance(button, int): # Using an encoder if isinstance(button, int): # Using an encoder
delta = self.delta * self.encoder_rate * 0.1 if self.precision else self.delta * self.encoder_rate delta = self.delta * self.encoder_rate * 0.1 if self.precision else self.delta * self.encoder_rate
self.value(self.value() * (1 + delta)**val) self.value(self.value() * (1 + delta)**val)
else: else: # val == 1 or -1
asyncio.create_task(self.btnhan(button, val, d)) asyncio.create_task(self.btnhan(button, val))
async def btnhan(self, button, up): async def btnhan(self, button, up):
up = up == 1 up = up == 1