跳到主要内容
版本:3.0 Beta 🧪

KeyEvent

概述

KeyEvent 类表示由按键输入交互触发的事件。KeyEvent 对象通常从 MatrixOS.KeyPad.Get() 获取,并提供对按键状态、力度、时间和其他输入属性的直接访问。

Python KeyEvent 类实现位于 Applications/Python/PikaPython/MatrixOS_KeyEvent.py,类型提示位于 Applications/Python/PikaPython/_MatrixOS_KeyEvent.pyi


方法

ID

def ID(self) -> int

获取此按键事件的唯一标识符。

返回值:

  • int:按键 ID

Example:

key_event = MatrixOS.KeyPad.Get(50)
if key_event:
key_id = key_event.ID()
print(f"Key ID: {key_id}")

State

def State(self) -> int

Gets the current state of the key.

Returns:

  • int: Key state value

Hold

def Hold(self) -> bool

Checks if the key is being held.

Returns:

  • bool: True if key is held

HoldTime

def HoldTime(self) -> int

Gets the time the key has been held in milliseconds.

Returns:

  • int: Hold time in milliseconds

Active

def Active(self) -> bool

Checks if the key is currently active (pressed).

Returns:

  • bool: True if key is active

Force

def Force(self) -> float

Gets the force/pressure applied to the key.

Returns:

  • float: Force value (0.0 to 1.0)

Value

def Value(self, index: int = 0) -> float

Gets a specific value from the key event.

Parameters:

  • index (int, optional): Value index (default: 0)

Returns:

  • float: Value at specified index

__bool__

def __bool__(self) -> bool

Allows KeyEvent to be used in boolean context.

Returns:

  • bool: True if event is valid

Example:

key_event = MatrixOS.KeyPad.Get(50)
if key_event: # Uses __bool__
print("Valid key event received")

Usage Examples

Basic Key Event Handling

def handle_key_events():
"""Basic key event processing"""
print("Key event handler started...")

while True:
key_event = MatrixOS.KeyPad.Get(50) # 50ms timeout

if key_event:
key_id = key_event.ID()

print(f"Key {key_id} event:")
print(f" State: {key_event.State()}")
print(f" Force: {key_event.Force():.2f}")
print(f" Active: {key_event.Active()}")

if key_event.Hold():
print(f" Hold time: {key_event.HoldTime()}ms")

handle_key_events()

Key Event Classification

def classify_key_events():
"""Classify and respond to different types of key events"""

while True:
key_event = MatrixOS.KeyPad.Get(50)

if key_event:
key_id = key_event.ID()

# Convert to XY coordinates for display
xy = MatrixOS.KeyPad.ID2XY(key_id)

if key_event.Active():
# Key is currently pressed
force = key_event.Force()

if force > 0.8:
print(f"Hard press at ({xy.X()},{xy.Y()})")
MatrixOS.LED.SetColor(xy, Color(255, 0, 0))
elif force > 0.4:
print(f"Medium press at ({xy.X()},{xy.Y()})")
MatrixOS.LED.SetColor(xy, Color(255, 255, 0))
else:
print(f"Soft press at ({xy.X()},{xy.Y()})")
MatrixOS.LED.SetColor(xy, Color(0, 255, 0))

if key_event.Hold():
hold_time = key_event.HoldTime()
if hold_time > 1000: # Held for more than 1 second
print(f"Long hold detected: {hold_time}ms")
MatrixOS.LED.SetColor(xy, Color(255, 255, 255))
else:
# Key was released
print(f"Key released at ({xy.X()},{xy.Y()})")
MatrixOS.LED.SetColor(xy, Color(0, 0, 0))

MatrixOS.LED.Update()

classify_key_events()

Event-Driven Application

def event_driven_app():
"""Event-driven application using KeyEvent objects"""

app_state = {
"mode": "normal",
"selected_key": None,
"last_event_time": 0
}

def handle_normal_mode(key_event):
"""Handle events in normal mode"""
key_id = key_event.ID()
xy = MatrixOS.KeyPad.ID2XY(key_id)

if key_event.Active():
app_state["selected_key"] = key_id
MatrixOS.LED.SetColor(xy, Color(0, 255, 255))

# Check for mode switch (long press)
if key_event.Hold() and key_event.HoldTime() > 2000:
app_state["mode"] = "config"
MatrixOS.LED.Fill(Color(255, 0, 255))
print("Switched to config mode")
else:
MatrixOS.LED.SetColor(xy, Color(0, 0, 0))

def handle_config_mode(key_event):
"""Handle events in configuration mode"""
key_id = key_event.ID()

if key_event.Active():
if key_id == 0: # Top-left corner to exit
app_state["mode"] = "normal"
MatrixOS.LED.Fill(Color(0, 0, 0))
print("Switched to normal mode")
else:
# Configuration actions
xy = MatrixOS.KeyPad.ID2XY(key_id)
MatrixOS.LED.SetColor(xy, Color(255, 255, 0))
print(f"Config action: key {key_id}")

print("Event-driven app started")
print("Long press any key for config mode")

while True:
key_event = MatrixOS.KeyPad.Get(50)

if key_event:
app_state["last_event_time"] = MatrixOS.SYS.Millis()

if app_state["mode"] == "normal":
handle_normal_mode(key_event)
elif app_state["mode"] == "config":
handle_config_mode(key_event)

MatrixOS.LED.Update()

# Auto-return to normal mode if no activity
if (app_state["mode"] == "config" and
MatrixOS.SYS.Millis() - app_state["last_event_time"] > 10000):
app_state["mode"] = "normal"
MatrixOS.LED.Fill(Color(0, 0, 0))
MatrixOS.LED.Update()
print("Auto-returned to normal mode")

event_driven_app()

Force-Sensitive Drawing

def force_drawing():
"""Draw with different colors based on key force"""

print("Force-sensitive drawing active")
print("Press keys with different pressure levels")

while True:
key_event = MatrixOS.KeyPad.Get(50)

if key_event:
xy = MatrixOS.KeyPad.ID2XY(key_event.ID())

if key_event.Active():
force = key_event.Force()

# Map force to color intensity
if force > 0.9:
color = Color(255, 255, 255) # White for maximum force
elif force > 0.7:
color = Color(255, 0, 0) # Red for high force
elif force > 0.5:
color = Color(255, 128, 0) # Orange for medium force
elif force > 0.3:
color = Color(255, 255, 0) # Yellow for light force
else:
color = Color(0, 255, 0) # Green for minimal force

MatrixOS.LED.SetColor(xy, color)
print(f"Drawing at ({xy.X()},{xy.Y()}) with force {force:.2f}")
else:
# Keep the drawing when key is released
pass

MatrixOS.LED.Update()

force_drawing()

Multi-Key Gesture Detection

def gesture_detector():
"""Detect multi-key gestures using KeyEvent timing"""

active_keys = {}
gesture_threshold = 200 # ms

def detect_gesture(active_keys):
"""Analyze active keys for gesture patterns"""
key_ids = list(active_keys.keys())

if len(key_ids) == 2:
# Two-key gestures
key1_xy = MatrixOS.KeyPad.ID2XY(key_ids[0])
key2_xy = MatrixOS.KeyPad.ID2XY(key_ids[1])

# Horizontal swipe
if key1_xy.Y() == key2_xy.Y() and abs(key1_xy.X() - key2_xy.X()) == 1:
return "horizontal_swipe"
# Vertical swipe
elif key1_xy.X() == key2_xy.X() and abs(key1_xy.Y() - key2_xy.Y()) == 1:
return "vertical_swipe"
# Corner tap
elif (key1_xy.X() == 0 and key1_xy.Y() == 0) or (key1_xy.X() == 7 and key1_xy.Y() == 7):
return "corner_combo"

elif len(key_ids) == 4:
# Four corners
corners = [(0,0), (0,7), (7,0), (7,7)]
key_positions = [(MatrixOS.KeyPad.ID2XY(kid).X(), MatrixOS.KeyPad.ID2XY(kid).Y()) for kid in key_ids]
if all(pos in corners for pos in key_positions):
return "four_corners"

return None

print("Gesture detector active")
print("Try: two adjacent keys, four corners, etc.")

while True:
key_event = MatrixOS.KeyPad.Get(50)

if key_event:
key_id = key_event.ID()
current_time = MatrixOS.SYS.Millis()

if key_event.Active():
active_keys[key_id] = {
"start_time": current_time,
"event": key_event
}

# Light up active keys
xy = MatrixOS.KeyPad.ID2XY(key_id)
MatrixOS.LED.SetColor(xy, Color(0, 255, 0))

else:
# Key released
if key_id in active_keys:
del active_keys[key_id]

xy = MatrixOS.KeyPad.ID2XY(key_id)
MatrixOS.LED.SetColor(xy, Color(0, 0, 0))

# Check for gestures when multiple keys are active
if len(active_keys) >= 2:
gesture = detect_gesture(active_keys)
if gesture:
print(f"Gesture detected: {gesture}")

# Visual feedback
MatrixOS.LED.Fill(Color(255, 255, 255))
MatrixOS.LED.Update()
MatrixOS.SYS.DelayMs(200)

# Clear gesture state
active_keys.clear()
MatrixOS.LED.Fill(Color(0, 0, 0))

MatrixOS.LED.Update()

gesture_detector()

Performance Monitoring

def key_performance_monitor():
"""Monitor key performance and timing"""

key_stats = {}

while True:
key_event = MatrixOS.KeyPad.Get(50)

if key_event:
key_id = key_event.ID()

if key_id not in key_stats:
key_stats[key_id] = {
"presses": 0,
"total_force": 0.0,
"max_force": 0.0,
"total_hold_time": 0
}

stats = key_stats[key_id]

if key_event.Active():
force = key_event.Force()
stats["total_force"] += force
stats["max_force"] = max(stats["max_force"], force)

if key_event.Hold():
hold_time = key_event.HoldTime()
if hold_time > stats.get("last_hold_time", 0):
stats["total_hold_time"] = hold_time
stats["last_hold_time"] = hold_time

else:
# Key released
stats["presses"] += 1

# Print stats every 10 presses
if stats["presses"] % 10 == 0:
avg_force = stats["total_force"] / stats["presses"]
xy = MatrixOS.KeyPad.ID2XY(key_id)
print(f"Key ({xy.X()},{xy.Y()}) - Presses: {stats['presses']}, "
f"Avg Force: {avg_force:.2f}, Max Force: {stats['max_force']:.2f}")

key_performance_monitor()

Common Patterns

Event Validation

# Check if event is valid
key_event = MatrixOS.KeyPad.Get(50)
if key_event: # Uses __bool__ method
# Process event
pass

# Alternative explicit check
if key_event is not None:
# Process event
pass

Force-Based Actions

def force_based_action(key_event):
"""Perform different actions based on key force"""
force = key_event.Force()

if force > 0.8:
return "strong_action"
elif force > 0.5:
return "medium_action"
else:
return "light_action"

Hold Detection

def check_hold_duration(key_event):
"""Check for different hold durations"""
if key_event.Hold():
hold_time = key_event.HoldTime()

if hold_time > 3000:
return "extra_long_hold"
elif hold_time > 1000:
return "long_hold"
elif hold_time > 500:
return "short_hold"

return "no_hold"

Comments