You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Connect4: add directional controls
This commit is contained in:
@@ -447,6 +447,54 @@ def handle_result(self, result):
|
||||
- `mpos.ui.focus_direction`: Keyboard/joystick navigation helpers
|
||||
- `mpos.ui.anim`: Animation utilities
|
||||
|
||||
### Keyboard and Focus Navigation
|
||||
|
||||
MicroPythonOS supports keyboard/joystick navigation through LVGL's focus group system. This allows users to navigate apps using arrow keys and select items with Enter.
|
||||
|
||||
**Basic focus handling pattern**:
|
||||
```python
|
||||
def onCreate(self):
|
||||
# Get the default focus group
|
||||
focusgroup = lv.group_get_default()
|
||||
if not focusgroup:
|
||||
print("WARNING: could not get default focusgroup")
|
||||
|
||||
# Create a clickable object
|
||||
button = lv.button(screen)
|
||||
|
||||
# Add focus/defocus event handlers
|
||||
button.add_event_cb(lambda e, b=button: self.focus_handler(b), lv.EVENT.FOCUSED, None)
|
||||
button.add_event_cb(lambda e, b=button: self.defocus_handler(b), lv.EVENT.DEFOCUSED, None)
|
||||
|
||||
# Add to focus group (enables keyboard navigation)
|
||||
if focusgroup:
|
||||
focusgroup.add_obj(button)
|
||||
|
||||
def focus_handler(self, obj):
|
||||
"""Called when object receives focus"""
|
||||
obj.set_style_border_color(lv.theme_get_color_primary(None), lv.PART.MAIN)
|
||||
obj.set_style_border_width(2, lv.PART.MAIN)
|
||||
obj.scroll_to_view(True) # Scroll into view if needed
|
||||
|
||||
def defocus_handler(self, obj):
|
||||
"""Called when object loses focus"""
|
||||
obj.set_style_border_width(0, lv.PART.MAIN)
|
||||
```
|
||||
|
||||
**Key principles**:
|
||||
- Get the default focus group with `lv.group_get_default()`
|
||||
- Add objects to the focus group to make them keyboard-navigable
|
||||
- Use `lv.EVENT.FOCUSED` to highlight focused elements (usually with a border)
|
||||
- Use `lv.EVENT.DEFOCUSED` to remove highlighting
|
||||
- Use theme color for consistency: `lv.theme_get_color_primary(None)`
|
||||
- Call `scroll_to_view(True)` to auto-scroll focused items into view
|
||||
- The focus group automatically handles arrow key navigation between objects
|
||||
|
||||
**Example apps with focus handling**:
|
||||
- **Launcher** (`builtin/apps/com.micropythonos.launcher/assets/launcher.py`): App icons are focusable
|
||||
- **Settings** (`builtin/apps/com.micropythonos.settings/assets/settings_app.py`): Settings items are focusable
|
||||
- **Connect 4** (`apps/com.micropythonos.connect4/assets/connect4.py`): Game columns are focusable
|
||||
|
||||
**Other utilities**:
|
||||
- `mpos.apps.good_stack_size()`: Returns appropriate thread stack size for platform (16KB ESP32, 24KB desktop)
|
||||
- `mpos.wifi`: WiFi management utilities
|
||||
|
||||
@@ -129,6 +129,10 @@ class Connect4(Activity):
|
||||
self.pieces.append(piece_row)
|
||||
|
||||
# Create column buttons (invisible clickable areas)
|
||||
focusgroup = lv.group_get_default()
|
||||
if not focusgroup:
|
||||
print("WARNING: could not get default focusgroup")
|
||||
|
||||
for col in range(self.COLS):
|
||||
btn = lv.obj(self.screen)
|
||||
btn.set_size(self.CELL_SIZE, self.ROWS * self.CELL_SIZE)
|
||||
@@ -138,6 +142,12 @@ class Connect4(Activity):
|
||||
btn.set_style_border_width(0, 0)
|
||||
btn.add_flag(lv.obj.FLAG.CLICKABLE)
|
||||
btn.add_event_cb(lambda e, c=col: self.on_column_click(c), lv.EVENT.CLICKED, None)
|
||||
btn.add_event_cb(lambda e, b=btn: self.focus_column(b), lv.EVENT.FOCUSED, None)
|
||||
btn.add_event_cb(lambda e, b=btn: self.defocus_column(b), lv.EVENT.DEFOCUSED, None)
|
||||
|
||||
if focusgroup:
|
||||
focusgroup.add_obj(btn)
|
||||
|
||||
self.column_buttons.append(btn)
|
||||
|
||||
self.setContentView(self.screen)
|
||||
@@ -145,6 +155,15 @@ class Connect4(Activity):
|
||||
def onResume(self, screen):
|
||||
self.last_time = time.ticks_ms()
|
||||
|
||||
def focus_column(self, column_btn):
|
||||
"""Highlight column when focused"""
|
||||
column_btn.set_style_border_color(lv.theme_get_color_primary(None), lv.PART.MAIN)
|
||||
column_btn.set_style_border_width(3, lv.PART.MAIN)
|
||||
|
||||
def defocus_column(self, column_btn):
|
||||
"""Remove highlight when unfocused"""
|
||||
column_btn.set_style_border_width(0, lv.PART.MAIN)
|
||||
|
||||
def cycle_difficulty(self, event):
|
||||
if self.animating:
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user