Improve greying out of scale classes.

pull/8/head
Peter Hinch 2021-06-11 15:33:05 +01:00
rodzic 4aeaee5312
commit 8001e16aa0
7 zmienionych plików z 79 dodań i 28 usunięć

Wyświetl plik

@ -1798,4 +1798,42 @@ variable.
## 23.2 Use of graphics primitives
(ssd and display objects)
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 issues the display driver calls.
The following code instantiates two classes:
```python
from hardware_setup import display, ssd
```
The `ssd` object is an instance of the object defined in the display driver. It
is a requirement that this is a subclass of `framebuf.FrameBuffer`. Hence `ssd`
supports all the graphics primitives provided by `FrameBuffer`. These may be
used to draw on the `Screen`.
The `display` object has an `ssd` bound variable which is a reference to the
`ssd` device. The `display` has methods with the same names and args as those
of `ssd`. These support greying out. So you can write (for example)
```python
display.rect(10, 10, 50, 50, RED)
```
To render in the correct colors it is wise ensure that greying out is disabled
prior to calling `display` methods. This is done with
```python
display.usegrey(False)
```
There is little point in issuing `display.rect` as it confers no advantage over
`ssd.rect`. However the `Display` class adds methods not currently available in
`framebuf`. These are listed below.
* `circle(self, x0, y0, r, color, width =1)` Width specifies the line width.
* `fillcircle(self, x0, y0, r, color)`
* `clip_rect(self, x, y, w, h, color)` Rectangle with clipped corners.
* `fill_clip_rect(self, x, y, w, h, color)`
* `print_left(self, writer, x, y, txt, fgcolor=None, bgcolor=None, invert=False)`
* `print_centred(self, writer, x, y, text, fgcolor=None, bgcolor=None, invert=False)`
Hopefully these are self explanatory. The `Display` methods use the `framebuf`
convention of `x, y` coordinates rather than the `row, col` system used by
micro-gui.

Wyświetl plik

@ -65,15 +65,19 @@ class Display:
self._down.close_func(self.do_down)
self._is_grey = False # Not greyed-out
def print_centred(self, writer, x, y, text, fgcolor=None, bgcolor=None):
def print_centred(self, writer, x, y, text, fgcolor=None, bgcolor=None, invert=False):
sl = writer.stringlen(text)
writer.set_textpos(ssd, y - writer.height // 2, x - sl // 2)
if self._is_grey:
fgcolor = GREY
writer.setcolor(fgcolor, bgcolor)
writer.printstring(text)
writer.printstring(text, invert)
writer.setcolor() # Restore defaults
def print_left(self, writer, x, y, txt, fgcolor=None, bgcolor=None, invert=False):
writer.set_textpos(ssd, y, x)
if self._is_grey:
fgcolor = GREY
writer.setcolor(fgcolor, bgcolor)
writer.printstring(txt, invert)
writer.setcolor() # Restore defaults
@ -230,7 +234,6 @@ class Screen:
def show(cls, force):
for obj in cls.current_screen.displaylist:
if obj.visible: # In a buttonlist only show visible button
# pend signals an obect with changed contents
if force or obj.draw:
obj.draw_border()
obj.show()

Wyświetl plik

@ -48,7 +48,7 @@ class CartesianScreen(Screen):
self.g = CartesianGraph(wri, 2, 2, yorigin = 2, fgcolor=GREEN,
gridcolor=LIGHTGREEN) # Asymmetric y axis
Label(wri, 100, 2, 'Asymmetric axes.')
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
# At this point in time the Screen and graph have been constructed but
# not rendered. If we drew the curves now they would be overwritten by
@ -76,7 +76,7 @@ class PolarScreen(Screen):
def __init__(self):
super().__init__()
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
def after_open(self): # After graph has been drawn
@ -94,7 +94,7 @@ class Lissajous(Screen):
super().__init__()
self.g = CartesianGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
Label(wri, 100, 2, 'Lissajous figure.')
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
def after_open(self): # After graph has been drawn
@ -111,7 +111,7 @@ class Lemniscate(Screen):
super().__init__()
self.g = CartesianGraph(wri, 2, 2, height = 75, fgcolor=GREEN, gridcolor=LIGHTGREEN)
Label(wri, 82, 2, 'To infinity and beyond...')
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
def after_open(self): # After graph has been drawn
@ -130,7 +130,7 @@ class PolarClip(Screen):
super().__init__()
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
Label(wri, 100, 2, 'Clipping of polar data.')
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
def after_open(self): # After graph has been drawn
@ -148,7 +148,7 @@ class RTPolar(Screen):
super().__init__()
self.g = PolarGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
Label(wri, 100, 2, 'Realtime polar data.')
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
def after_open(self): # After graph has been drawn
@ -168,7 +168,7 @@ class RTRect(Screen):
super().__init__()
self.g = CartesianGraph(wri, 2, 2, fgcolor=GREEN, gridcolor=LIGHTGREEN)
Label(wri, 100, 2, 'Realtime discontinuous data.')
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
def after_open(self): # After graph has been drawn
@ -198,7 +198,7 @@ class TSeq(Screen):
self.g = CartesianGraph(wri, 2, 2, xorigin = 10, fgcolor=GREEN,
gridcolor=LIGHTGREEN, bdcolor=False)
Label(wri, 100, 2, 'Time sequence.')
fwdbutton(wri, 2, 130, EmptyScreen, 'Forward', GREEN)
fwdbutton(wri, 30, 130, EmptyScreen, 'Forward', GREEN)
CloseButton(wri)
def after_open(self): # After graph has been drawn
@ -241,8 +241,8 @@ class BaseScreen(Screen):
Screen.change(d[lb.textvalue()])
def test():
if display.height < 240 or display.width < 320:
print(' This test requires a display of at least 320x240 pixels.')
if display.height < 128 or display.width < 200:
print(' This test requires a display of at least 128x200 pixels.')
else:
print('Testing micro-gui...')
Screen.change(BaseScreen)

Wyświetl plik

@ -53,15 +53,18 @@ class FooScreen(Screen):
self.rb0 = None
self.bs0 = None
wri = CWriter(ssd, arial10, GREEN, BLACK, verbose=False)
lbltim = Label(wri, 50, 85, 'this is a test', bdcolor=RED)
lbltim = Label(wri, 65, 100, 'this is a test', bdcolor=RED)
m0 = Meter(wri, 20, 240, divisions = 4, ptcolor=YELLOW,
label='left', style=Meter.LINE, legends=('0.0', '0.5', '1.0'))
m0 = Meter(wri, 10, 240, divisions = 4, ptcolor=YELLOW, height=80, width=15,
label='Meter example', style=Meter.BAR, legends=('0.0', '0.5', '1.0'))
# Instantiate displayable objects. bgcolor forces complete redraw.
dial = Dial(wri, 2, 2, height = 75, ticks = 12, bgcolor=BLACK, bdcolor=None, label=120) # Border in fg color
scale = Scale(wri, 2, 100, width = 124, tickcb = tickcb,
pointercolor=RED, fontcolor=YELLOW, bdcolor=CYAN)
row = 105
col = 2
Label(wri, row, col, 'Normal buttons')
# Four Button instances
row = 120
ht = 30
@ -73,8 +76,9 @@ class FooScreen(Screen):
self.bs = ButtonList(self.callback)
self.bs0 = None
col+= 50
Label(wri, row - 15, col, 'ButtonList')
for t in table_buttonset: # Buttons overlay each other at same location
button = self.bs.add_button(wri, 120, col, shape=RECTANGLE, textcolor=BLUE, height=30, **t)
button = self.bs.add_button(wri, row, col, shape=RECTANGLE, textcolor=BLUE, height=30, **t)
if self.bs0 is None: # Save for reset button callback
self.bs0 = button
@ -82,21 +86,25 @@ class FooScreen(Screen):
col+= 60
btn = Button(wri, row, col, height=30, callback=self.rstcb, text='reset', litcolor=RED, fgcolor=GREEN, bgcolor=DARKGREEN)
col = 2
row = 170
Label(wri, row, col, 'Radio buttons')
# Radio buttons
col= 2
row = 185
self.rb = RadioButtons(BLUE, self.rbcb) # color of selected button
self.rb0 = None
for t in table_radiobuttons:
button = self.rb.add_button(wri, 160, col, textcolor = WHITE,
button = self.rb.add_button(wri, row, col, textcolor = WHITE,
fgcolor = BLUE, bgcolor = DARKBLUE, shape=CIRCLE, height = 30, **t)
if self.rb0 is None: # Save for reset button callback
self.rb0 = button
col+= 35
# Checkbox
col+= 35
Checkbox(wri, 160, col, callback=self.cbcb)
Label(wri, row - 15, col, 'Checkbox and LED')
Checkbox(wri, row, col, callback=self.cbcb)
col+= 40
self.led = LED(wri, 160, col, color=YELLOW, bdcolor=GREEN)
self.led = LED(wri, row, col, color=YELLOW, bdcolor=GREEN)
CloseButton(wri)
asyncio.create_task(run(dial, lbltim, m0, scale))
@ -109,7 +117,7 @@ class FooScreen(Screen):
def rstcb(self, button):
print('Reset button: init ButtonList and RadioButtons')
self.bs.value(self.bs0) # BUG This is calling ButtonList.value which calls ._update -> Screen.select which changes currency
self.bs.value(self.bs0)
self.rb.value(self.rb0)
def cbcb(self, cb):

Wyświetl plik

@ -1,7 +1,7 @@
# meter.py Extension to ugui providing a linear "meter" widget.
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2019 Peter Hinch
# Copyright (c) 2021 Peter Hinch
from gui.core.ugui import Widget, display
from gui.widgets.label import Label

Wyświetl plik

@ -9,7 +9,7 @@
from gui.core.ugui import LinearIO, display
from hardware_setup import ssd # Display driver for Writer
from gui.core.writer import Writer
from gui.core.colors import BLACK
from gui.core.colors import *
dolittle = lambda *_ : None
@ -84,6 +84,7 @@ class Scale(LinearIO):
# So pixels per unit value == win_width/200
win_width: int = x1 - x0
ticks: int = self.ticks # Total # of ticks visible and hidden
txtcolor = GREY if self.greyed_out() else self.fontcolor
while True:
x: int = x0 + (fx * win_width) // 200 # Current X position
ys: int # Start Y position for tick
@ -94,7 +95,7 @@ class Scale(LinearIO):
txt = self.legendcb(self._fvalue(iv * 10))
tlen = wri.stringlen(txt)
Writer.set_textpos(ssd, y0, min(x, x1 - tlen))
wri.setcolor(self.fontcolor, self.bgcolor)
wri.setcolor(txtcolor, self.bgcolor)
wri.printstring(txt)
wri.setcolor()
ys = self.ldy0 # Large tick

Wyświetl plik

@ -15,7 +15,7 @@ from math import log10
from gui.core.ugui import LinearIO, display
from hardware_setup import ssd # Display driver for Writer
from gui.core.writer import Writer
from gui.core.colors import BLACK
from gui.core.colors import *
# Null function
dolittle = lambda *_ : None
@ -86,6 +86,7 @@ class ScaleLog(LinearIO):
vc = self._value # Current value, corresponds to centre of display
d = int(log10(vc)) - 1 # 10**d is start of a decade guaranteed to be outside display
vs = max(10 ** d, 1.0) # vs: start value of current decade
txtcolor = GREY if self.greyed_out() else self.fontcolor
while True: # For each decade until we run out of space
done = True # Assume completion
xs: float = xc - dw * log10(vc / vs) # x location of start of scale
@ -102,7 +103,7 @@ class ScaleLog(LinearIO):
txt = self.legendcb(vt)
tlen = wri.stringlen(txt)
Writer.set_textpos(ssd, y0, min(x, x1 - tlen))
wri.setcolor(self.fontcolor, self.bgcolor)
wri.setcolor(txtcolor, self.bgcolor)
wri.printstring(txt)
ys = self.ldy0 # Large tick
yl = self.ldl