Rust sdl2中Event变体作为HashMap键报E0423的解决方法
报错根因
你碰到的E0423错误核心原因有两个:
sdl2::event::Event的所有变体都是类结构体变体,不是无载荷的单元变体,直接写Event::Quit只是变体的类型名,不是可以直接传值的合法实例,必须把变体要求的所有字段都填充后才能得到合法的Event值,直接写变体名当参数就会触发这个编译错误。- 就算你手动构造了
Event::Quit实例,也不适合直接拿完整Event当HashMap的key:SDL2返回的Event实例会携带大量动态运行时数据(比如事件时间戳、鼠标坐标、重复按键标记等),你不可能提前预知这些动态值,自然也没法构造出完全相等的key做匹配。
另外你贴的示例代码还有几个基础语法错误,也会导致编译失败:
Hashmap::new()拼写错误,标准库的HashMap遵循大驼峰命名规则,正确写法是HashMap::new()- HashMap变量未加
mut修饰,Rust中变量默认不可变,没有mut声明无法调用insert修改集合内容 - 直接把
event传给contains_key会转移事件的所有权,后续如果要复用事件会触发所有权相关编译错误
可行实现方案
不要直接用原生Event作为HashMap的key,先自定义一个只保留事件匹配特征的轻量枚举作为键类型,给这个枚举派生Hash、Eq、PartialEq trait满足HashMap的key要求,运行时先把SDL返回的原生事件转换成自定义键,再去HashMap查对应值即可。
参考实现代码:
use std::collections::HashMap; use sdl2::event::Event; use sdl2::keyboard::Keycode; // 自定义事件键,只存需要匹配的核心特征,不带冗余动态字段 #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)] enum AppEvent { Quit, KeyPress(Keycode), } fn main() -> Result<(), String> { let sdl_ctx = sdl2::init()?; let mut event_pump = sdl_ctx.event_pump()?; let mut event_map = HashMap::new(); // 插入键值对:X键按下对应值12,退出事件对应退出标记 event_map.insert(AppEvent::KeyPress(Keycode::X), 12); event_map.insert(AppEvent::Quit, -1); 'main_loop: loop { for event in event_pump.poll_iter() { // 原生事件转自定义键,无关事件直接过滤 let bind_key = match event { Event::Quit { .. } => Some(AppEvent::Quit), Event::KeyDown { keycode: Some(k), .. } => Some(AppEvent::KeyPress(k)), _ => None }; // 查到对应值就执行业务逻辑 if let Some(val) = bind_key.and_then(|k| event_map.get(&k)) { match val { 12 => println!("X键按下,对应值为12"), -1 => break 'main_loop, _ => {} } } } } Ok(()) }
这种写法不需要关心事件携带的冗余动态字段,只需要匹配你关心的核心特征,自定义键是Copy类型,不会触发所有权问题,匹配效率也比直接比对完整Event结构高。
内容的提问来源于stack exchange,提问作者rgfrtzwerf
相关产品推荐
相关产品推荐

