You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt应用扫描2D DataMatrix条码时字符丢失问题求助

解决Qt 5.6.3 eglfs环境下GD4500扫描器字符丢失问题

核心问题分析

evtest能输出完整条码,说明Linux驱动层数据正常,问题出在Qt 5.6.3的eglfs键盘事件处理逻辑——快速连续的按键事件被合并或丢弃,且keyboardInputInterval仅支持依赖X11的QApplication,无法在eglfs环境使用。

可行解决思路

1. 直接读取evdev设备(最可靠)

绕开Qt的事件系统,直接从扫描器对应的/dev/input/eventX设备读取原始输入事件,自行解析拼接条码。

实现步骤:

  • 固定扫描器设备路径:通过evtest找到扫描器对应的event设备,或用udev规则给设备加固定别名(避免重启后event编号变化):
    创建/etc/udev/rules.d/99-gd4500-scanner.rules:

    SUBSYSTEM=="input", ATTRS{idVendor}=="XXXX", ATTRS{idProduct}=="YYYY", MODE="0666", SYMLINK+="gd4500-scanner"
    

    替换XXXX和YYYY为扫描器的USB厂商/产品ID(可通过lsusb查看)。

  • 编写evdev读取线程:用QThread循环读取输入事件,解析键值拼接条码:

    #include <QThread>
    #include <QString>
    #include <fcntl.h>
    #include <linux/input.h>
    #include <unistd.h>
    
    class ScannerReader : public QThread
    {
        Q_OBJECT
    protected:
        void run() override {
            int fd = open("/dev/gd4500-scanner", O_RDONLY | O_NONBLOCK);
            if (fd < 0) {
                qWarning("Failed to open GD4500 scanner device");
                return;
            }
    
            struct input_event ev;
            QString currentBarcode;
            bool shiftPressed = false;
    
            while (!isInterruptionRequested()) {
                ssize_t n = read(fd, &ev, sizeof(ev));
                if (n == sizeof(ev)) {
                    if (ev.type == EV_KEY) {
                        if (ev.value == 1) { // 按键按下
                            switch(ev.code) {
                                case KEY_LEFTSHIFT:
                                case KEY_RIGHTSHIFT:
                                    shiftPressed = true;
                                    break;
                                case KEY_ENTER:
                                    emit barcodeScanned(currentBarcode);
                                    currentBarcode.clear();
                                    break;
                                default:
                                    char c = mapKeyCodeToChar(ev.code, shiftPressed);
                                    if (c != 0) {
                                        currentBarcode.append(c);
                                    }
                                    break;
                            }
                        } else if (ev.value == 0) { // 按键释放
                            if (ev.code == KEY_LEFTSHIFT || ev.code == KEY_RIGHTSHIFT) {
                                shiftPressed = false;
                            }
                        }
                    }
                }
                usleep(1000); // 降低CPU占用
            }
            close(fd);
        }
    
        char mapKeyCodeToChar(unsigned int code, bool shift) {
            // 根据键盘布局映射键码到字符,示例仅做基础映射,需补充完整
            switch(code) {
                case KEY_A: return shift ? 'A' : 'a';
                case KEY_B: return shift ? 'B' : 'b';
                case KEY_0: return shift ? ')' : '0';
                case KEY_1: return shift ? '!' : '1';
                // 补充其他数字、符号、字母的映射
                default: return 0;
            }
        }
    
    signals:
        void barcodeScanned(const QString& barcode);
    };
    
  • 在主程序中使用:启动线程并连接barcodeScanned信号处理条码数据。

2. 修改Qt EGLFS插件的键盘事件逻辑

Qt 5.6.3的eglfs键盘处理可能存在快速事件丢失的问题,可修改Qt源码调整事件合并策略:

  • 找到Qt源码路径:qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfskerneldevice.cpp
  • 在键盘事件处理函数中,添加时间间隔判断:记录上一个按键事件的时间戳,当新事件与上一个事件的间隔小于扫描器的输出间隔(比如10ms)时,直接传递事件而不合并。
  • 重新编译Qt的eglfs插件,替换原插件。

3. 优化扫描器输出设置

除了调整USB速度,还可通过扫描器的配置条码修改以下参数:

  • 增加字符输出间隔:设置为15ms以上,超过Qt事件处理的阈值
  • 开启扫描结束标记:确保扫描器输出回车/换行作为条码结束符,方便识别完整条码
  • 切换到慢输出模式:部分扫描器支持降低键盘输出速度,适配嵌入式系统的处理能力

4. 升级Qt版本(若项目允许)

Qt 5.6.3是较老的版本,后续LTS版本(如5.12+)修复了大量嵌入式平台的输入事件处理bug,升级后可能直接解决字符丢失问题。


内容的提问来源于stack exchange,提问作者user3172491

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 05:04:54