README improvements. Tidy up demo code.

pull/8/head
Peter Hinch 2021-06-12 11:59:12 +01:00
rodzic 8001e16aa0
commit a5508d14b6
7 zmienionych plików z 212 dodań i 105 usunięć

280
README.md
Wyświetl plik

@ -17,13 +17,37 @@ to a wide range of displays. It is also portable between hosts.
# Project status # Project status
Code has been tested on ESP32 and Pi Pico. It is new and bugs are likely. This Code has been tested on ESP32 and Pi Pico. The API shuld be stable. I'm not
document is also incomplete and under review. aware of any bugs but code is new and issues are likely. This document is
likely to have errors, typos and omissions. It is under review.
# 0. Contents # 0. Contents
**TODO** **TODO** Add sub-headings
1. [Basic concepts](./README.md#1-basic-concepts) Including installation and test.
2. [Usage](./README.md#2-usage) Application design.
3. [The ssd and display objects](./README.md#3-the-ssd-and-display-objects)
4. [Screen class](./README.md#4-screen-class) Full screen window.
5. [Window class](./README.md#5-window-class)
6. [Label widget](./README.md#6-label-widget) Single line text display.
7. [LED widget](./README.md#7-led-widget) Display Boolean values.
8. [Checkbox widget](./README.md#8-checkbox-widget) Enter Boolean values.
9. [Button and CloseButton widgets](./README.md#9-button-and-closebutton-widgets) Pushbutton emulation.
10. [ButtonList object](./README.md#10-buttonlist-object) Pushbuttons with multiple states.
11. [RadioButtons object](./README.md#11-radiobuttons-object) One-of-N pushbuttons.
12. [Listbox widget](./README.md#12-listbox-widget)
13. [Dropdown widget](./README.md#13-dropdown-widget) Dropdown lists.
14. [DialogBox class](./README.md#14-dialogbox class) Pop-up modal dialog boxes.
15. [Textbox widget](./README.md#15-textbox-widget) Scrolling text display.
16. [Meter widget](./README.md#16-meter-widget) Display floats on an analog meter.
17. [Slider and HorizSlider widgets](./README.md#17-slider-and-horizslider-widgets) Linear potentiometer float data entry and display
18. [Scale widget](./README.md#18-scale-widget) High precision float entry and display.
19. [ScaleLog widget](./README.md#19-scalelog-widget) Wide dynamic range float entry and display.
20. [Dial widget](./README.md#20-dial-widget) Display multiple vectors.
21. [Knob widget](./README.md#21-knob-widget) Rotary potentiometer float entry.
22. [Graph plotting](./README.md#22-graph-plotting) Widgets for Cartesian and polar graphs.
[Appendix 1 Application design](./README.md#appendix-1-application-design)
# 1. Basic concepts # 1. Basic concepts
@ -54,12 +78,14 @@ attributes. It can overlay part of an underlying `Screen` and is typically used
for modal dialog boxes. for modal dialog boxes.
A `Widget` is an object capable of displaying data. Some are also capable of A `Widget` is an object capable of displaying data. Some are also capable of
data input. The latter can be capable of accepting focus, see data input: such a widget is defined as `active`. A `passive` widget can only
[navigation](./README.md#13-navigation). `Widget` objects have dimensions display data. An `active` widget can acquire `focus`. The widget with `focus`
defined as `height` and `width`. The space requred by them exceeds these by two is able to respond to user input. See [navigation](./README.md#14-navigation).
pixels all round, as a white border is drawn to show which object currently has `Widget` objects have dimensions defined as `height` and `width`. The space
focus. Thus to place a `Widget` at the extreme top left, `row` and `col` values requred by them exceeds these dimensions by two pixels all round. This is
should be 2. because `micro-gui` displays a white border to show which object currently has
`focus`. Thus to place a `Widget` at the extreme top left, `row` and `col`
values should be 2.
## 1.3 Fonts ## 1.3 Fonts
@ -87,16 +113,16 @@ The GUI requires from 2 to 5 pushbuttons for control. These are:
1. `Next` Move to the next widget. 1. `Next` Move to the next widget.
2. `Select` Operate the currently selected widget. 2. `Select` Operate the currently selected widget.
3. `Prev` Move to the previous widget. 3. `Prev` Move to the previous widget.
4. `Increase` Move within the widget. 4. `Increase` Move within the widget (i.e. adjust its value).
5. `Decrease` Move within the widget. 5. `Decrease` Move within the widget.
Many widgets such as `Pushbutton` or `Checkbox` objects require only the Many widgets such as `Pushbutton` or `Checkbox` objects require only the
`Select` button to operate: it is possible to design an interface using only `Select` button to operate: it is possible to design an interface with a subset
the first two buttons. of `micro-gui` widgets which requires only the first two buttons.
Widgets such as `Listbox` objects, dropdown lists (`Dropdown`), and those for Widgets such as `Listbox` objects, dropdown lists (`Dropdown`), and those for
floating point data entry require the `Increase` and `Decrease` buttons to move floating point data entry require the `Increase` and `Decrease` buttons to
within the widget or to adjust the linear value. select a data item or to adjust the linear value.
A `LinearIO` is a `Widget` that responds to the `increase` and `decrease` A `LinearIO` is a `Widget` that responds to the `increase` and `decrease`
buttons by running an `asyncio` task. These typically output floating point buttons by running an `asyncio` task. These typically output floating point
@ -104,25 +130,67 @@ values using an accelerating algorithm responding to the duration of the button
press. This enables floats with a wide dynamic range to be adjusted with press. This enables floats with a wide dynamic range to be adjusted with
precision. precision.
The currently selected `Widget` is identified by a white border: the focus The currently selected `Widget` is identified by a white border: the `focus`
moves between widgets via `Next` and `Prev`. Only `Widget` instances that can moves between widgets via `Next` and `Prev`. Only `active` `Widget` instances
accept input can receive the focus; such widgets are defined as `active`. (those that can accept input) can receive the `focus`. Widgets are defined as
Widgets are defined as `active` or passive in the constructor, and this status `active` or `passive` in the constructor, and this status cannot be changed. In
cannot be changed. In some cases the state can be specified as a constructor some cases the state can be specified as a constructor arg. An `active` widget
arg. An `active` widget can be disabled and re-enabled at runtime. A disabled can be disabled and re-enabled at runtime. A disabled `active` widget is shown
`active` widget is shown "greyed-out" and, until enabled, cannot accept the "greyed-out" and, until re-enabled, cannot accept the focus.
focus.
## 1.5 Hardware definition ## 1.5 Hardware definition
A file `hardware_setup.py` must exist in the GUI root directory. This defines A file `hardware_setup.py` must exist in the GUI root directory. This defines
the connections to the display, the display driver, and pins used for the the connections to the display, the display driver, and pins used for the
pushbuttons. Example files may be found in the `setup_examples` directory. pushbuttons. Example files may be found in the `setup_examples` directory. The
following is a typical example for a Raspberry Pi Pico driving an ILI9341
display:
```python
from machine import Pin, SPI, freq
import gc
from drivers.ili93xx.ili9341 import ILI9341 as SSD
freq(250_000_000) # RP2 overclock
# Create and export an SSD instance
pdc = Pin(8, Pin.OUT, value=0) # Arbitrary pins
prst = Pin(9, Pin.OUT, value=1)
pcs = Pin(10, Pin.OUT, value=1)
spi = SPI(0, baudrate=30_000_000)
gc.collect() # Precaution before instantiating framebuf
ssd = SSD(spi, pcs, pdc, prst, usd=True)
from gui.core.ugui import Display, setup
# Create and export a Display instance
# Define control buttons
nxt = Pin(19, Pin.IN, Pin.PULL_UP) # Move to next control
sel = Pin(16, Pin.IN, Pin.PULL_UP) # Operate current control
prev = Pin(18, Pin.IN, Pin.PULL_UP) # Move to previous control
increase = Pin(20, Pin.IN, Pin.PULL_UP) # Increase control's value
decrease = Pin(17, Pin.IN, Pin.PULL_UP) # Decrease control's value
display = Display(ssd, nxt, sel, prev, increase, decrease)
setup(display)
```
Display drivers are documented Display drivers are documented
[here](https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md). [here](https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md).
## 1.6 Installation ## 1.6 Quick hardware check
The following may be pasted at the REPL to verify correct connection to the
display. It also confirms that `hardware_setup.py` is specifying a suitable
display driver.
```python
from hardware_setup import ssd # Create a display instance
from gui.core.colors import *
ssd.fill(0)
ssd.line(0, 0, ssd.width - 1, ssd.height - 1, GREEN) # Green diagonal corner-to-corner
ssd.rect(0, 0, 15, 15, RED) # Red square at top left
ssd.rect(ssd.width -15, ssd.height -15, 15, 15, BLUE) # Blue square at bottom right
ssd.show()
```
## 1.7 Installation
The easy way to start is to use `mpremote` which allows a directory on your PC The easy way to start is to use `mpremote` which allows a directory on your PC
to be mounted on the host. In this way the filesystem on the host is left to be mounted on the host. In this way the filesystem on the host is left
@ -155,21 +223,6 @@ kept.
There is scope for speeding loading and saving RAM by using frozen bytecode. There is scope for speeding loading and saving RAM by using frozen bytecode.
Once again, directory structure must be maintained. Once again, directory structure must be maintained.
## 1.7 Quick hardware check
The following may be pasted at the REPL to verify correct connection to the
display. It also confirms that `hardware_setup.py` is specifying a suitable
display driver.
```python
from hardware_setup import ssd # Create a display instance
from gui.core.colors import *
ssd.fill(0)
ssd.line(0, 0, ssd.width - 1, ssd.height - 1, GREEN) # Green diagonal corner-to-corner
ssd.rect(0, 0, 15, 15, RED) # Red square at top left
ssd.rect(ssd.width -15, ssd.height -15, 15, 15, BLUE) # Blue square at bottom right
ssd.show()
```
## 1.8 Performance and hardware notes ## 1.8 Performance and hardware notes
The largest supported display is a 320x240 ILI9341 unit. On a Pi Pico with no The largest supported display is a 320x240 ILI9341 unit. On a Pi Pico with no
@ -182,29 +235,25 @@ Snappy navigation benefits from several approaches:
3. Device driver support for `uasyncio`. Currently this exists on ILI9341 and 3. Device driver support for `uasyncio`. Currently this exists on ILI9341 and
ST7789 (e.g. TTGO T-Display). I intend to extend this to other drivers. ST7789 (e.g. TTGO T-Display). I intend to extend this to other drivers.
On ESP32 I found it necessary to use physical pullup resistors on the On the TTGO T-Display I found it necessary to use physical pullup resistors on
pushbutton GPIO lines. the pushbutton GPIO lines. According to the ESP32 gurus pins 36-39 do not have
pullup support.
## 1.9 Firmware and dependencies ## 1.9 Firmware and dependencies
Firmware should be V1.15 or later. Firmware should be V1.15 or later. The source tree includes all dependencies.
These are listed to enable users to check for newer versions:
The source tree includes all dependencies. These are listed to enable users to
check for newer versions:
* [writer.py](https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/writer.py) * [writer.py](https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/writer.py)
Provides text rendering of Python font files. Provides text rendering of Python font files.
A copy of the official driver for OLED displays using the SSD1306 chip is
provided. The official file is here:
* [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py). * [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
A copy of the official driver for OLED displays using the SSD1306 chip is
Displays based on the Nokia 5110 (PCD8544 chip) require this driver. It is not provided. The link is to the official file.
in this repo but may be found here: * [Synchronisation primitives](https://github.com/peterhinch/micropython-async/tree/master/v3/primitives).
* [PCD8544/Nokia 5110](https://github.com/mcauser/micropython-pcd8544.git) The link is to my `uasyncio` support repo.
* [PCD8544/Nokia 5110](https://github.com/mcauser/micropython-pcd8544.git).
Synchronisation primitives for `uasyncio` may be found here: Displays based on the Nokia 5110 (PCD8544 chip) require this driver. It is not
* [My async repo](https://github.com/peterhinch/micropython-async/tree/master/v3/primitives). provided in this repo. The link is to its source.
## 1.10 Supported hosts and displays ## 1.10 Supported hosts and displays
@ -250,6 +299,8 @@ require a large (320x240) display. Demos are run by issuing (for example):
* `various.py` Assorted widgets including the different types of pushbutton. * `various.py` Assorted widgets including the different types of pushbutton.
* `vtest.py` Clock and compass styles of vector display. * `vtest.py` Clock and compass styles of vector display.
###### [Contents](./README.md#0-contents)
# 2. Usage # 2. Usage
## 2.1 Program structure and operation ## 2.1 Program structure and operation
@ -309,7 +360,7 @@ Note how the `Next` pushbutton moves the focus between the two buttons and the
it is not `active`: a `Label` cannot accept user input. Pushing the `Select` it is not `active`: a `Label` cannot accept user input. Pushing the `Select`
pushbutton while the focus is on a `Pushbutton` causes the callback to run. pushbutton while the focus is on a `Pushbutton` causes the callback to run.
Applications start by performing `Screen.change()` to a user-defined Screen Applications start by performing `Screen.change()` to a user-defined `Screen`
object. This must be subclassed from the GUI's `Screen` class. Note that object. This must be subclassed from the GUI's `Screen` class. Note that
`Screen.change` accepts a class name, not a class instance. `Screen.change` accepts a class name, not a class instance.
@ -340,41 +391,41 @@ optional: a default null function and empty list are provided. Callbacks may
optionally be written as bound methods. This facilitates communication between optionally be written as bound methods. This facilitates communication between
widgets. widgets.
When writing callbacks take care to ensure that the number of arguments passed When writing callbacks take care to ensure that the correct number of arguments
is correct, bearing in mind the first arg listed above. Failure to do this will are passed, bearing in mind the first arg described above. An incorrect
result in tracebacks which implicate the GUI code rather than the buggy user argument count results in puzzling tracebacks which appear to implicate the GUI
code: this is because the GUI runs the callbacks. code. This is because it is the GUI which actually executes the callbacks.
## 2.3 Colors ## 2.3 Colors
The file `gui/core/colors.py` defines standard color constants which may be The file `gui/core/colors.py` defines a set of color constants which may be
used with any display driver. This section describes how to change these or used with any display driver. This section describes how to change these or
to create additional colors. to create additional colors. Most of the color display drivers define colors
as 8-bit or larger values. For the larger displays 4-bit drivers are provided
with the aim of conserving RAM.
Most of the color display drivers define colors as 8-bit or larger values. In the 4-bit case colors are assigned to a lookup table (LUT) with 16 entries.
In such cases colors may be created and assigned to variables as follows: The frame buffer stores 4-bit color values, which are converted to the correct
```python color depth for the hardware when the display is refreshed. Of the 16 possible
from hardware_setup import ssd colors 13 are assigned in `gui/core/colors.py`, leaving color numbers 12, 13
PALE_YELLOW = ssd.rgb(150, 150, 0) and 14 free.
```
The GUI also provides drivers with 4-bit color to minimise RAM use. Colors are
assigned to a lookup table having 16 entries. The frame buffer stores 4-bit
color values, which are converted to the correct color depth for the hardware
when the display is refreshed.
Of the possible 16 colors 13 are assigned in `gui/core/colors.py`, leaving The following code is portable between displays and creates a user defined
color numbers 12, 13 and 14 free. Any color can be assigned as follows: color `PALE_YELLOW`.
```python ```python
from gui.core.colors import * # Imports the create_color function from gui.core.colors import * # Imports the create_color function
PALE_YELLOW = create_color(12, 150, 150, 0) PALE_YELLOW = create_color(12, 150, 150, 0) # index, r, g, b
``` ```
This creates a color `rgb(150, 150, 0)` assigns it to "spare" color number 12 If a 4-bit driver is in use, the color `rgb(150, 150, 0)` will be assigned to
then sets `PALE_YELLOW` to 12. Any color number in range `0 <= n <= 15` may be "spare" color number 12. Any color number in range `0 <= n <= 15` may be
used (implying that predefined colors may be reassigned). It is recommended used, implying that predefined colors may be reassigned. It is recommended
that `BLACK` (0) and `WHITE` (15) are not changed. If code is to be ported that `BLACK` (0) and `WHITE` (15) are not changed. If an 8-bit or larger driver
between 4-bit and other drivers, use `create_color()` for all custom colors: is in use, the first `index` arg is ignored and there is no restriction on the
it will produce appropriate behaviour. For an example see the `nano-gui` demo number of colors that may be created.
`color15.py` - in particular the `vari_fields` function.
Regardless of the display driver the `PALE_YELLOW` variable may be used to
refer to the color. An example of custom color definition may be found in
[this nano-gui demo](https://github.com/peterhinch/micropython-nano-gui/blob/4ef0e20da27ef7c0b5c34136dcb372200f0e5e66/gui/demos/color15.py#L92).
### 2.3.1 Monochrome displays ### 2.3.1 Monochrome displays
@ -391,7 +442,24 @@ There is an issue regarding ePaper displays discussed
I don't consider ePaper displays as suitable for I/O because of their slow I don't consider ePaper displays as suitable for I/O because of their slow
refresh time. refresh time.
# 3. Class details ###### [Contents](./README.md#0-contents)
# 3. The ssd and display objects
The following code, issued as the first executable line of an application,
initialises the display.
```python
from hardware_setup import display, ssd
```
It creates singleton instances of `SSD` and `Display` classes. Normal GUI
applications only need to import `ssd`. This refererence to the display driver
is used to initialise `Writer` objects. Bound variables `.height` and `.width`
may be read to determine the dimensions of the display hardware.
Use of `display` is restricted to applications which use graphics primitives to
write directly to the screen. See Appendix 1.
###### [Contents](./README.md#0-contents)
# 4. Screen class # 4. Screen class
@ -454,6 +522,8 @@ base screen are cancelled.
For finer control applications can ignore this method and handle cancellation For finer control applications can ignore this method and handle cancellation
explicitly in code. explicitly in code.
###### [Contents](./README.md#0-contents)
# 5. Window class # 5. Window class
This is a `Screen` subclass providing for modal windows. As such it has This is a `Screen` subclass providing for modal windows. As such it has
@ -485,6 +555,8 @@ callbacks to the user window constructor args. These may be called by widgets
to send data to the calling screen. Note that widgets on the screen below will to send data to the calling screen. Note that widgets on the screen below will
not be updated until the window has closed. not be updated until the window has closed.
###### [Contents](./README.md#0-contents)
# 6. Label widget # 6. Label widget
```python ```python
@ -562,6 +634,8 @@ class BaseScreen(Screen):
Screen.change(BaseScreen) Screen.change(BaseScreen)
``` ```
###### [Contents](./README.md#0-contents)
# 7. LED widget # 7. LED widget
```python ```python
@ -600,6 +674,8 @@ Methods:
passed, no border is displayed. This clears a previously drawn border. passed, no border is displayed. This clears a previously drawn border.
3. `show` No args. (Re)draws the LED. Primarily for internal use by GUI. 3. `show` No args. (Re)draws the LED. Primarily for internal use by GUI.
###### [Contents](./README.md#0-contents)
# 8. Checkbox widget # 8. Checkbox widget
```python ```python
@ -638,6 +714,8 @@ Methods:
correspond to the control's current value, updates it; the checkbox is correspond to the control's current value, updates it; the checkbox is
re-drawn and the callback executed. Always returns the control's value. re-drawn and the callback executed. Always returns the control's value.
###### [Contents](./README.md#0-contents)
# 9. Button and CloseButton widgets # 9. Button and CloseButton widgets
```python ```python
@ -694,6 +772,8 @@ right hand corner of the current `Screen`. Operating it causes the screen to
close, with the screen below being revealed. On the bottom level screen, a close, with the screen below being revealed. On the bottom level screen, a
`CloseButton` will shut down the application. `CloseButton` will shut down the application.
###### [Contents](./README.md#0-contents)
# 10. ButtonList object # 10. ButtonList object
```python ```python
@ -741,6 +821,8 @@ for t in table: # Buttons overlay each other at same location
bl.add_button(wri, 10, 10, textcolor = BLACK, **t) bl.add_button(wri, 10, 10, textcolor = BLACK, **t)
``` ```
###### [Contents](./README.md#0-contents)
# 11. RadioButtons object # 11. RadioButtons object
```python ```python
@ -787,6 +869,8 @@ for t in table:
col += 60 # Horizontal row of buttons col += 60 # Horizontal row of buttons
``` ```
###### [Contents](./README.md#0-contents)
# 12. Listbox widget # 12. Listbox widget
```python ```python
@ -845,6 +929,8 @@ The callback's first argument is the listbox instance followed by any args
specified to the constructor. The currently selected item may be retrieved by specified to the constructor. The currently selected item may be retrieved by
means of the instance's `value` or `textvalue` methods. means of the instance's `value` or `textvalue` methods.
###### [Contents](./README.md#0-contents)
# 13. Dropdown widget # 13. Dropdown widget
```python ```python
@ -914,6 +1000,8 @@ The callback's first argument is the dropdown instance followed by any args
specified to the constructor. The currently selected item may be retrieved by specified to the constructor. The currently selected item may be retrieved by
means of the instance's `value` or `textvalue` methods. means of the instance's `value` or `textvalue` methods.
###### [Contents](./README.md#0-contents)
# 14. DialogBox class # 14. DialogBox class
```python ```python
@ -959,6 +1047,8 @@ flexible designs. For example these might have widgets other than pushbuttons.
The approach is to write a user subclass of `Window`. Example code may be found The approach is to write a user subclass of `Window`. Example code may be found
in `gui/demos/screens.py`. in `gui/demos/screens.py`.
###### [Contents](./README.md#0-contents)
# 15. Textbox widget # 15. Textbox widget
```python ```python
@ -1024,6 +1114,8 @@ If text is regularly appended to a `Textbox` its buffer grows, using RAM. The
value of `ntrim` sets a limit to the number of lines which are retained, with value of `ntrim` sets a limit to the number of lines which are retained, with
the oldest (topmost) being discarded as required. the oldest (topmost) being discarded as required.
###### [Contents](./README.md#0-contents)
# 16. Meter widget # 16. Meter widget
```python ```python
@ -1078,6 +1170,8 @@ Methods:
passed, no border is displayed. This clears a previously drawn border. passed, no border is displayed. This clears a previously drawn border.
3. `show` No args. (Re)draws the meter. Primarily for internal use by GUI. 3. `show` No args. (Re)draws the meter. Primarily for internal use by GUI.
###### [Contents](./README.md#0-contents)
# 17. Slider and HorizSlider widgets # 17. Slider and HorizSlider widgets
```python ```python
@ -1141,6 +1235,8 @@ user supplied args. They can be a bound methods, typically of a `Screen`
subclass. The callback runs whenever the value changes enabling dynamic color subclass. The callback runs whenever the value changes enabling dynamic color
change. See `gui/demos/active.py`. change. See `gui/demos/active.py`.
###### [Contents](./README.md#0-contents)
# 18. Scale widget # 18. Scale widget
```python ```python
@ -1249,6 +1345,8 @@ For performance reasons the control stores values as integers. This means that
if you set `value` and subsequently retrieve it, there may be some loss of if you set `value` and subsequently retrieve it, there may be some loss of
precision. Each visible division on the control represents 10 integer units. precision. Each visible division on the control represents 10 integer units.
###### [Contents](./README.md#0-contents)
# 19. ScaleLog widget # 19. ScaleLog widget
```python ```python
@ -1363,6 +1461,8 @@ def tickcb(f, c):
return c return c
``` ```
###### [Contents](./README.md#0-contents)
# 20. Dial widget # 20. Dial widget
```python ```python
@ -1479,6 +1579,8 @@ class BaseScreen(Screen):
Screen.change(BaseScreen) Screen.change(BaseScreen)
``` ```
###### [Contents](./README.md#0-contents)
# 21. Knob widget # 21. Knob widget
```python ```python
@ -1520,6 +1622,8 @@ Methods:
correspond to the new value. The move callback will run. The method constrains correspond to the new value. The move callback will run. The method constrains
the range to 0.0 to 1.0. Always returns the control's value. the range to 0.0 to 1.0. Always returns the control's value.
###### [Contents](./README.md#0-contents)
# 22. Graph Plotting # 22. Graph Plotting
```python ```python
@ -1769,9 +1873,11 @@ class TSeq(Screen):
t += 1 t += 1
``` ```
# 23. Application design ###### [Contents](./README.md#0-contents)
## 23.1 Tab order and button layout # Appendix 1 Application design
## Tab order and button layout
The "tab order" of widgets on a `Screen` is the order with which they acquire The "tab order" of widgets on a `Screen` is the order with which they acquire
focus with successive presses of the `Next` button. It is determined by the focus with successive presses of the `Next` button. It is determined by the
@ -1796,7 +1902,7 @@ 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 to the fact that the length of the internal text can be substantial and
variable. variable.
## 23.2 Use of graphics primitives ## Use of graphics primitives
These notes are for those wishing to draw directly to the `Screen` instance. 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 This is done by providing the user `Screen` class with an `after_open()` method

Wyświetl plik

@ -1,7 +1,7 @@
# active.py micro-gui demo of widgets that respond to user control # active.py micro-gui demo of widgets that respond to user control
# Import SSD and Display instances. Must be done first because of RAM use. # Create SSD instance. Must be done first because of RAM use.
from hardware_setup import display, ssd # Create a display instance from hardware_setup import ssd
from gui.core.ugui import Screen from gui.core.ugui import Screen
from gui.core.writer import CWriter from gui.core.writer import CWriter
import gui.fonts.arial10 as arial10 # Font for CWriter import gui.fonts.arial10 as arial10 # Font for CWriter
@ -90,7 +90,7 @@ class BaseScreen(Screen):
s.color(GREEN) s.color(GREEN)
def test(): def test():
if display.height < 240 or display.width < 320: if ssd.height < 240 or ssd.width < 320:
print(' This test requires a display of at least 320x240 pixels.') print(' This test requires a display of at least 320x240 pixels.')
else: else:
print('Testing micro-gui...') print('Testing micro-gui...')

Wyświetl plik

@ -7,8 +7,8 @@
# Released under the MIT License (MIT). See LICENSE. # Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2021 Peter Hinch # Copyright (c) 2021 Peter Hinch
# Initialise hardware and framebuf before importing modules. # Create SSD instance. Must be done first because of RAM use.
from hardware_setup import ssd, display # Create a display instance from hardware_setup import ssd
import cmath import cmath
import math import math
@ -241,7 +241,7 @@ class BaseScreen(Screen):
Screen.change(d[lb.textvalue()]) Screen.change(d[lb.textvalue()])
def test(): def test():
if display.height < 128 or display.width < 200: if ssd.height < 128 or ssd.width < 200:
print(' This test requires a display of at least 128x200 pixels.') print(' This test requires a display of at least 128x200 pixels.')
else: else:
print('Testing micro-gui...') print('Testing micro-gui...')

Wyświetl plik

@ -1,7 +1,7 @@
# screens.py micro-gui demo of multiple screens, dropdowns etc # screens.py micro-gui demo of multiple screens, dropdowns etc
# Initialise hardware and framebuf before importing modules.
# Import SSD and Display instances. Must be done first because of RAM use. # Create SSD instance. Must be done first because of RAM use.
from hardware_setup import display, ssd # Create a display instance from hardware_setup import ssd # Create a display instance
from gui.core.ugui import Screen, Window from gui.core.ugui import Screen, Window
from gui.widgets.label import Label from gui.widgets.label import Label
@ -100,7 +100,7 @@ class BaseScreen(Screen):
CloseButton(wri) # Quit the application CloseButton(wri) # Quit the application
def test(): def test():
if display.height < 128 or display.width < 240: if ssd.height < 128 or ssd.width < 240:
print('This test requires a display of at least 240x128 pixels.') print('This test requires a display of at least 240x128 pixels.')
else: else:
print('Testing micro-gui...') print('Testing micro-gui...')

Wyświetl plik

@ -7,7 +7,7 @@
# import gui.demos.tbox # import gui.demos.tbox
# Initialise hardware and framebuf before importing modules. # Initialise hardware and framebuf before importing modules.
from hardware_setup import display, ssd # Create a display instance from hardware_setup import ssd # Create a display instance
from gui.core.ugui import Screen from gui.core.ugui import Screen
from gui.core.writer import CWriter from gui.core.writer import CWriter
@ -111,7 +111,7 @@ class MainScreen(Screen):
def test(): def test():
if display.height < 128 or display.width < 128: if ssd.height < 128 or ssd.width < 128:
print(' This test requires a display of at least 128x128 pixels.') print(' This test requires a display of at least 128x128 pixels.')
else: else:
print('Testing micro-gui...') print('Testing micro-gui...')

Wyświetl plik

@ -1,8 +1,9 @@
# various.py micro-gui demo of multiple controls on a large display # various.py micro-gui demo of multiple controls on a large display
# Initialise hardware and framebuf before importing modules. # Initialise hardware and framebuf before importing modules.
# Import SSD and Display instances. Must be done first because of RAM use. # Create SSD instance. Must be done first because of RAM use.
from hardware_setup import display, ssd # Create a display instance from hardware_setup import ssd
from gui.core.ugui import Screen from gui.core.ugui import Screen
from gui.core.writer import CWriter from gui.core.writer import CWriter
import gui.fonts.arial10 as arial10 # Font for CWriter import gui.fonts.arial10 as arial10 # Font for CWriter
@ -159,7 +160,7 @@ async def run(dial, lbltim, m0, scale):
def test(): def test():
if display.height < 240 or display.width < 320: if ssd.height < 240 or ssd.width < 320:
print(' This test requires a display of at least 320x240 pixels.') print(' This test requires a display of at least 320x240 pixels.')
else: else:
print('Testing micro-gui...') print('Testing micro-gui...')

Wyświetl plik

@ -3,8 +3,8 @@
# Released under the MIT License (MIT). See LICENSE. # Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2021 Peter Hinch # Copyright (c) 2021 Peter Hinch
# Initialise hardware and framebuf before importing modules. # Create SSD instance. Must be done first because of RAM use.
from hardware_setup import display, ssd # Create a display instance from hardware_setup import ssd
import urandom import urandom
import time import time
@ -104,7 +104,7 @@ class VScreen(Screen):
self.reg_task(aclock(dial, lbldate, lbltim)) self.reg_task(aclock(dial, lbldate, lbltim))
def test(): def test():
if display.height < 240 or display.width < 320: if ssd.height < 240 or ssd.width < 320:
print(' This test requires a display of at least 320x240 pixels.') print(' This test requires a display of at least 320x240 pixels.')
else: else:
print('Testing micro-gui...') print('Testing micro-gui...')