micropython-nano-gui/extras/README.md

9.2 KiB

Nano-gui extras

This directory contains additional widgets and demos. Further widgets may be back-ported here from micro-gui.

Demos

These were tested on the Waveshare Pico Res Touch 2.8" display, a 320*240 LCD. Scaling will be required for smaller units. They are found in extras/demos and are run by issuing (for example):

import extras.demos.calendar
  • calendar.py Demonstrates the Calendar widget, which uses the grid widget.

The following demos run on color displays. If an ePaper display is used, partial updates must be supported. Currently these are only supported by the Waveshare 400x300 Pi Pico display.

  • clock_test.py Runs the Clock widget, showing current RTC time.
  • eclock_test.py Runs the EClock widget, showing current RTC time.
  • eclock_async.py Illustrates asynchronous coding with partial updates.

Widgets

These are found in extras/widgets.

Grid

from gui.widgets import Grid  # File: grid.py

Image

This is a rectangular array of Label instances. Rows are of a fixed height equal to the font height + 4 (i.e. the label height). Column widths are specified in pixels with the column width being the specified width +4 to allow for borders. The dimensions of the widget including borders are thus:
height = no. of rows * (font height + 4)
width = sum(column width + 4)
Cells may be addressed as a 1 or 2-dimensional array.

Constructor args:

  1. writer The Writer instance (font and screen) to use.
  2. row Location of grid on screen.
  3. col
  4. lwidth If an integer N is passed all labels will have width of N pixels. A list or tuple of integers will define the widths of successive columns. If the list has fewer entries than there are columns, the last entry will define the width of those columns. Thus [20, 30] will produce a grid with column 0 being 20 pixels and all subsequent columns being 30.
  5. nrows Number of rows.
  6. ncols Number of columns.
  7. invert=False Display in inverted or normal style.
  8. fgcolor=None Color of foreground (the control itself). If None the Writer foreground default is used.
  9. bgcolor=BLACK Background color of cells. If None the Writer background default is used.
  10. bdcolor=None Color of border of the widget and its internal grid. If False no border or grid will be drawn. If None the fgcolor will be used, otherwise a color may be passed.
  11. align=ALIGN_LEFT By default text in labels is left aligned. Options are ALIGN_RIGHT and ALIGN_CENTER. Justification can only occur if there is sufficient space in the Label as defined by lwidth.

Methods:

  • show Draw the grid lines to the framebuffer.
  • __getitem__ Returns an iterator enabling Label instances to be accessed.
  • __setitem__ Assign a value to one or more labels. If multiple labels are specified and a single text value is passed, all labels will receive that value. If an iterator is passed, consecutive labels will receive values from the iterator. If the iterator runs out of data, the last value will be repeated.

Addressing:
The Label instances may be addressed as a 1D array as follows

grid[20] = str(42)
grid[20:25] = iter([str(n) for n in range(20, 25)])

or as a 2D array:

grid[2, 5] = "A"  # Row == 2, col == 5
grid[0:7, 3] = "b"  # Populate col 3 of rows 0..6
grid[1:3, 1:3] = (str(n) for n in range(25))  # Produces
# 0 1
# 2 3

Columns are populated from left to right, rows from top to bottom. Unused iterator values are ignored. If an iterator runs out of data the last value is repeated, thus

grid[1:3, 1:3] = (str(n) for n in range(2))  # Produces
# 0 1
# 1 1

Read access:

for label in grid[2, 0:]:
    v = label.value()  # Access each label in row 2

Sample usage (complete example):

from color_setup import ssd
from gui.core.writer import CWriter
from gui.core.nanogui import refresh
import gui.fonts.font10 as font
from gui.core.colors import *
from extras.widgets.grid import Grid
from gui.widgets.label import ALIGN_CENTER, ALIGN_LEFT

wri = CWriter(ssd, font, verbose=False)
wri.set_clip(True, True, False)  # Clip to screen, no wrap
refresh(ssd, True)  # Clear screen and initialise GUI
colwidth = (40, 25)  # Col 0 width is 40, subsequent columns 25
row, col = 10, 10  # Placement
rows, cols = 6, 8  # Grid dimensions
grid = Grid(wri, row, col, colwidth, rows, cols, align=ALIGN_CENTER)
grid.show()  # Draw grid lines

# Populate grid
grid[1:6, 0] = iter("ABCDE")  # Label row and col headings
grid[0, 1:cols] = (str(x) for x in range(cols))
grid[20] = ""  # Clear cell 20 by setting its value to ""
grid[2, 5] = str(42)  # 2d array syntax
# Dynamic formatting
def txt(text):
    return {"text": text}
redfg = {"fgcolor": RED}
grid[3, 7] = redfg | txt(str(99))  # Specify color as well as text
invla = {"invert": True, "align": ALIGN_LEFT}
grid[2, 1] = invla | txt("x")  # Invert using invert flag
bkongn = {"fgcolor": BLACK, "bgcolor": GREEN, "align": ALIGN_LEFT}  # Invert by swapping bg and fg
grid[3, 1] = bkongn | txt("a")
grid[4,2] = {"fgcolor": BLUE} | txt("go")
refresh(ssd)

Calendar

This builds on the grid to create a calendar. This shows a one month view which may be updated to show any month. The date matching the system's date ("today") may be highlighted. The calendar also has a "current day" which may be highlighted in a different fashion. The current day may be moved at will.

Constructor args:

  • wri The Writer instance (font and screen) to use.
  • row Location of grid on screen.
  • col
  • colwidth Width of grid columns.
  • fgcolor Foreground color (grid lines).
  • bgcolor Background color.
  • today_c Color of text for today.
  • cur_c Color of text for current day.
  • sun_c Color of text for Sundays.
  • today_inv=False Show today's date inverted (good for ePaper/monochrome).
  • cur_inv=False Show current day inverted.

Method:

  • show No args. (Re)draws the control. Primarily for internal use by GUI.

Bound object:

  • date This is a DateCal instance, defined in date.py. It supports the following properties, enabling the calendar's current day to be accessed and changed.

  • year

  • month Range 1 <= month <= 12

  • mday Day in month. Range depends on month and year.

  • day Day since epoch.

Read-only property:

  • wday Day of week. 0 = Monday.

Method:

  • now Set date to system date.

The DateCal class is documented here.

A demo of the Calendar class is extras/demos/calendar.py. Example navigation fragments:

cal = Calendar(wri, 10, 10, 35, GREEN, BLACK, RED, CYAN, BLUE, True)
cal.date.month += 1  # One month forward
cal.date.day += 7  # One week forward
cal.update()  # Update framebuffer
refresh(ssd)  # Redraw screen

Clock

This displays a conentional clock with an optional seconds hand. See extras/demos/clock.py.

Constructor args:

  • writer The Writer instance (font and screen) to use.
  • row Location of clock on screen.
  • col
  • height Dimension in pixels.
  • fgcolor=None Foreground, background and border colors.
  • bgcolor=None
  • bdcolor=RED
  • pointers=(CYAN, CYAN, RED) Colors for hours, mins and secs hands. If pointers[2] = None no second hand will be drawn.
  • label=None If an integer is passed a label of that width will be ceated which will show the current time in digital format.

Methods:

  • value=t Arg t: int is a time value e.g. time.localtime(). Causes clock to be updated and redrawn to the framebuffer.
  • show No args. (Re)draws the clock. Primarily for internal use by GUI.

EClock

This is an unconventional clock display discussed here and here. In summary, it is designed to eliminate the effects of ghosting on ePaper displays. Updating is additive, with white pixels being converted to black, with a full refresh occurring once per hour. It also has the property that time is displayed in the way that we think of it, "ten to seven" rather than 6:50. It can be displayed in full color on suitable displays, which misses the point of the design other than to be different...

See extras/demos/eclock.py.

Constructor args:

  • writer The Writer instance (font and screen) to use.
  • row Location of clock on screen.
  • col
  • height Dimension in pixels.
  • fgcolor=None Foreground, background and border colors.
  • bgcolor=None
  • bdcolor=RED
  • int_colors=None An optional 5-tuple may be passed to define internal colors. In its absence all members will be WHITE (for ePaper use). Tuple members must be color constants and are as follows:
  1. Hour ticks: the ticks around the outer circle.
  2. Arc: the color of the main arc.
  3. Mins ticks: Ticks on the main arc.
  4. Mins arc: color of the elapsed minutes arc.
  5. Pointer: color of the hours chevron.

Methods:

  • value=t Arg t: int is a time value e.g. time.localtime(). Causes clock to be updated and redrawn to the framebuffer.
  • show No args. (Re)draws the clock. Primarily for internal use by GUI.