kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
Prior to listbox refactor.
rodzic
a9b0e90968
commit
70c0ea248e
15
README.md
15
README.md
|
@ -1256,7 +1256,7 @@ Constructor mandatory positional args:
|
|||
|
||||
Mandatory keyword only argument:
|
||||
* `elements` A list or tuple of strings to display. Must have at least one
|
||||
entry.
|
||||
entry. See below for an alternative way to use the `Dropdown`.
|
||||
|
||||
Optional keyword only arguments:
|
||||
* `width=None` Control width in pixels. By default this is calculated to
|
||||
|
@ -1298,6 +1298,19 @@ 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
|
||||
means of the instance's `value` or `textvalue` methods.
|
||||
|
||||
#### Alternative approach
|
||||
|
||||
By default the `Dropdown` runs a single callback regardless of the element
|
||||
chosen. This can be changed by specifying `elements` such that each element
|
||||
comprises a 3-list or 3-tuple with the following contents:
|
||||
0. String to display.
|
||||
1. Callback.
|
||||
2. Tuple of args (may be ()).
|
||||
|
||||
In this case constructor args `callback` and `args` must not be supplied. Args
|
||||
received by the callback functions comprise the `Dropdown` instance followed by
|
||||
any supplied args.
|
||||
|
||||
###### [Contents](./README.md#0-contents)
|
||||
|
||||
# 14. DialogBox class
|
||||
|
|
|
@ -5,34 +5,40 @@
|
|||
|
||||
import hardware_setup # Create a display instance
|
||||
from gui.core.ugui import Screen, ssd
|
||||
import gui.fonts.freesans20 as freesans20
|
||||
import gui.fonts.freesans20 as font
|
||||
from gui.core.writer import CWriter
|
||||
|
||||
from gui.widgets.menu import Menu
|
||||
from gui.widgets.buttons import CloseButton
|
||||
from gui.core.colors import *
|
||||
from gui.widgets.dialog import DialogBox
|
||||
|
||||
class BaseScreen(Screen):
|
||||
|
||||
def __init__(self):
|
||||
def cb(button, n):
|
||||
print('Top level callback', n)
|
||||
print('Help callback', n)
|
||||
|
||||
def cb_sm(lb, n):
|
||||
kwargs = {'writer' : wri, 'row': 60, 'col' : 2,
|
||||
'elements' : (('Yes', GREEN), ('No', RED), ('Foo', YELLOW)),
|
||||
'label' : 'Test dialog',
|
||||
}
|
||||
print('Submenu callback', lb.value(), lb.textvalue(), n)
|
||||
if lb.value() == 0:
|
||||
Screen.change(DialogBox, kwargs = kwargs)
|
||||
|
||||
super().__init__()
|
||||
mnu = (('Gas', cb_sm, (0,), ('Helium','Neon','Argon','Krypton','Xenon','Radon')),
|
||||
('Metal', cb_sm, (1,), ('Lithium', 'Sodium', 'Potassium','Rubidium','Caesium')),
|
||||
('View', cb, (2,)))
|
||||
wri = CWriter(ssd, freesans20, GREEN, BLACK, verbose=False)
|
||||
mnu = (('Gas', (('Helium', cb_sm, (0,)),
|
||||
('Neon', cb_sm, (1,)),
|
||||
('Argon', cb_sm, (2,)),
|
||||
('Krypton', cb_sm, (3,)),
|
||||
('Xenon', cb_sm, (4,)),
|
||||
('Radon', cb_sm, (5,)))),
|
||||
('Metal',(('Lithium', cb_sm, (6,)),
|
||||
('Sodium', cb_sm, (7,)),
|
||||
('Potassium', cb_sm, (8,)),
|
||||
('Rubidium', cb_sm, (9,)),
|
||||
('More', (('Gold', cb_sm, (6,)),
|
||||
('Silver', cb_sm, (7,)),
|
||||
('Iron', cb_sm, (8,)),
|
||||
('Zinc', cb_sm, (9,)),
|
||||
('Copper', cb_sm, (10,)))))),
|
||||
('Help', cb, (2,)))
|
||||
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
|
||||
Menu(wri, bgcolor=BLUE, textcolor=WHITE, args = mnu)
|
||||
CloseButton(wri)
|
||||
|
||||
|
|
|
@ -41,6 +41,15 @@ class Dropdown(Widget):
|
|||
|
||||
self.entry_height = writer.height + 2 # Allow a pixel above and below text
|
||||
height = self.entry_height
|
||||
e0 = elements[0]
|
||||
# Check whether elements specified as (str, str,...) or ([str, callback, args], [...)
|
||||
if isinstance(e0, tuple) or isinstance(e0, list):
|
||||
te = [x[0] for x in elements] # Copy text component
|
||||
self.els = elements # Retain original
|
||||
elements = te
|
||||
if callback is not dolittle:
|
||||
raise ValueError('Cannot specify callback.')
|
||||
callback = self._despatch
|
||||
if width is None: # Allow for square at end for arrow
|
||||
self.textwidth = max(writer.stringlen(s) for s in elements)
|
||||
width = self.textwidth + 2 + height
|
||||
|
@ -88,3 +97,7 @@ class Dropdown(Widget):
|
|||
if len(self.elements) > 1:
|
||||
args = (self.writer, self.row - 2, self.col - 2, self)
|
||||
Screen.change(_ListDialog, args = args)
|
||||
|
||||
def _despatch(self, _): # Run the callback specified in elements
|
||||
x = self.els[self.value()]
|
||||
x[1](self, *x[2])
|
||||
|
|
|
@ -16,35 +16,45 @@ from gui.core.colors import *
|
|||
# handled by Screen .move bound method
|
||||
class SubMenu(Window):
|
||||
|
||||
def __init__(self, menu, button, elements, cb, args): # menu is parent Menu
|
||||
def __init__(self, menu, button, elements): # menu is parent Menu
|
||||
self.menu = menu
|
||||
self.button = button
|
||||
wri = menu.writer
|
||||
row = button.height + 2
|
||||
col = button.col # Drop down below top level menu button
|
||||
# Need to determine Window dimensions from size of Listbox, which
|
||||
# depends on number and length of elements.
|
||||
entry_height, lb_height, textwidth = Listbox.dimensions(wri, elements)
|
||||
te = [x[0] for x in elements] # Text part
|
||||
self.elements = elements
|
||||
entry_height, lb_height, textwidth = Listbox.dimensions(wri, te)
|
||||
lb_width = textwidth + 2
|
||||
# Calculate Window dimensions
|
||||
ap_height = lb_height + 6 # Allow for listbox border
|
||||
ap_width = lb_width + 6
|
||||
super().__init__(row, col, ap_height, ap_width)
|
||||
self.listbox = Listbox(wri, row + 3, col + 3, elements = elements, width = lb_width,
|
||||
fgcolor = button.fgcolor, bgcolor = button.bgcolor, bdcolor=False,
|
||||
fontcolor = button.textcolor, select_color = menu.select_color,
|
||||
callback = self.callback)
|
||||
self.cb = cb
|
||||
self.args = args
|
||||
Listbox(wri, row + 3, col + 3, elements = te, width = lb_width,
|
||||
fgcolor = button.fgcolor, bgcolor = button.bgcolor, bdcolor=False,
|
||||
fontcolor = button.textcolor, select_color = menu.select_color,
|
||||
callback = self.callback)
|
||||
|
||||
def callback(self, obj_listbox):
|
||||
def callback(self, lbox):
|
||||
Screen.back()
|
||||
self.cb(obj_listbox, *self.args) # CB can access obj_listbox.value() or .textvalue()
|
||||
el = self.elements[lbox.value()] # (text, cb, args)
|
||||
if len(el) == 2: # Recurse into submenu
|
||||
args = (self.menu, self.button, el[1])
|
||||
Screen.change(SubMenu, args = args)
|
||||
else:
|
||||
el[1](lbox, *el[2])
|
||||
|
||||
# A Menu is a set of Button objects at the top of the screen. On press, Buttons either run the
|
||||
# user callback or instantiate a SubMenu
|
||||
# args: ((text, cb, (args,)),(text, cb, (args,), (elements,)), ...)
|
||||
# args is a list comprising items which may be a mixture of two types
|
||||
# Single items: (top_text, cb, (args, ...))
|
||||
# Submenus: (top_text, ((mnu_text, cb, (args, ...)),(mnu_text, cb, (args, ...)),...)
|
||||
class Menu:
|
||||
|
||||
def __init__(self, writer, *, height=25, bgcolor=None, fgcolor=None, textcolor=None, select_color=DARKBLUE, args):
|
||||
def __init__(self, writer, *, height=25, bgcolor=None, fgcolor=None,
|
||||
textcolor=None, select_color=DARKBLUE, args):
|
||||
self.writer = writer
|
||||
self.select_color = select_color
|
||||
row = 2
|
||||
|
@ -54,8 +64,8 @@ class Menu:
|
|||
'height' : height,
|
||||
'textcolor' : textcolor, }
|
||||
for arg in args:
|
||||
if len(arg) == 4: # Handle submenu
|
||||
# txt, cb, (cbargs,), (elements,) = arg
|
||||
if len(arg) == 2: # Handle submenu
|
||||
# txt, ((element, cb, (cbargs,)),(element,cb, (cbargs,)), ..) = arg
|
||||
b = Button(writer, row, col, text=arg[0],
|
||||
callback=self.cb, args=arg, **btn)
|
||||
else:
|
||||
|
@ -64,6 +74,6 @@ class Menu:
|
|||
callback=cb, args=cbargs, **btn)
|
||||
col = b.mcol
|
||||
|
||||
def cb(self, button, txt, user_cb, args, elements): # Button pushed which calls submenu
|
||||
args = (self, button, elements, user_cb, args)
|
||||
def cb(self, button, txt, elements): # Button pushed which calls submenu
|
||||
args = (self, button, elements)
|
||||
Screen.change(SubMenu, args = args)
|
||||
|
|
|
@ -51,4 +51,4 @@ 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) #, 5)
|
||||
display = Display(ssd, nxt, sel, prev, increase, decrease, 5)
|
||||
|
|
Ładowanie…
Reference in New Issue