Raspberry Pi 上带有 Tslib 的 Qt 5.4 Linux 触摸屏输入因 LinuxFB QPA 平台插件而失败

Posted

技术标签:

【中文标题】Raspberry Pi 上带有 Tslib 的 Qt 5.4 Linux 触摸屏输入因 LinuxFB QPA 平台插件而失败【英文标题】:Qt 5.4 Linux Touchscreen Input with Tslib on Raspberry Pi failing with LinuxFB QPA Platform Plugin 【发布时间】:2015-03-05 02:27:35 【问题描述】:

我为我的 Raspberry Pi 购买了一个 Tontec 2.4 英寸触摸屏 (http://elinux.org/MZTX-PI-EXT)。触摸屏控制器需要 elinux 帖子中描述的“tsc2007.ko”和“tsp_raspi.ko”内核模块。 tsc2007.ko 模块位于 Raspbian 内核树中,但 tsp_raspi.ko 可以在此处找到:https://github.com/osandov/raspi/tree/master/tsc2007。

我已经用这些模块为 Pi 交叉编译了一个新的内核,它们可以很好地加载并在 Raspbian 中创建一个 /dev/input/event0 设备。如果我“测试”该设备并触摸屏幕,我会得到输出,因此我知道事件正在 Linux 中传递:

pi@raspberry /dev/input $ evtest
Available devices:
/dev/input/event0:  TSC2007 Touchscreen
Select the device event number [0-0]: 0
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0
Input device name: "TSC2007 Touchscreen"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 330 (BTN_TOUCH)
  Event type 3 (EV_ABS)
    Event code 0 (ABS_X)
      Value   1922
      Min        0
      Max     4095
      Fuzz      64
    Event code 1 (ABS_Y)
      Value   2221
      Min        0
      Max     4095
      Fuzz      64
    Event code 24 (ABS_PRESSURE)
      Value      0
      Min        0
      Max     4095
      Fuzz      64
Properties:
Testing ... (interrupt to exit)
Event: time 1425521704.199489, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1425521704.199489, type 3 (EV_ABS), code 1 (ABS_Y), value 2085
Event: time 1425521704.199489, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 538
Event: time 1425521704.199489, -------------- SYN_REPORT ------------
Event: time 1425521704.209174, type 3 (EV_ABS), code 0 (ABS_X), value 1455
...

我安装了 tslib 并运行了一个快速的 ts_calibrate。我还确保 ts_test 在我触摸屏幕时吐出数据。

我在 /etc/profile 中添加了以下环境变量以在 Qt5 中支持 tslib:

## For Qt5 Touchscreen Support
export QT_DEBUG_PLUGINS=1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/arm-linux-gnueabihf/
export QT_PLUGIN_PATH=/usr/lib/plugins
export QT_QPA_FONTDIR=/usr/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/plugins/platforms
export QT_QPA_PLATFORM=linuxfb
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event0
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0
export TSLIB_TSEVENTTYPE='INPUT'
export TSLIB_CALIBFILE='/etc/pointercal'
export TSLIB_CONFFILE='/etc/ts.conf'
export TSLIB_CONSOLEDEVICE='none'
export TSLIB_FBDEVICE='/dev/fb0'
export TSLIB_PLUGINDIR='/usr/lib/ts'
export TSLIB_TSDEVICE='/dev/input/event0'

我阅读了 Qt5 文档以及如何在我的应用程序中获取触摸事件。我有一个主 Widget 并在构造函数中设置了适当的标志:

MainWidget::MainWidget(QLabel *parent)
    : QLabel(parent)


    qDebug() << "Setting WA_AcceptTouchEvents on MainWidget...";

    // Accept touch events
    setAttribute(Qt::WA_AcceptTouchEvents);
    setAttribute(Qt::WA_StaticContents);


我设置了一个事件过滤器来尝试捕捉触摸事件:

bool MainWidget::eventFilter( QObject* target, QEvent* e )


    qDebug() << "Event Type: " << e->type();

    return false;

    return QLabel::eventFilter(target, e);

我这样启动我的应用程序:

myapp -platform linuxfb:fb=/dev/fb0 -plugin tslib:/dev/input/event0

我还在 qtslib.cpp 的 Qt 源代码中取消了单个 printf 的注释:

void QTsLibMouseHandler::readMouseData()

    ts_sample sample;

    while (get_sample(m_dev, &sample, m_rawMode)) 
        bool pressed = sample.pressure;
        int x = sample.x;
        int y = sample.y;

        // work around missing coordinates on mouse release
        if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) 
            x = m_x;
            y = m_y;
        

        if (!m_rawMode) 
            //filtering: ignore movements of 2 pixels or less
            int dx = x - m_x;
            int dy = y - m_y;
            if (dx*dx <= 4 && dy*dy <= 4 && pressed == m_pressed)
                continue;
        
        QPoint pos(x, y);

        //printf("handleMouseEvent %d %d %d %ld\n", m_x, m_y, pressed, sample.tv.tv_usec);

        QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton);

        m_x = x;
        m_y = y;
        m_pressed = pressed;
    

当我启动我的 Qt 应用程序时,我看到插件加载正常(甚至显示正确的 event0 文件)。我还看到当我触摸屏幕时 qt tslib 插件正在接收触摸事件。问题是永远不会调用事件过滤器!

这是正在启动的应用程序:

Got keys from plugin meta data ("tslib", "tslibraw")
QFactoryLoader::QFactoryLoader() checking directory path "/home/pi/generic" ...
loaded library "/usr/lib/qt/plugins/generic/libqtslibplugin.so"
QTsLibMouseHandler "tslib" ""
QTsLibMouseHandler "tslib" "/dev/input/event0"
QFactoryLoader::QFactoryLoader() checking directory path "/usr/lib/qt/plugins/styles" ...
QFactoryLoader::QFactoryLoader() checking directory path "/home/pi/styles" ...
Setting WA_AcceptTouchEvents on MainWidget...

-----------------------------------------
Waiting for data now...
-----------------------------------------

handleMouseEvent 0 0 1 751196
handleMouseEvent 0 0 1 751196
handleMouseEvent 1696 1615 1 771075
handleMouseEvent 1696 1615 1 771075
handleMouseEvent 1679 1622 1 781368
handleMouseEvent 1671 1638 1 781368
handleMouseEvent 1679 1622 1 781368
handleMouseEvent 1671 1638 1 781368
...

我发现了一些论坛帖子,人们在使用 linuxfb 平台插件时遇到触摸输入问题:

http://comments.gmane.org/gmane.comp.lib.qt.user/5686

http://qt-project.org/forums/viewthread/35757

http://qt-project.org/forums/viewthread/36120/

我已经尝试了他们的所有建议,但问题仍然存在 - 即使 Qt tslib 插件说它正在接收它们,我的应用程序也没有接收到触摸事件。

似乎 tslib 插件在将它接收到的事件注入我的应用程序的事件循环时遇到问题:

QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton);

我还尝试了 Qt5.4 touch fingerpaint 示例并看到相同的行为 - 未收到任何触摸事件。

我不知道从这里去哪里。我将非常感谢解决此问题的任何帮助。谢谢!

更新:

我更改了事件过滤器,如下所示:

bool MainWidget::eventFilter(QObject *obj, QEvent *event)


    qDebug() << "Event received" << obj->metaObject()->className() <<  event->type();
    switch (event->type()) 
        case QEvent::TouchBegin:
            qDebug() << "TouchBegin";
        case QEvent::TouchUpdate:
            qDebug() << "TouchUpdate";
        case QEvent::TouchEnd:
            qDebug() << "TouchEnd";
        

            //        QTouchEvent *touch = static_cast<QTouchEvent *>(event);
            //        QList<QTouchEvent::TouchPoint> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
            //        foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) 
            //            switch (touchPoint.state()) 
            //            case Qt::TouchPointStationary:
            //                // don't do anything if this touch point hasn't moved
            //                continue;
            //            default:
            //                
            //                
            //                break;
            //            
            //        
            //        break;
        
        //default:
            //return QLabel::event(event);
    
    //return true;


现在,每当我触摸屏幕时,我都可以看到与 Qt Tslib 插件打印混合在一起的“套接字通知程序”事件。关于为什么事件类型为 50 但没有触摸事件的任何想法?

Event received QSocketNotifier 50
handleMouseEvent 2702 2618 0 557715
Event received QSocketNotifier 50
handleMouseEvent 2698 2612 1 547758
Event received QSocketNotifier 50
handleMouseEvent 2706 2802 1 759928
Event received QSocketNotifier 50
Event received QSocketNotifier 50

更新 #2:

我安装事件过滤器只是为了尝试捕获任何事件。我不确定在 Qt5 中什么将事件类型 50 ( QSocketNotifier ) 转换为 QTouch* 或 QMouse* 事件。

这里有更多信息:

当我运行 evtest 时,我看到屏幕分辨率很大(~2500 x ~2500 ),实际屏幕为 320x240。我试着改变了 /boot/config.txt 中的 /dev/fb0 帧缓冲区大小为 320x240 和 重新启动。但是 evtest 和 ts_calibrate 步骤仍然显示巨大 分辨率。 由于分辨率大,我尝试制作我的主要小部件 10000x10000 看看我是否会得到触摸或鼠标事件 - 但我 仍然只能得到 QSocketNotifier 然后我尝试强制 tslib 插件始终在 屏幕位置 X=50 Y=50,但我仍然只得到事件类型 50 QSocketNotifier。

【问题讨论】:

【参考方案1】:

通过确保在 RasbperryPi 上安装 tslib 插件解决了问题。

TSLIB_PLUGINDIR=/usr/lib/ts

Pi 上没有目录 /usr/lib/ts。

【讨论】:

我找不到包裹。你是通过包管理器安装的吗?还是手动?你能详细说明一下你是如何让它工作的吗? 您好,该软件包应使用“sudo apt-get install evtest tslib libts-bin”安装 tslib 似乎已变为 libts-0.0-0 并且该文件夹现在似乎为 /usr/lib/arm-linux-gnueabihf/ts0。但是,我仍然无法让它运行...... :( hmmm - 可以尝试软链接或从 buildroot 为树莓派构建 tslib。 我(现在)正在关注those instructions 以在tslib 的支持下构建Qt。你用的是 raspbian 包?你自己建的?您的 Qt 库如何获得 tslib 支持? (我觉得我的默认情况下没有支持,但我不确定我是否在寻找正确的地方)。很抱歉变成了吸血鬼:(

以上是关于Raspberry Pi 上带有 Tslib 的 Qt 5.4 Linux 触摸屏输入因 LinuxFB QPA 平台插件而失败的主要内容,如果未能解决你的问题,请参考以下文章

我如何让Raspberry Pi用python发送带有图片的电子邮件

cv2.VideoWriter() 在带有 Raspicam 的 Raspberry Pi 上不起作用

为啥堆栈段可以在 Raspberry Pi 上执行?

带有温度传感器的 SocketIO - 我几乎在我的 Raspberry Pi 上使用 NodeJS 和 SocketIO 完成了 DS18B20,如何提取 Promise data ?

.NET Core 准备好在 Raspberry PI 3 上运行了吗?

长按在 Raspberry Pi 触摸屏上不起作用