kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
Add aclock, dropdown and primitives demos.
rodzic
0d74bd317f
commit
3b26ab9528
64
README.md
64
README.md
|
@ -396,15 +396,19 @@ Demos are run by issuing (for example):
|
|||
These will run on screens of 128x128 pixels or above. The initial ones are
|
||||
minimal and aim to demonstrate a single technique.
|
||||
* `simple.py` Minimal demo discussed below. `Button` presses print to REPL.
|
||||
* `checkbox` A `Checkbox` controlling an `LED`.
|
||||
* `checkbox.py` A `Checkbox` controlling an `LED`.
|
||||
* `slider.py` A `Slider` whose color varies with its value.
|
||||
* `slider_label.py` A `Slider` updating a `Label`. Good for trying precision
|
||||
mode.
|
||||
* `linked_slider.py` One `Slider` updating two others, and a coding "wrinkle"
|
||||
* `linked_sliders.py` One `Slider` updating two others, and a coding "wrinkle"
|
||||
required for doing this.
|
||||
* `dropdown.py` A dropdown list updates a `Label`.
|
||||
* `dialog.py` `DialogBox` demo. Illustrates the screen change mechanism.
|
||||
* `screen_change.py` A `Pushbutton` causing a screen change using a re-usable
|
||||
"forward" button.
|
||||
* `primitives.py` Use of graphics primitives.
|
||||
* `aclock.py` An analog clock using the `Dial` vector display. Also shows
|
||||
screen layout using widget metrics. Has a simple `uasyncio` task.
|
||||
* `tbox.py` Text boxes and user-controlled scrolling.
|
||||
|
||||
### 1.11.2 Test scripts
|
||||
|
@ -766,17 +770,21 @@ Constructor args:
|
|||
|
||||
The constructor displays the string at the required location.
|
||||
|
||||
Methods:
|
||||
1. `value` Redraws the label. This takes the following args:
|
||||
* `text=None` The text to display. If `None` displays last value.
|
||||
* ` invert=False` If true, show inverse text.
|
||||
* `fgcolor=None` Foreground color: if `None` the `Writer` default is used.
|
||||
* `bgcolor=None` Background color, as per foreground.
|
||||
* `bdcolor=None` Border color. As per above except that if `False` is
|
||||
passed, no border is displayed. This clears a previously drawn border.
|
||||
Returns the current text string.
|
||||
Method:
|
||||
`value` Redraws the label. This takes the following args:
|
||||
* `text=None` The text to display. If `None` displays last value.
|
||||
* `invert=False` If true, show inverse text.
|
||||
* `fgcolor=None` Foreground color: if `None` the `Writer` default is used.
|
||||
* `bgcolor=None` Background color, as per foreground.
|
||||
* `bdcolor=None` Border color. As per above except that if `False` is
|
||||
passed, no border is displayed. This clears a previously drawn border.
|
||||
Returns the current text string.
|
||||
|
||||
If populating a label would cause it to extend beyond the screen boundary a
|
||||
If the `value` method is called with a text string too long for the `Label` a
|
||||
`ValueError` will be thrown. The width specified to the constructor should be
|
||||
sufficient for all possible values.
|
||||
|
||||
If constructing a label would cause it to extend beyond the screen boundary a
|
||||
warning is printed at the console. The label may appear at an unexpected place.
|
||||
The following is a complete "Hello world" script.
|
||||
```python
|
||||
|
@ -1368,6 +1376,11 @@ Methods:
|
|||
* `bdcolor=None` Border color. As per above except that if `False` is
|
||||
passed, no border is displayed. This clears a previously drawn border.
|
||||
|
||||
### Legends
|
||||
|
||||
Depending on the font in use for legends additional space may be required above
|
||||
and below the `Meter` to display the top and bottom legends.
|
||||
|
||||
###### [Contents](./README.md#0-contents)
|
||||
|
||||
# 17. Slider and HorizSlider widgets
|
||||
|
@ -1441,6 +1454,11 @@ user supplied args. The callback can be a bound method, typically of a `Screen`
|
|||
subclass. The callback runs when the widget is instantiated and whenever the
|
||||
value changes. This enables dynamic color change. See `gui/demos/active.py`.
|
||||
|
||||
### Legends
|
||||
|
||||
Depending on the font in use for legends additional space may be required
|
||||
around sliders to display all legends.
|
||||
|
||||
###### [Contents](./README.md#0-contents)
|
||||
|
||||
# 18. Scale widget
|
||||
|
@ -2173,8 +2191,30 @@ The apparently obvious solution of designing a vertical `Scale` is tricky owing
|
|||
to the fact that the length of the internal text can be substantial and
|
||||
variable.
|
||||
|
||||
## Screen layout
|
||||
|
||||
Widgets are positioned using absolute `row` and `col` coordinates. These may
|
||||
optionally be calculated using the metrics of other widgets. This facilitates
|
||||
relative positioning which can make layouts easier to modify. Such layouts can
|
||||
also automatically adapt to changes of fonts. To simplify this, all widgets
|
||||
have the following bound variables, which should be considered read-only:
|
||||
|
||||
* `height` As specified. Does not include border.
|
||||
* `width` Ditto.
|
||||
* `rows` Height including borders.
|
||||
* `cols` Width with borders.
|
||||
|
||||
This support is fairly "micro" and does not take account of labels and legends.
|
||||
This means that `rows` and `cols` for `Dial`, `Meter`, `Slider` and
|
||||
`HorizSlider` do not necessarily reflect the full amount of space used by the
|
||||
control.
|
||||
|
||||
The `aclock.py` demo provides a simple example of this approach.
|
||||
|
||||
## Use of graphics primitives
|
||||
|
||||
See [demo primitives.py](./gui/demos/primitives.py).
|
||||
|
||||
These notes are for those wishing to draw directly to the `Screen` instance.
|
||||
This is done by providing the user `Screen` class with an `after_open()` method
|
||||
which is written to issue the display driver calls.
|
||||
|
|
|
@ -550,6 +550,8 @@ class Widget:
|
|||
self.col = col
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.rows = height + 4 # For metrics. Default: allow for border.
|
||||
self.cols = width + 4
|
||||
self.visible = True # Used by ButtonList class for invisible buttons
|
||||
self.draw = True # Signals that obect must be redrawn
|
||||
self._value = value
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
# aclock.py micro-gui analog clock demo.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# Initialise hardware and framebuf before importing modules.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, ssd
|
||||
from gui.widgets.label import Label
|
||||
from gui.widgets.dial import Dial, Pointer
|
||||
from gui.widgets.buttons import CloseButton
|
||||
|
||||
# Now import other modules
|
||||
from cmath import rect, pi
|
||||
import uasyncio as asyncio
|
||||
import time
|
||||
from gui.core.writer import CWriter
|
||||
|
||||
# Font for CWriter
|
||||
import gui.fonts.arial10 as font
|
||||
from gui.core.colors import *
|
||||
|
||||
|
||||
# Adjust passed Dial and Label instances to show current time and date.
|
||||
async def aclock(dial, lbldate, lbltim):
|
||||
# Return a unit vector of phase phi. Multiplying by this will
|
||||
# rotate a vector anticlockwise which is mathematically correct.
|
||||
# Alas clocks modelled on sundials were invented in the northern
|
||||
# hemisphere. Otherwise they would have rotated widdershins
|
||||
# in accordance with maths. Hence negative sign when called.
|
||||
def uv(phi):
|
||||
return rect(1, phi)
|
||||
|
||||
def suffix(n):
|
||||
if n in (1, 21, 31):
|
||||
return 'st'
|
||||
if n in (2, 22):
|
||||
return 'nd'
|
||||
if n in (3, 23):
|
||||
return 'rd'
|
||||
return th
|
||||
|
||||
days = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
|
||||
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
|
||||
'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
|
||||
|
||||
hrs = Pointer(dial)
|
||||
mins = Pointer(dial)
|
||||
secs = Pointer(dial)
|
||||
|
||||
hstart = 0 + 0.7j # Pointer lengths. Will rotate relative to top.
|
||||
mstart = 0 + 1j
|
||||
sstart = 0 + 1j
|
||||
|
||||
while True:
|
||||
t = time.localtime()
|
||||
hrs.value(hstart * uv(-t[3] * pi/6 - t[4] * pi / 360), CYAN)
|
||||
mins.value(mstart * uv(-t[4] * pi/30), CYAN)
|
||||
secs.value(sstart * uv(-t[5] * pi/30), RED)
|
||||
lbltim.value('{:02d}.{:02d}.{:02d}'.format(t[3], t[4], t[5]))
|
||||
lbldate.value('{} {}{} {} {}'.format(days[t[6]], t[2], suffix(t[2]), months[t[1] - 1], t[0]))
|
||||
await asyncio.sleep(1)
|
||||
|
||||
class BaseScreen(Screen):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
labels = {'bdcolor' : RED,
|
||||
'fgcolor' : WHITE,
|
||||
'bgcolor' : DARKGREEN,
|
||||
}
|
||||
|
||||
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
|
||||
gap = 4 # Vertical gap between widgets
|
||||
dial = Dial(wri, 2, 2, height = 70, ticks = 12,
|
||||
fgcolor = GREEN, pip = GREEN)
|
||||
# Set up clock display: instantiate labels
|
||||
row = dial.rows + gap
|
||||
lbldate = Label(wri, row, 2, 100, **labels)
|
||||
row += lbldate.rows + gap
|
||||
lbltim = Label(wri, row, 2, '00.00.00', **labels)
|
||||
self.reg_task(aclock(dial, lbldate, lbltim))
|
||||
CloseButton(wri)
|
||||
|
||||
|
||||
def test():
|
||||
print('Analog clock demo.')
|
||||
Screen.change(BaseScreen)
|
||||
|
||||
test()
|
|
@ -1,5 +1,8 @@
|
|||
# active.py micro-gui demo of widgets that respond to user control
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# Create SSD instance. Must be done first because of RAM use.
|
||||
import hardware_setup
|
||||
from gui.core.ugui import Screen, ssd
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# checkbox.py Minimal micro-gui demo showing a Checkbox updating an LED.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, ssd
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# dialog.py micro-gui demo of the DialogBox class
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, Window, ssd
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# dropdown.py micro-gui demo of Dropdown class
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, Window, ssd
|
||||
|
||||
from gui.widgets.label import Label
|
||||
from gui.widgets.buttons import CloseButton
|
||||
from gui.widgets.dropdown import Dropdown
|
||||
from gui.core.writer import CWriter
|
||||
|
||||
# Font for CWriter
|
||||
import gui.fonts.font10 as font
|
||||
from gui.core.colors import *
|
||||
|
||||
|
||||
class BaseScreen(Screen):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
super().__init__()
|
||||
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
|
||||
|
||||
col = 2
|
||||
row = 2
|
||||
Dropdown(wri, row, col,
|
||||
elements = ('hydrogen', 'helium', 'neon', 'xenon', 'radon'),
|
||||
bdcolor = GREEN, bgcolor = DARKGREEN,
|
||||
callback=self.ddcb)
|
||||
row += 30
|
||||
self.lbl = Label(wri, row, col, 90, bdcolor=RED)
|
||||
CloseButton(wri) # Quit the application
|
||||
|
||||
def ddcb(self, dd):
|
||||
if hasattr(self, 'lbl'):
|
||||
self.lbl.value(dd.textvalue())
|
||||
|
||||
def test():
|
||||
print('Dropdown demo.')
|
||||
Screen.change(BaseScreen)
|
||||
|
||||
test()
|
|
@ -1,5 +1,8 @@
|
|||
# linked_sliders.py Minimal micro-gui demo one Slider controlling two others.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, ssd
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# primitives.py micro-gui demo of use of graphics primitives
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, Window, ssd, display
|
||||
|
||||
from gui.widgets.label import Label
|
||||
from gui.widgets.buttons import CloseButton
|
||||
from gui.core.writer import CWriter
|
||||
|
||||
# Font for CWriter
|
||||
import gui.fonts.font10 as font
|
||||
from gui.core.colors import *
|
||||
|
||||
|
||||
class BaseScreen(Screen):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
super().__init__()
|
||||
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
|
||||
|
||||
col = 2
|
||||
row = 2
|
||||
Label(wri, row, col, 'Primitives')
|
||||
CloseButton(wri) # Quit the application
|
||||
|
||||
|
||||
def after_open(self):
|
||||
display.usegrey(False)
|
||||
# Coordinates are x, y as per framebuf
|
||||
# circle method is in Display class only
|
||||
display.circle(70, 70, 30, RED, 2)
|
||||
# These methods exist in framebuf, so also in SSD and Display
|
||||
ssd.hline(0, 127, 128, BLUE)
|
||||
ssd.vline(127, 0, 128, BLUE)
|
||||
|
||||
def test():
|
||||
print('Primitives demo.')
|
||||
Screen.change(BaseScreen)
|
||||
|
||||
test()
|
|
@ -1,5 +1,8 @@
|
|||
# screen_change.py Minimal micro-gui demo showing a Button causing a screen change.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, ssd
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# screens.py micro-gui demo of multiple screens, dropdowns etc
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, Window, ssd
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# simple.py Minimal micro-gui demo.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, ssd
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# slider.py Minimal micro-gui demo showing a Slider with variable color.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup
|
||||
from gui.core.ugui import Screen, ssd
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# slider_label.py Minimal micro-gui demo showing a Slider controlling a Label.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# hardware_setup must be imported before other modules because of RAM use.
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, ssd
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# various.py micro-gui demo of multiple controls on a large display
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2021 Peter Hinch
|
||||
|
||||
# Initialise hardware and framebuf before importing modules.
|
||||
# Create SSD instance. Must be done first because of RAM use.
|
||||
import hardware_setup
|
||||
|
|
|
@ -56,7 +56,7 @@ async def ptr_test(dial):
|
|||
ptr.value(v, RED)
|
||||
await asyncio.sleep_ms(200)
|
||||
|
||||
# Analog clock demo. Note this could also be achieved using the Dial class.
|
||||
# Analog clock demo.
|
||||
async def aclock(dial, lbldate, lbltim):
|
||||
uv = lambda phi : rect(1, phi) # Return a unit vector of phase phi
|
||||
days = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
|
||||
|
|
|
@ -11,7 +11,8 @@ class Checkbox(Widget):
|
|||
def __init__(self, writer, row, col, *, height=30, fillcolor=None,
|
||||
fgcolor=None, bgcolor=None, bdcolor=False,
|
||||
callback=dolittle, args=[], value=False, active=True):
|
||||
super().__init__(writer, row, col, height, height, fgcolor, bgcolor, bdcolor, value, active)
|
||||
super().__init__(writer, row, col, height, height, fgcolor,
|
||||
bgcolor, bdcolor, value, active)
|
||||
super()._set_callbacks(callback, args)
|
||||
self.fillcolor = fillcolor
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ class Dial(Widget):
|
|||
self.pip = self.fgcolor if pip is None else pip
|
||||
if label is not None:
|
||||
self.label = Label(writer, row + height + 3, col, label)
|
||||
#self.cols = max(self.cols, self.label.cols)
|
||||
#self.rows += 3 + self.label.rows
|
||||
radius = int(height / 2)
|
||||
self.radius = radius
|
||||
self.ticks = ticks
|
||||
|
|
|
@ -23,13 +23,13 @@ class Meter(Widget):
|
|||
Label(writer, row + height + writer.height // 2, col, label)
|
||||
self.style = style
|
||||
self.ptcolor = ptcolor if ptcolor is not None else self.fgcolor
|
||||
if legends is not None: # Legends
|
||||
if legends is not None: # Legends are static
|
||||
x = col + width + 4
|
||||
y = row + height
|
||||
dy = 0 if len(legends) <= 1 else height / (len(legends) -1)
|
||||
yl = y - writer.height / 2 # Start at bottom
|
||||
for legend in legends:
|
||||
Label(writer, int(yl), x, legend)
|
||||
l = Label(writer, round(yl), x, legend)
|
||||
yl -= dy
|
||||
self.value(value)
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ class Slider(LinearIO):
|
|||
display.rect(self.slot_x0, self.slot_y0, slot_w, slot_len, self.fgcolor)
|
||||
|
||||
txtcolor = GREY if self.greyed_out() else self.fontcolor
|
||||
# Dynamic processing of legends supports greying-out
|
||||
if self.legends is not None:
|
||||
if len(self.legends) <= 1:
|
||||
dy = 0
|
||||
|
|
Ładowanie…
Reference in New Issue