rust秒表demo

刚学了2天rust,基本语法看了一下,有了总体框架和概念。现在我想写个秒表小demo

现在我想:
1、当我按下键盘上的F1键,秒表从0开始计时,再次按下F1,暂停计时。
2、秒表在命令行打印显示毫秒即可。

我找了两个全局热键库和一个时间库:
全局热键库
https://crates.io/crates/taur...
https://crates.io/crates/live...

时间库
https://crates.io/crates/asyn...

有的库文档也没有,所以代码开了个头:

use std::time::Duration;


fn main() {

   let mut current_time=1;
   println!("current time is {}", current_time);

}

然后进行不下去了,大佬能否帮我看看应该怎么写这几行代码。万分感谢。

阅读 4.6k
2 个回答

写了一个demo,基本实现了你的需求,但是有一些小问题尚未解决,你参考一下吧

问题的原因找到了,就是库device_query的问题,按下F1的时候会产生两个事件:f1被按下;f1弹起来。device_query捕捉到了这个事件,但是并没有提供接口让调用者把它们区分开来,所以会出现连续捕捉到两个f1的情况,此时只要sleep一小会就能绕过这个问题。先这样吧,有时间的话你可以去完善一下这个demo。

[dependencies]
device_query = "0.2.8"
use device_query::{DeviceQuery, DeviceState, Keycode};
use std::{
    thread::sleep,
    time::{Duration, Instant},
};

fn main() {
    let mut status = "init";
    let device_state = DeviceState::new();
    let mut start_time = Instant::now();
    println!("请按下F1开始计时");
    loop {
        if status == "started" {
            print!("\r{}", start_time.elapsed().as_millis());
        }
        let keys: Vec<Keycode> = device_state.get_keys();
        if keys.len() == 0 || keys[0] != Keycode::F1 {
            continue;
        }
        // println!("捕捉到输入{:}", keys[0]);
        match status {
            "init" => {
                status = "started";
                sleep(Duration::from_millis(100)); //不先睡一会的话,下一轮loop会立马捕捉到F1原因不明
                println!("请按下F1结束计时");
                start_time = Instant::now();
            }
            "started" => {
                println!("\n经过了:{}毫秒", start_time.elapsed().as_millis());
                return;
            }
            _ => return,
        }
    }
}
新手上路,请多包涵

@youth7
有可能库已经更新了好多版本了, 有些不一样了吧, 我已经用上了 2.1.0 版本了
经测试, 这个库是每调用 get_keys 就会返回键盘按下的按键, 也就是说, 只要键盘按下任意一个键, get_keys 函数就会返回这个按键, 添加 sleep 也只是消抖的功能, 而且100ms太短了, 我再快的按按键抬起, 也会有 500+ 调用 get_keys 的次数(目测应该是每1ms循环一次), 这是我优化的代码:

use device_query::{DeviceQuery, DeviceState, Keycode};
use std::{time::{Instant}};

fn main() {
    let mut status = "init";
    let device_state = DeviceState::new();
    let mut start_time = Instant::now();
    println!("请按下F10开始计时");
    let mut down_count:u32 = 0;
    loop {
        if status == "started" {
            print!("\r{}", start_time.elapsed().as_millis());
        }
        let keys: Vec<Keycode> = device_state.get_keys();
        // 跳过无按键事件
        if keys.len() == 0 {
            down_count = 0;
            continue;
        }
        down_count+=1;
        // 跳过除F10的按键
        if keys[0] != Keycode::F10 || down_count!= 1{
            // println!("{down_count}\t捕捉到输入{:}", keys[0]);
            continue;
        }
        
        match status {
            "init" => {
                status = "started";
                println!("请按下F10结束计时");
                start_time = Instant::now();
            }
            "started" => {
                println!("\n经过了:{}毫秒", start_time.elapsed().as_millis());
                return;
            }
            _ => return,
        }
    }
}

我使用了一个计数, 当键盘按下, get_keys 获取的第一次才触发下面的状态机, 其余跳过

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进