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