FLTK Rust 按键事件重复触发问题:实现单次按键响应
解决按键重复触发问题,实现单次按键移动方块
要实现按下按键仅触发一次移动,直到再次按下的逻辑,核心是跟踪按键的按下/释放状态,避免按住按键时重复响应。下面是修改后的完整代码及关键说明:
修改后的代码
use fltk::draw::*; use fltk::{prelude::*, *}; use std::cell::RefCell; use std::rc::Rc; fn main() { let app = app::App::default(); let mut win = window::Window::default().with_size(350, 350); let mut frame = frame::Frame::default().size_of_parent(); // 方块初始位置(窗口中心) let square_size = 10; let mut x_pos = win.w() / 2 - square_size / 2; let mut y_pos = win.h() / 2 - square_size / 2; // 用Rc<RefCell>共享状态:当前按住的按键、方块位置 let x_pos = Rc::new(RefCell::new(x_pos)); let y_pos = Rc::new(RefCell::new(y_pos)); let current_key = Rc::new(RefCell::new(None::<enums::Key>)); let x_draw = x_pos.clone(); let y_draw = y_pos.clone(); // 绘制黑色背景和白色方块 frame.draw(move |f| { draw_rect_fill(0, 0, f.w(), f.h(), enums::Color::Black); draw_rect_fill( *x_draw.borrow(), *y_draw.borrow(), square_size, square_size, enums::Color::White, ); }); let x_handle = x_pos.clone(); let y_handle = y_pos.clone(); let current_key_handle = current_key.clone(); // 处理按键事件 frame.handle(move |frame, event| { use fltk::enums::{Event, Key}; match event { // 按键按下事件 Event::KeyPress => { let key = app::event_key(); let mut current_key = current_key_handle.borrow_mut(); // 仅当没有按住的按键时,才执行移动逻辑 if current_key.is_none() { match key { Key::Right => { *x_handle.borrow_mut() += 5; // 每次移动5像素 frame.redraw(); } Key::Left => { *x_handle.borrow_mut() -= 5; frame.redraw(); } Key::Up => { *y_handle.borrow_mut() -= 5; frame.redraw(); } Key::Down => { *y_handle.borrow_mut() += 5; frame.redraw(); } _ => return false, } // 记录当前按住的按键 *current_key = Some(key); true } else { // 已有按住的按键,忽略重复触发 false } } // 按键释放事件 Event::KeyRelease => { let key = app::event_key(); let mut current_key = current_key_handle.borrow_mut(); // 如果释放的是当前按住的按键,清空记录 if *current_key == Some(key) { *current_key = None; true } else { false } } // 忽略其他事件 _ => false, } }); win.end(); win.show(); app.run().unwrap(); }
关键逻辑说明
- 跟踪按键状态:用
current_key存储当前按住的按键,初始为None。只有当current_key为None时,才响应按键按下事件,避免重复触发。 - 区分事件类型:通过
Event::KeyPress和Event::KeyRelease分别处理按键按下和释放动作,释放时清空current_key,允许下次按键再次触发。 - 优化方块位置:直接维护方块的x/y坐标,比原代码的offset更直观,同时调整了方块初始位置使其完全居中。
- 移除阻塞操作:删掉了原代码中的
app::sleep(0.0500),避免阻塞事件循环导致界面卡顿。
内容的提问来源于stack exchange,提问作者user324885
相关产品推荐
相关产品推荐

