跳到主要内容
版本:最新版 🚧

KeyEvent

Overview

The KeyEvent class represents an event triggered by key input interaction. KeyEvent objects are typically obtained from MatrixOS.KeyPad.Get() and provide direct access to key state, force, timing, and other input properties.

The Python KeyEvent class is implemented in Applications/Python/PikaPython/MatrixOS_KeyEvent.py with type hints in Applications/Python/PikaPython/_MatrixOS_KeyEvent.pyi.


Methods

ID

def ID(self) -> int

Gets the unique identifier for this key event.

Returns:

  • int: The key 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