kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
README needs updating.
rodzic
447e87bad1
commit
3f7be4ebba
152
README.md
152
README.md
|
@ -109,39 +109,42 @@ a workround if it's impossible to upgrade. See
|
||||||
5.1 [Constructor](./README.md#51-constructor)
|
5.1 [Constructor](./README.md#51-constructor)
|
||||||
5.2 [Class method](./README.md#52-class-method)
|
5.2 [Class method](./README.md#52-class-method)
|
||||||
5.3 [Popup windows](./README.md#53-popup-windows)
|
5.3 [Popup windows](./README.md#53-popup-windows)
|
||||||
6. [Label widget](./README.md#6-label-widget) Single line text display.
|
6. [Widgets](./README.md#6-widgets) Displayable objects.
|
||||||
7. [LED widget](./README.md#7-led-widget) Display Boolean values.
|
6.1 [Label widget](./README.md#61-label-widget) Single line text display.
|
||||||
8. [Checkbox widget](./README.md#8-checkbox-widget) Enter Boolean values.
|
6.2 [LED widget](./README.md#62-led-widget) Display Boolean values.
|
||||||
9. [Button and CloseButton widgets](./README.md#9-button-and-closebutton-widgets) Pushbutton emulation.
|
6.3 [Checkbox widget](./README.md#63-checkbox-widget) Enter Boolean values.
|
||||||
10. [ButtonList object](./README.md#10-buttonlist-object) Pushbuttons with multiple states.
|
6.4 [Button and CloseButton widgets](./README.md#64-button-and-closebutton-widgets) Pushbutton emulation.
|
||||||
11. [RadioButtons object](./README.md#11-radiobuttons-object) One-of-N pushbuttons.
|
6.5 [ButtonList object](./README.md#65-buttonlist-object) Pushbuttons with multiple states.
|
||||||
12. [Listbox widget](./README.md#12-listbox-widget)
|
6.6 [RadioButtons object](./README.md#66-radiobuttons-object) One-of-N pushbuttons.
|
||||||
13. [Dropdown widget](./README.md#13-dropdown-widget) Dropdown lists.
|
6.7 [Listbox widget](./README.md#67-listbox-widget)
|
||||||
14. [DialogBox class](./README.md#14-dialogbox-class) Pop-up modal dialog boxes.
|
6.8 [Dropdown widget](./README.md#68-dropdown-widget) Dropdown lists.
|
||||||
15. [Textbox widget](./README.md#15-textbox-widget) Scrolling text display.
|
6.9 [DialogBox class](./README.md#69-dialogbox-class) Pop-up modal dialog boxes.
|
||||||
16. [Meter widget](./README.md#16-meter-widget) Display floats on an analog meter, with data driven callbacks.
|
6.10 [Textbox widget](./README.md#610-textbox-widget) Scrolling text display.
|
||||||
16.1 [Region class](./README.md#161-region-class)
|
6.11 [Meter widget](./README.md#611-meter-widget) Display floats on an analog meter, with data driven callbacks.
|
||||||
17. [Slider and HorizSlider widgets](./README.md#17-slider-and-horizslider-widgets) Linear potentiometer float data entry and display
|
6.11.1 [Region class](./README.md#161-region-class)
|
||||||
18. [Scale widget](./README.md#18-scale-widget) High precision float entry and display.
|
6.12 [Slider and HorizSlider widgets](./README.md#612-slider-and-horizslider-widgets) Linear potentiometer float data entry and display
|
||||||
19. [ScaleLog widget](./README.md#19-scalelog-widget) Wide dynamic range float entry and display.
|
6.13 [Scale widget](./README.md#613-scale-widget) High precision float entry and display.
|
||||||
20. [Dial widget](./README.md#20-dial-widget) Display multiple vectors.
|
6.14 [ScaleLog widget](./README.md#614-scalelog-widget) Wide dynamic range float entry and display.
|
||||||
21. [Knob widget](./README.md#21-knob-widget) Rotary potentiometer float entry.
|
6.15 [Dial widget](./README.md#615-dial-widget) Display multiple vectors.
|
||||||
22. [Adjuster widget](./README.md#22-adjuster-widget) Space saving way to enter floats.
|
6.16 [Knob widget](./README.md#616-knob-widget) Rotary potentiometer float entry.
|
||||||
23. [Menu class](./README.md#23-menu-class)
|
6.17 [Adjuster widget](./README.md#617-adjuster-widget) Space saving way to enter floats.
|
||||||
24. [Graph plotting](./README.md#24-graph-plotting) Widgets for Cartesian and polar graphs.
|
6.18 [Menu class](./README.md#618-menu-class)
|
||||||
24.1 [Concepts](./README.md#241-concepts)
|
6.19 [BitMap widget](./README.md#619-bitmap-widget) Draw bitmaps from files.__
|
||||||
24.1.1 [Graph classes](./README.md#2411-graph-classes)
|
6.20 [QRMap widget](./README.md#620-qrmap-widget) Draw QR codes.__
|
||||||
24.1.2 [Curve classes](./README.md#2412-curve-classes)
|
7. [Graph plotting](./README.md#7-graph-plotting) Widgets for Cartesian and polar graphs.
|
||||||
24.1.3 [Coordinates](./README.md#2413-coordinates)
|
7.1 [Concepts](./README.md#71-concepts)
|
||||||
24.2 [Graph classes](./README.md#242-graph-classes)
|
7.1.1 [Graph classes](./README.md#711-graph-classes)
|
||||||
24.2.1 [Class CartesianGraph](./README.md#2421-class-cartesiangraph)
|
7.1.2 [Curve classes](./README.md#712-curve-classes)
|
||||||
24.2.2 [Class PolarGraph](./README.md#2422-class-polargraph)
|
7.1.3 [Coordinates](./README.md#713-coordinates)
|
||||||
24.3 [Curve classes](./README.md#243-curve-classes)
|
7.2 [Graph classes](./README.md#72-graph-classes)
|
||||||
24.3.1 [Class Curve](./README.md#2431-class-curve)
|
7.2.1 [Class CartesianGraph](./README.md#721-class-cartesiangraph)
|
||||||
24.3.2 [Class PolarCurve](./README.md#2432-class-polarcurve)
|
7.2.2 [Class PolarGraph](./README.md#722-class-polargraph)
|
||||||
24.4 [Class TSequence](./README.md#244-class-tsequence) Plotting realtime, time sequential data.
|
7.3 [Curve classes](./README.md#73-curve-classes)
|
||||||
25. [Old firmware](./README.md#25-old-firmware) For users of color displays who can't run current firmware.
|
7.3.1 [Class Curve](./README.md#731-class-curve)
|
||||||
26. [Realtime applications](./README.md#26-realtime-applications) Accommodating tasks requiring fast RT performance.
|
7.3.2 [Class PolarCurve](./README.md#732-class-polarcurve)
|
||||||
|
7.4 [Class TSequence](./README.md#74-class-tsequence) Plotting realtime, time sequential data.
|
||||||
|
8. [Old firmware](./README.md#8-old-firmware) For users of color displays who can't run current firmware.
|
||||||
|
9. [Realtime applications](./README.md#9-realtime-applications) Accommodating tasks requiring fast RT performance.
|
||||||
[Appendix 1 Application design](./README.md#appendix-1-application-design) Tab order, button layout, encoder interface, use of graphics primitives
|
[Appendix 1 Application design](./README.md#appendix-1-application-design) Tab order, button layout, encoder interface, use of graphics primitives
|
||||||
|
|
||||||
# 1. Basic concepts
|
# 1. Basic concepts
|
||||||
|
@ -960,7 +963,9 @@ constructor and is closed by issuing the `close()` static method.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 6. Label widget
|
# 6. Widgets
|
||||||
|
|
||||||
|
## 6.1 Label widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Label
|
from gui.widgets import Label
|
||||||
|
@ -1046,7 +1051,7 @@ Screen.change(BaseScreen)
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 7. LED widget
|
## 6.2 LED widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import LED
|
from gui.widgets import LED
|
||||||
|
@ -1085,7 +1090,7 @@ controlled with `led(True)` or `led(False)`.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 8. Checkbox widget
|
## 6.3 Checkbox widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Checkbox
|
from gui.widgets import Checkbox
|
||||||
|
@ -1126,7 +1131,7 @@ Methods:
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 9. Button and CloseButton widgets
|
## 6.4 Button and CloseButton widgets
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.core.colors import * # Colors and shapes
|
from gui.core.colors import * # Colors and shapes
|
||||||
|
@ -1203,7 +1208,7 @@ Optional keyword only arguments:
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 10. ButtonList object
|
## 6.5 ButtonList object
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.core.colors import * # Colors and shapes
|
from gui.core.colors import * # Colors and shapes
|
||||||
|
@ -1262,7 +1267,7 @@ for t in table: # Buttons overlay each other at same location
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 11. RadioButtons object
|
## 6.6 RadioButtons object
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.core.colors import * # Colors and shapes
|
from gui.core.colors import * # Colors and shapes
|
||||||
|
@ -1310,7 +1315,7 @@ for t in table:
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 12. Listbox widget
|
## 6.7 Listbox widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Listbox
|
from gui.widgets import Listbox
|
||||||
|
@ -1419,7 +1424,7 @@ Screen.change(BaseScreen)
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 13. Dropdown widget
|
## 6.8 Dropdown widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Dropdown
|
from gui.widgets import Dropdown
|
||||||
|
@ -1534,7 +1539,7 @@ Screen.change(BaseScreen)
|
||||||
```
|
```
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 14. DialogBox class
|
## 6.9 DialogBox class
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import DialogBox
|
from gui.widgets import DialogBox
|
||||||
|
@ -1588,7 +1593,7 @@ in `gui/demos/screens.py`.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 15. Textbox widget
|
## 6.10 Textbox widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Textbox
|
from gui.widgets import Textbox
|
||||||
|
@ -1655,7 +1660,7 @@ the oldest (topmost) being discarded as required.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 16. Meter widget
|
## 6.11 Meter widget
|
||||||
|
|
||||||
This `passive` widget displays a single floating point value on a vertical
|
This `passive` widget displays a single floating point value on a vertical
|
||||||
linear scale. Optionally it can support data dependent callbacks.
|
linear scale. Optionally it can support data dependent callbacks.
|
||||||
|
@ -1749,7 +1754,7 @@ behaves similarly for data values between 0.9 and 1.0.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
## 16.1 Region class
|
### 6.11.1 Region class
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Region
|
from gui.widgets import Region
|
||||||
|
@ -1809,7 +1814,7 @@ callbacks to run as appropriate.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 17. Slider and HorizSlider widgets
|
## 6.12 Slider and HorizSlider widgets
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Slider, HorizSlider
|
from gui.widgets import Slider, HorizSlider
|
||||||
|
@ -1887,7 +1892,7 @@ around sliders to display all legends.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 18. Scale widget
|
## 6.13 Scale widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Scale
|
from gui.widgets import Scale
|
||||||
|
@ -2024,7 +2029,7 @@ precision. Each visible division on the control represents 10 integer units.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 19. ScaleLog widget
|
## 6.14 ScaleLog widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import ScaleLog
|
from gui.widgets import ScaleLog
|
||||||
|
@ -2164,7 +2169,7 @@ def tickcb(f, c):
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 20. Dial widget
|
## 6.15 Dial widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Dial, Pointer
|
from gui.widgets import Dial, Pointer
|
||||||
|
@ -2280,7 +2285,7 @@ Screen.change(BaseScreen)
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 21. Knob widget
|
## 6.16 Knob widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Knob
|
from gui.widgets import Knob
|
||||||
|
@ -2338,7 +2343,7 @@ value changes. This enables dynamic color change.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 22. Adjuster widget
|
## 6.17 Adjuster widget
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Adjuster
|
from gui.widgets import Adjuster
|
||||||
|
@ -2404,7 +2409,7 @@ basis. See code comments for further details.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 23 Menu class
|
## 6.18 Menu class
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets import Menu
|
from gui.widgets import Menu
|
||||||
|
@ -2512,7 +2517,22 @@ different callback if the application required it.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 24. Graph Plotting
|
## 6.19 BitMap Widget
|
||||||
|
|
||||||
|
This renders a monochrome bitmap stored in a file to a rectangular region. The
|
||||||
|
bitmap file format is C source code generated by the Linux `bitmap` editor. The
|
||||||
|
data may be rendered in any color. Data and colors can be changed at run time.
|
||||||
|
|
||||||
|
Not suitable for animation due to blocking time.
|
||||||
|
Question generator in coroutine.
|
||||||
|
|
||||||
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
|
## 6.20 QRMap Widget
|
||||||
|
|
||||||
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
|
# 7. Graph Plotting
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from gui.widgets.graph import PolarGraph, PolarCurve, CartesianGraph, Curve, TSequence
|
from gui.widgets.graph import PolarGraph, PolarCurve, CartesianGraph, Curve, TSequence
|
||||||
|
@ -2525,7 +2545,7 @@ from gui.widgets.graph import PolarGraph, PolarCurve, CartesianGraph, Curve, TSe
|
||||||
|
|
||||||
For example code see `gui/demos/plot.py`.
|
For example code see `gui/demos/plot.py`.
|
||||||
|
|
||||||
## 24.1 Concepts
|
## 7.1 Concepts
|
||||||
|
|
||||||
Data for Cartesian graphs constitutes a sequence of x, y pairs, for polar
|
Data for Cartesian graphs constitutes a sequence of x, y pairs, for polar
|
||||||
graphs it is a sequence of complex `z` values. The module supports three
|
graphs it is a sequence of complex `z` values. The module supports three
|
||||||
|
@ -2535,13 +2555,13 @@ common cases:
|
||||||
3. One or more `y` values arrive gradually. The `X` axis represents time. This
|
3. One or more `y` values arrive gradually. The `X` axis represents time. This
|
||||||
is a simplifying case of 2.
|
is a simplifying case of 2.
|
||||||
|
|
||||||
### 24.1.1 Graph classes
|
### 7.1.1 Graph classes
|
||||||
|
|
||||||
A user program first instantiates a graph object (`PolarGraph` or
|
A user program first instantiates a graph object (`PolarGraph` or
|
||||||
`CartesianGraph`). This creates an empty graph image upon which one or more
|
`CartesianGraph`). This creates an empty graph image upon which one or more
|
||||||
curves may be plotted. Graphs are passive widgets so cannot accept user input.
|
curves may be plotted. Graphs are passive widgets so cannot accept user input.
|
||||||
|
|
||||||
### 24.1.2 Curve classes
|
### 7.1.2 Curve classes
|
||||||
|
|
||||||
The user program then instantiates one or more curves (`Curve` or
|
The user program then instantiates one or more curves (`Curve` or
|
||||||
`PolarCurve`) as appropriate to the graph. Curves may be assigned colors to
|
`PolarCurve`) as appropriate to the graph. Curves may be assigned colors to
|
||||||
|
@ -2556,7 +2576,7 @@ Where it is required to plot realtime data as it arrives, this is achieved
|
||||||
via calls to the curve's `point` method. If a prior point exists it causes a
|
via calls to the curve's `point` method. If a prior point exists it causes a
|
||||||
line to be drawn connecting the point to the last one drawn.
|
line to be drawn connecting the point to the last one drawn.
|
||||||
|
|
||||||
### 24.1.3 Coordinates
|
### 7.1.3 Coordinates
|
||||||
|
|
||||||
`PolarGraph` and `CartesianGraph` objects are subclassed from `Widget` and are
|
`PolarGraph` and `CartesianGraph` objects are subclassed from `Widget` and are
|
||||||
positioned accordingly by `row` and `col` with a 2-pixel outside border. The
|
positioned accordingly by `row` and `col` with a 2-pixel outside border. The
|
||||||
|
@ -2572,9 +2592,9 @@ unit circle but will be clipped to the rectangular graph boundary.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
## 24.2 Graph classes
|
## 7.2 Graph classes
|
||||||
|
|
||||||
### 24.2.1 Class CartesianGraph
|
### 7.2.1 Class CartesianGraph
|
||||||
|
|
||||||
Constructor.
|
Constructor.
|
||||||
Mandatory positional arguments:
|
Mandatory positional arguments:
|
||||||
|
@ -2601,7 +2621,7 @@ Keyword only arguments (all optional):
|
||||||
Method:
|
Method:
|
||||||
* `show` No args. Redraws the empty graph. Used when plotting time sequences.
|
* `show` No args. Redraws the empty graph. Used when plotting time sequences.
|
||||||
|
|
||||||
### 24.2.2 Class PolarGraph
|
### 7.2.2 Class PolarGraph
|
||||||
|
|
||||||
Constructor.
|
Constructor.
|
||||||
Mandatory positional arguments:
|
Mandatory positional arguments:
|
||||||
|
@ -2626,9 +2646,9 @@ Method:
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
## 24.3 Curve classes
|
## 7.3 Curve classes
|
||||||
|
|
||||||
### 24.3.1 Class Curve
|
### 7.3.1 Class Curve
|
||||||
|
|
||||||
The Cartesian curve constructor takes the following positional arguments:
|
The Cartesian curve constructor takes the following positional arguments:
|
||||||
|
|
||||||
|
@ -2668,7 +2688,7 @@ To plot x values from 1000 to 4000 we would set the `origin` x value to 1000
|
||||||
and the `excursion` x value to 3000. The `excursion` values scale the plotted
|
and the `excursion` x value to 3000. The `excursion` values scale the plotted
|
||||||
values to fit the corresponding axis.
|
values to fit the corresponding axis.
|
||||||
|
|
||||||
### 24.3.2 Class PolarCurve
|
### 7.3.2 Class PolarCurve
|
||||||
|
|
||||||
The constructor takes the following positional arguments:
|
The constructor takes the following positional arguments:
|
||||||
|
|
||||||
|
@ -2702,7 +2722,7 @@ Complex points should lie within the unit circle to be drawn within the grid.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
## 24.4 Class TSequence
|
## 7.4 Class TSequence
|
||||||
|
|
||||||
A common task is the acquisition and plotting of real time data against time,
|
A common task is the acquisition and plotting of real time data against time,
|
||||||
such as hourly temperature and air pressure readings. This class facilitates
|
such as hourly temperature and air pressure readings. This class facilitates
|
||||||
|
@ -2766,7 +2786,7 @@ class TSeq(Screen):
|
||||||
```
|
```
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
# 25. Old firmware
|
# 8. Old firmware
|
||||||
|
|
||||||
Current firmware is highly recommended. For users of color displays who cannot
|
Current firmware is highly recommended. For users of color displays who cannot
|
||||||
run V1.17 or later it is possible to run under V1.15+. This involves copying
|
run V1.17 or later it is possible to run under V1.15+. This involves copying
|
||||||
|
@ -2774,7 +2794,7 @@ run V1.17 or later it is possible to run under V1.15+. This involves copying
|
||||||
to `gui/core/writer.py`. This uses Python code to render text if the firmware
|
to `gui/core/writer.py`. This uses Python code to render text if the firmware
|
||||||
or driver are unable to support fast rendering.
|
or driver are unable to support fast rendering.
|
||||||
|
|
||||||
# 26. Realtime applications
|
# 9. Realtime applications
|
||||||
|
|
||||||
Screen refresh is performed in a continuous loop with yields to the scheduler.
|
Screen refresh is performed in a continuous loop with yields to the scheduler.
|
||||||
In normal applications this works well, however a significant proportion of
|
In normal applications this works well, however a significant proportion of
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
# bitmap.py Minimal micro-gui demo.
|
# bitmap.py Display a changing bitmap via the BitMap widget.
|
||||||
|
|
||||||
# Released under the MIT License (MIT). See LICENSE.
|
# Released under the MIT License (MIT). See LICENSE.
|
||||||
# Copyright (c) 2022 Peter Hinch
|
# Copyright (c) 2022 Peter Hinch
|
||||||
|
|
||||||
# hardware_setup must be imported before other modules because of RAM use.
|
# hardware_setup must be imported before other modules because of RAM use.
|
||||||
import gc
|
|
||||||
import uasyncio as asyncio
|
|
||||||
import hardware_setup # Create a display instance
|
import hardware_setup # Create a display instance
|
||||||
from gui.core.ugui import Screen, ssd
|
from gui.core.ugui import Screen, ssd
|
||||||
from gui.widgets import Label, Button, CloseButton, BMG
|
from gui.widgets import Label, Button, CloseButton, BitMap
|
||||||
# Create buffer for bitmapped graphic before fragmentation sets in
|
|
||||||
scale = 1
|
|
||||||
qr_ht = 100
|
|
||||||
qr_wd = 100
|
|
||||||
qr_buf = BMG.make_buffer(qr_ht, qr_wd)
|
|
||||||
gc.collect()
|
|
||||||
from gui.core.writer import CWriter
|
from gui.core.writer import CWriter
|
||||||
import gui.fonts.arial10 as arial10
|
import gui.fonts.arial10 as arial10
|
||||||
from gui.core.colors import *
|
from gui.core.colors import *
|
||||||
|
@ -29,19 +21,21 @@ class BaseScreen(Screen):
|
||||||
col = 2
|
col = 2
|
||||||
row = 2
|
row = 2
|
||||||
Label(wri, row, col, "Bitmap Demo.")
|
Label(wri, row, col, "Bitmap Demo.")
|
||||||
row = 50
|
row = 25
|
||||||
self.graphic = BMG(wri, row, col, qr_ht, qr_wd, scale, fgcolor=WHITE, bgcolor=BLACK, buf=qr_buf)
|
self.graphic = BitMap(wri, row, col, 99, 99, fgcolor=WHITE, bgcolor=BLACK)
|
||||||
#Button(wri, row, col, text="URL", callback=my_callback, args=(graphic, qr))
|
col = 120
|
||||||
asyncio.create_task(self.animate())
|
Button(wri, row, col, text="Next", callback=self.cb)
|
||||||
CloseButton(wri) # Quit the application
|
CloseButton(wri) # Quit the application
|
||||||
|
self.image = 0
|
||||||
|
|
||||||
async def animate(self):
|
def cb(self, _):
|
||||||
while True:
|
self.graphic.value(f"/moon/m{self.image:02d}")
|
||||||
for n in range(13):
|
self.image += 1
|
||||||
fn = f"/moon/m{n}.c"
|
self.image %= 28
|
||||||
#print(fn)
|
if self.image == 3:
|
||||||
await asyncio.sleep_ms(200)
|
self.graphic.color(BLUE)
|
||||||
self.graphic.value(fn)
|
else:
|
||||||
|
self.graphic.color(WHITE)
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
print("Bitmap demo.")
|
print("Bitmap demo.")
|
||||||
|
|
|
@ -8,12 +8,12 @@ import gc
|
||||||
import hardware_setup # Create a display instance
|
import hardware_setup # Create a display instance
|
||||||
from uQR import QRCode
|
from uQR import QRCode
|
||||||
from gui.core.ugui import Screen, ssd
|
from gui.core.ugui import Screen, ssd
|
||||||
from gui.widgets import Label, Button, CloseButton, BMG
|
from gui.widgets import Label, Button, CloseButton, QRMap
|
||||||
# Create buffer for bitmapped graphic before fragmentation sets in
|
# Create buffer for bitmapped graphic before fragmentation sets in
|
||||||
scale = 3 # Magnification of graphic
|
scale = 3 # Magnification of graphic
|
||||||
qr_ht = scale * 41
|
qr_ht = scale * 41
|
||||||
qr_wd = scale *41
|
qr_wd = scale * 41
|
||||||
qr_buf = BMG.make_buffer(qr_ht, qr_wd)
|
qr_buf = QRMap.make_buffer(qr_ht, qr_wd)
|
||||||
gc.collect()
|
gc.collect()
|
||||||
from gui.core.writer import CWriter
|
from gui.core.writer import CWriter
|
||||||
import gui.fonts.arial10 as arial10
|
import gui.fonts.arial10 as arial10
|
||||||
|
@ -35,7 +35,7 @@ class BaseScreen(Screen):
|
||||||
row = 2
|
row = 2
|
||||||
Label(wri, row, col, "QR code Demo.")
|
Label(wri, row, col, "QR code Demo.")
|
||||||
row = 50
|
row = 50
|
||||||
graphic = BMG(wri, row, col, qr_ht, qr_wd, scale, fgcolor=BLACK, bgcolor=WHITE, buf=qr_buf)
|
graphic = QRMap(wri, row, col, (qr_ht, qr_wd), scale, fgcolor=BLACK, bgcolor=WHITE, buf=qr_buf)
|
||||||
qr = QRCode(version=4) # Gives 41x41 matrix
|
qr = QRCode(version=4) # Gives 41x41 matrix
|
||||||
qr.add_data("uQR rocks!")
|
qr.add_data("uQR rocks!")
|
||||||
graphic.value(qr.get_matrix())
|
graphic.value(qr.get_matrix())
|
||||||
|
|
|
@ -23,7 +23,8 @@ _attrs = {
|
||||||
"Slider": "sliders",
|
"Slider": "sliders",
|
||||||
"HorizSlider": "sliders",
|
"HorizSlider": "sliders",
|
||||||
"Textbox": "textbox",
|
"Textbox": "textbox",
|
||||||
"BMG": "bitmap",
|
"BitMap": "bitmap",
|
||||||
|
"QRMap": "qrcode",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Lazy loader, effectively does:
|
# Lazy loader, effectively does:
|
||||||
|
|
|
@ -1,96 +1,49 @@
|
||||||
# bitmap.py Provides the BMG (bitmapped graphics) class
|
# bitmap.py Provides the BMG (bitmapped graphics) class
|
||||||
|
|
||||||
# Released under the MIT License (MIT). See LICENSE.
|
# Released under the MIT License (MIT). See LICENSE.
|
||||||
# Copyright (c) 2022 Peter Hinch
|
# Copyright (c) 2022 Peter Hinch
|
||||||
import gc
|
|
||||||
from framebuf import FrameBuffer, MONO_HLSB
|
# Graphics are files created by Linux bitmap utility.
|
||||||
|
# Widget writes data direct to the FrameBuffer.
|
||||||
|
# There is no scaling: declared size of the widget must exactly
|
||||||
|
# match the size of the bitmap.
|
||||||
|
|
||||||
from gui.core.ugui import Widget
|
from gui.core.ugui import Widget
|
||||||
from gui.core.colors import *
|
from gui.core.colors import *
|
||||||
from gui.core.ugui import ssd
|
from gui.core.ugui import ssd
|
||||||
|
|
||||||
def rbit8(v):
|
|
||||||
v = (v & 0x0f) << 4 | (v & 0xf0) >> 4
|
|
||||||
v = (v & 0x33) << 2 | (v & 0xcc) >> 2
|
|
||||||
return (v & 0x55) << 1 | (v & 0xaa) >> 1
|
|
||||||
|
|
||||||
class BMG(Widget):
|
class BitMap(Widget):
|
||||||
|
|
||||||
@staticmethod
|
def __init__(self, writer, row, col, height, width, *, fgcolor=None, bgcolor=None, bdcolor=RED):
|
||||||
def make_buffer(height, width):
|
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor)
|
||||||
w = (width >> 3) + int(width & 7 > 0)
|
|
||||||
return bytearray(height * w)
|
|
||||||
|
|
||||||
def __init__(self, writer, row, col, height, width, scale=1, *, fgcolor=None, bgcolor=None, bdcolor=RED, buf=None):
|
|
||||||
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, False)
|
|
||||||
if buf is None:
|
|
||||||
buf = BMG.make_buffer(height, width)
|
|
||||||
self._fb = FrameBuffer(buf, width, height, MONO_HLSB)
|
|
||||||
self._scale = scale
|
|
||||||
self._buf = buf
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
if super().show(True): # Draw or erase border
|
if not super().show(True): # Draw or erase border
|
||||||
palette = ssd.palette
|
return
|
||||||
palette.bg(self.bgcolor)
|
if self._value is None:
|
||||||
palette.fg(self.fgcolor)
|
return
|
||||||
ssd.blit(self._fb, self.col, self.row, -1, palette)
|
with open(self._value, "r") as f:
|
||||||
|
g = self.gen_bytes(f)
|
||||||
|
bit = 1
|
||||||
|
wrap = False
|
||||||
|
for row in range(self.height):
|
||||||
|
if not wrap:
|
||||||
|
byte = next(g) # Each row starts on a new byte
|
||||||
|
bit = 1
|
||||||
|
for col in range(self.width):
|
||||||
|
c = self.fgcolor if byte & bit else self.bgcolor
|
||||||
|
ssd.pixel(self.col + col, self.row + row, c)
|
||||||
|
wrap = (bit := bit << 1) == 0x100
|
||||||
|
if wrap:
|
||||||
|
byte = next(g)
|
||||||
|
bit = 1
|
||||||
|
|
||||||
def color(self, fgcolor=None, bgcolor=None):
|
def gen_bytes(self, f): # Yield data bytes from file stream
|
||||||
if fgcolor is not None:
|
f.readline()
|
||||||
self.fgcolor = fgcolor
|
f.readline() # Advance file pointer to data start
|
||||||
if bgcolor is not None:
|
|
||||||
self.bgcolor = bgcolor
|
|
||||||
self.draw = True
|
|
||||||
|
|
||||||
def value(self, obj):
|
|
||||||
if isinstance(obj, list): # 2d list of booleans
|
|
||||||
self._fb.fill(1)
|
|
||||||
s = self._scale
|
|
||||||
wd = len(obj[0])
|
|
||||||
ht = len(obj)
|
|
||||||
if wd * s > self.width or ht * s > self.height:
|
|
||||||
print('Object too large for buffer', wd * s, self.width, ht * s, self.height)
|
|
||||||
else:
|
|
||||||
print(f"Object is {wd} x {ht}")
|
|
||||||
for row in range(ht):
|
|
||||||
for col in range(wd):
|
|
||||||
v = obj[row][col]
|
|
||||||
for nc in range(s):
|
|
||||||
for nr in range(s):
|
|
||||||
self._fb.pixel(col * s + nc, row * s + nr, v)
|
|
||||||
elif isinstance(obj, str): # Assume filename
|
|
||||||
try:
|
|
||||||
with open(obj, "r") as f:
|
|
||||||
g = self.handle_stream(f)
|
|
||||||
n = 0
|
|
||||||
for x in g:
|
|
||||||
self._buf[n] = rbit8(x)
|
|
||||||
n += 1
|
|
||||||
except OSError:
|
|
||||||
print(f"Failed to input from {obj}")
|
|
||||||
self.draw = True
|
|
||||||
gc.collect()
|
|
||||||
# TODO graphic must be exactly the right size. Get dims from file in app, pass stream?
|
|
||||||
def handle_stream(self, f):
|
|
||||||
m = self._scale
|
|
||||||
s = f.readline()
|
|
||||||
elements = s.split(" ")
|
|
||||||
if elements[1].endswith("width"):
|
|
||||||
wd = int(elements[2])
|
|
||||||
else:
|
|
||||||
raise OSError
|
|
||||||
s = f.readline()
|
|
||||||
elements = s.split(" ")
|
|
||||||
if elements[1].endswith("height"):
|
|
||||||
ht = int(elements[2])
|
|
||||||
else:
|
|
||||||
raise OSError
|
|
||||||
if wd * m > self.width or ht * m > self.height:
|
|
||||||
print("Object too large for buffer", wd * m, self.width, ht * m, self.height)
|
|
||||||
raise OSError
|
|
||||||
s = f.readline()
|
s = f.readline()
|
||||||
if not s.startswith("static"):
|
if not s.startswith("static"):
|
||||||
raise OSError
|
raise ValueError("Bad file format.")
|
||||||
while s := f.readline():
|
while s := f.readline():
|
||||||
if (lb := s.find("}")) != -1:
|
if (lb := s.find("}")) != -1:
|
||||||
s = s[:lb] # Strip trailing };
|
s = s[:lb] # Strip trailing };
|
||||||
|
@ -98,3 +51,31 @@ class BMG(Widget):
|
||||||
for x in p:
|
for x in p:
|
||||||
if x:
|
if x:
|
||||||
yield int(x, 16)
|
yield int(x, 16)
|
||||||
|
|
||||||
|
# Get height/width dimension from file stream.
|
||||||
|
def _get_dim(self, f, name):
|
||||||
|
s = f.readline()
|
||||||
|
elements = s.split(" ")
|
||||||
|
if not elements[1].endswith(name):
|
||||||
|
raise ValueError("Bad file format.")
|
||||||
|
return int(elements[2])
|
||||||
|
|
||||||
|
def _validate(self, fn):
|
||||||
|
if not isinstance(fn, str):
|
||||||
|
raise ValueError("Value must be a filename.")
|
||||||
|
with open(fn, "r") as f:
|
||||||
|
wd = self._get_dim(f, "width")
|
||||||
|
ht = self._get_dim(f, "height")
|
||||||
|
if not (wd == self.width and ht == self.height):
|
||||||
|
raise ValueError(f"Object dimensions {ht}x{wd} do not match widget {self.height}x{self.width}")
|
||||||
|
|
||||||
|
def value(self, fn):
|
||||||
|
self._validate(fn) # Throws on failure
|
||||||
|
super().value(fn)
|
||||||
|
|
||||||
|
def color(self, fgcolor=None, bgcolor=None):
|
||||||
|
if fgcolor is not None:
|
||||||
|
self.fgcolor = fgcolor
|
||||||
|
if bgcolor is not None:
|
||||||
|
self.bgcolor = bgcolor
|
||||||
|
self.draw = True
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
# qrcode.py Provides the QRMap widget to display the output of uQR library.
|
||||||
|
|
||||||
|
# Released under the MIT License (MIT). See LICENSE.
|
||||||
|
# Copyright (c) 2022 Peter Hinch
|
||||||
|
import gc
|
||||||
|
from framebuf import FrameBuffer, MONO_HLSB
|
||||||
|
from gui.core.ugui import Widget
|
||||||
|
from gui.core.colors import *
|
||||||
|
from gui.core.ugui import ssd
|
||||||
|
|
||||||
|
|
||||||
|
class QRMap(Widget):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def make_buffer(height, width): # Given dimensions in pixels
|
||||||
|
w = (width >> 3) + int(width & 7 > 0)
|
||||||
|
return bytearray(height * w)
|
||||||
|
|
||||||
|
def __init__(self, writer, row, col, image, scale=1, *, fgcolor=None, bgcolor=None, bdcolor=RED, buf=None):
|
||||||
|
self._scale = scale
|
||||||
|
self._image = image
|
||||||
|
try:
|
||||||
|
height, width = self.dimensions()
|
||||||
|
except OSError:
|
||||||
|
print(f"Failed to access {obj}.")
|
||||||
|
raise
|
||||||
|
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, False)
|
||||||
|
if buf is None:
|
||||||
|
buf = QRMap.make_buffer(height, width)
|
||||||
|
else:
|
||||||
|
if len(buf) != ((width >> 3) + int(width & 7 > 0)) * height:
|
||||||
|
raise OSError("Buffer size does not match width and height.")
|
||||||
|
self._fb = FrameBuffer(buf, width, height, MONO_HLSB)
|
||||||
|
if isinstance(image, list):
|
||||||
|
self.value(image)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
if super().show(True): # Draw or erase border
|
||||||
|
palette = ssd.palette
|
||||||
|
palette.bg(self.bgcolor)
|
||||||
|
palette.fg(self.fgcolor)
|
||||||
|
ssd.blit(self._fb, self.col, self.row, -1, palette)
|
||||||
|
|
||||||
|
def color(self, fgcolor=None, bgcolor=None):
|
||||||
|
if fgcolor is not None:
|
||||||
|
self.fgcolor = fgcolor
|
||||||
|
if bgcolor is not None:
|
||||||
|
self.bgcolor = bgcolor
|
||||||
|
self.draw = True
|
||||||
|
|
||||||
|
def dimensions(self): # Dimensions of current image in pixels
|
||||||
|
obj = self._image
|
||||||
|
if isinstance(obj, list): # 2d list of booleans
|
||||||
|
return len(obj) * self._scale, len(obj[0] * self._scale)
|
||||||
|
if isinstance(obj, tuple):
|
||||||
|
return obj
|
||||||
|
raise OSError
|
||||||
|
|
||||||
|
def value(self, obj):
|
||||||
|
self._image = obj
|
||||||
|
self._fb.fill(self.bgcolor) # In case tuple was passed or image smaller than buffer
|
||||||
|
if isinstance(obj, list): # 2d list of booleans
|
||||||
|
wd, ht = self.dimensions()
|
||||||
|
s = self._scale
|
||||||
|
if wd > self.width or ht > self.height:
|
||||||
|
print('Object too large for buffer', wd, self.width, ht, self.height)
|
||||||
|
else:
|
||||||
|
print(f"Object is {wd} x {ht} pixels")
|
||||||
|
for row in range(ht//s):
|
||||||
|
for col in range(wd//s):
|
||||||
|
v = obj[row][col]
|
||||||
|
for nc in range(s):
|
||||||
|
for nr in range(s):
|
||||||
|
self._fb.pixel(col * s + nc, row * s + nr, v)
|
||||||
|
else:
|
||||||
|
print(f"Invalid QR code {obj}.")
|
||||||
|
self.draw = True
|
||||||
|
gc.collect()
|
Ładowanie…
Reference in New Issue