如何在Dart中实现类似C语言kbhit()的非阻塞按键检测功能?
在Dart中实现类似C语言kbhit()的非阻塞按键检测功能
Dart标准库没有直接提供和C语言kbhit()完全一致的非阻塞按键检测函数,你之前使用的readByteSync()会阻塞程序直到有输入,下面提供两种可行的实现方案:
方案一:异步监听按键输入
通过stdin.listen()异步监听输入流,主程序可以继续执行而不被阻塞:
import 'dart:io'; void main() async { // 关闭回显和行模式,让按键操作立即响应 stdin.echoMode = false; stdin.lineMode = false; // 异步监听按键输入 stdin.listen((List<int> data) { String key = String.fromCharCodes(data); print('按下了按键: $key'); // 按q键退出程序并恢复终端设置 if (key.toLowerCase() == 'q') { stdin.echoMode = true; stdin.lineMode = true; exit(0); } }); // 主程序逻辑,不会被输入操作阻塞 print('程序运行中,按任意键测试,按q退出...'); while (true) { await Future.delayed(const Duration(milliseconds: 500)); print('主程序正在运行...'); } }
方案二:模拟kbhit()的轮询检测
如果需要像kbhit()那样主动检测是否有按键按下,可以结合异步读取和超时实现非阻塞检测:
import 'dart:io'; import 'dart:async'; // 模拟C语言kbhit(),返回是否有按键等待输入 Future<bool> kbhit() async { if (!stdin.hasTerminal) return false; stdin.echoMode = false; stdin.lineMode = false; try { // 设置超时为0,无输入时立即抛出超时异常 await stdin.readByte().timeout(Duration.zero); return true; } on TimeoutException { return false; } } void main() async { stdin.echoMode = false; stdin.lineMode = false; print('程序运行中,按任意键触发检测,按q退出...'); while (true) { if (await kbhit()) { int keyCode = stdin.readByteSync(); String key = String.fromCharCode(keyCode); print('检测到按键: $key'); if (key.toLowerCase() == 'q') { stdin.echoMode = true; stdin.lineMode = true; exit(0); } } // 主程序循环逻辑 await Future.delayed(const Duration(milliseconds: 300)); print('主程序循环中...'); } }
注意事项
- 上述代码仅在终端环境下有效,部分IDE控制台可能存在兼容性问题
- 程序退出前务必恢复
echoMode和lineMode,避免终端出现输入异常 - 方案二的
kbhit()函数仅检测是否有输入,需要额外调用readByteSync()读取具体按键值
内容的提问来源于stack exchange,提问作者Morteza Javadian
相关产品推荐
相关产品推荐

