Porównaj commity

...

2 Commity

Autor SHA1 Wiadomość Data
peterhinch 310957e518 Fix epaper demo initial refresh. 2023-06-01 12:16:35 +01:00
peterhinch d886989f7e Simplfy calendar demo. Fix Label where text is None. 2023-06-01 08:48:52 +01:00
5 zmienionych plików z 65 dodań i 67 usunięć

Wyświetl plik

@ -3090,26 +3090,40 @@ connecting to any host. The hardware_setup.py should be copied or adapted from
`setup_examples/pico_epaper_42_pico.py`. If using the socket, default args may `setup_examples/pico_epaper_42_pico.py`. If using the socket, default args may
be used (see code comment). be used (see code comment).
After an initial refresh to clear the screen the driver is put into partial Some attention to detail is required to handle the refresh characteristics.
mode. This provides a reasonably quick and visually satisfactory response to The application must wait for the initial full refresh (which occurs
user inputs such as button events. See the automatically) before putting the display into partial mode. This is done by
the screen constructor issuing
```python
asyncio.create_task(set_partial())
```
to run
```python
async def set_partial(): # Ensure 1st refresh is a full refresh
await Screen.rfsh_done.wait() # Wait for first refresh to end
ssd.set_partial()
```
The application then runs in partial mode with a reasonably quick and visually
satisfactory response to user inputs such as button events. See the
[epaper demo](https://github.com/peterhinch/micropython-micro-gui/blob/main/gui/demos/epaper.py). [epaper demo](https://github.com/peterhinch/micropython-micro-gui/blob/main/gui/demos/epaper.py).
This provides for a full refresh via the `reset` button. Provision of full
refresh is application dependent. It should be done as follows:
It is likely that applications will provide a full refresh method to clear any
ghosting. The demo provides for a full refresh via the `reset` button. A full
refresh should be done as follows:
```python ```python
async def full_refresh(): async def full_refresh():
Screen.rfsh_done.clear() # Enable completion flag Screen.rfsh_done.clear() # Enable completion flag
await Screen.rfsh_done.wait() # Wait for a refresh to end await Screen.rfsh_done.wait() # Wait for a refresh to end
ssd.set_full() ssd.set_full()
Screen.rfsh_done.clear() # Enable completion flag Screen.rfsh_done.clear() # Re-enable completion flag
await Screen.rfsh_done.wait() # Wait for a single full refresh to end await Screen.rfsh_done.wait() # Wait for a single full refresh to end
ssd.set_partial() ssd.set_partial() # Subsequent refreshes are partial
``` ```
The driver for the supported display uses 1-bit color mapping: this means that The driver for the supported display uses 1-bit color mapping: this means that
greying-out has no visible effect. Greyed-out controls cannot accept the focus greying-out has no visible effect. Greyed-out controls cannot accept the focus
and are therefore disabled but appearance is unchanged. and are therefore disabled but appearance is unchanged. `nano-gui` has a 2-bit
driver which supports greyscales, but there is no partial support so this is
unsuitable for `micro_gui`.
###### [Contents](./README.md#0-contents) ###### [Contents](./README.md#0-contents)

Wyświetl plik

@ -28,6 +28,8 @@ class BaseScreen(Screen):
row = 2 row = 2
rows = 6 rows = 6
cols = 7 cols = 7
self.ncells = cols * (rows - 1) # Row 0 has day labels
self.last_cell = cols * rows
colwidth = 35 colwidth = 35
self.lbl = Label(wri, row, col, text = (colwidth + 4) * cols, justify=Label.CENTRE) self.lbl = Label(wri, row, col, text = (colwidth + 4) * cols, justify=Label.CENTRE)
row = self.lbl.mrow row = self.lbl.mrow
@ -72,49 +74,28 @@ class BaseScreen(Screen):
d.now() d.now()
self.update() self.update()
def update(self): def days(self, month_length): # Produce content for every cell
def cell(): for n in range(self.ncells + 1):
if cur.year == today.year and cur.month == today.month and mday == today.mday: # Today yield str(n + 1) if n < month_length else ""
d["fgcolor"] = RED
elif mday == cur.mday: # Currency
d["fgcolor"] = YELLOW
elif mday in sundays:
d["fgcolor"] = BLUE
else:
d["fgcolor"] = GREEN
d["text"] = str(mday)
self.grid[idx] = d
today = DateCal() def update(self):
grid = self.grid
cur = self.date # Currency cur = self.date # Currency
self.lbl.value(f"{DateCal.months[cur.month - 1]} {cur.year}") self.lbl.value(f"{DateCal.months[cur.month - 1]} {cur.year}")
d = {} # Args for Label.value # Populate day number cells
wday = 0 values = self.days(cur.month_length) # Instantiate generator
wday_1 = cur.wday_n(1) # Weekday of 1st of month idx_1 = 7 + cur.wday_n(1) # Index of 1st of month
mday = 1 grid[idx_1 : self.last_cell] = values # Populate from mday 1 to last cell
seek = True grid[7 : idx_1] = values # Populate cells before 1st of month
sundays = cur.mday_list(6) # Color cells of Sunday, today and currency. In collisions (e.g. today==Sun)
for idx in range(7, self.grid.ncells): # last color applied is effective
if seek: # Find column for 1st of month grid[1:6, 6] = {"fgcolor": BLUE} # Sunday color
if wday < wday_1: grid[idx_1 + cur.mday - 1] = {"fgcolor": YELLOW} # Currency
self.grid[idx] = "" today = DateCal()
wday += 1 if cur.year == today.year and cur.month == today.month: # Today is in current month
else: grid[idx_1 + today.mday - 1] = {"fgcolor": RED}
seek = False
if not seek:
if mday <= cur.month_length:
cell()
mday += 1
else:
self.grid[idx] = ""
idx = 7 # Where another row would be needed, roll over to top few cells.
while mday <= cur.month_length:
cell()
idx += 1
mday += 1
self.lblnow.value(f"{today.day_str} {today.mday} {today.month_str} {today.year}") self.lblnow.value(f"{today.day_str} {today.mday} {today.month_str} {today.year}")
def test(): def test():
print('Calendar demo.') print('Calendar demo.')
Screen.change(BaseScreen) # A class is passed here, not an instance. Screen.change(BaseScreen) # A class is passed here, not an instance.

Wyświetl plik

@ -47,6 +47,9 @@ async def full_refresh():
await Screen.rfsh_done.wait() # Wait for a single full refresh to end await Screen.rfsh_done.wait() # Wait for a single full refresh to end
ssd.set_partial() ssd.set_partial()
async def set_partial(): # Ensure 1st refresh is a full refresh
await Screen.rfsh_done.wait() # Wait for first refresh to end
ssd.set_partial()
class FooScreen(Screen): class FooScreen(Screen):
def __init__(self): def __init__(self):
@ -161,6 +164,7 @@ class FooScreen(Screen):
Label(wri_large, lbl.mrow + 5, col, "y = sinc(x)") Label(wri_large, lbl.mrow + 5, col, "y = sinc(x)")
CloseButton(wri, bgcolor=BLACK) CloseButton(wri, bgcolor=BLACK)
asyncio.create_task(set_partial()) # After 1st full refresh
asyncio.create_task(run(dial, lbltim, m0, scale)) asyncio.create_task(run(dial, lbltim, m0, scale))
def callback(self, button, buttons, val): def callback(self, button, buttons, val):
@ -186,7 +190,6 @@ class FooScreen(Screen):
x += 0.05 x += 0.05
Curve(self.graph, None, populate()) Curve(self.graph, None, populate())
asyncio.create_task(full_refresh())
async def run(dial, lbltim, m0, scale): async def run(dial, lbltim, m0, scale):

Wyświetl plik

@ -28,24 +28,25 @@ class Label(Widget):
self.value(text, invert) self.value(text, invert)
def value(self, text=None, invert=False, fgcolor=None, bgcolor=None, bdcolor=None, justify=None): def value(self, text=None, invert=False, fgcolor=None, bgcolor=None, bdcolor=None, justify=None):
sl = self.writer.stringlen(text) if text is not None:
if justify is None: sl = self.writer.stringlen(text)
justify = self.justify if justify is None:
self.tcol = self.col # Default is left justify justify = self.justify
if sl > self.width: # Clip self.tcol = self.col # Default is left justify
font = self.writer.font if sl > self.width: # Clip
pos = 0 font = self.writer.font
n = 0 pos = 0
for ch in text: n = 0
pos += font.get_ch(ch)[2] # width of current char for ch in text:
if pos > self.width: pos += font.get_ch(ch)[2] # width of current char
break if pos > self.width:
n += 1 break
text = text[: n] n += 1
elif justify == 1: # Centre text = text[: n]
self.tcol = self.col + (self.width - sl) // 2 elif justify == 1: # Centre
elif justify == 2: # Right self.tcol = self.col + (self.width - sl) // 2
self.tcol = self.col + self.width - sl elif justify == 2: # Right
self.tcol = self.col + self.width - sl
txt = super().value(text) txt = super().value(text)
self.draw = True # Redraw unconditionally: colors may have changed. self.draw = True # Redraw unconditionally: colors may have changed.

Wyświetl plik

@ -56,4 +56,3 @@ decrease = Pin(17, Pin.IN, Pin.PULL_UP) # Decrease control's value
# display = Display(ssd, nxt, sel, prev) # 3-button mode # display = Display(ssd, nxt, sel, prev) # 3-button mode
display = Display(ssd, nxt, sel, prev, increase, decrease) # 5-button mode display = Display(ssd, nxt, sel, prev, increase, decrease) # 5-button mode
ssd.wait_until_ready() # Blocking wait ssd.wait_until_ready() # Blocking wait
ssd.set_partial() # Subsequent refreshes are partial