i.MX6UL基于嵌入式QT实现电容屏多点触控

基于i.MX6UL平台,使用嵌入式QT实现电容屏的多点触控,前提是开发板的电容触摸屏驱动已经支持多点触控,并且驱动程序能通过事件方式向应用程序上报触控数据。关于电容触摸屏多点触控驱动程序的介绍,不在本章节描述之列。本章节重在实现多点触控的QT应用程序。

嵌入式QT电容屏多点触控应用程序,是基于qTUIO库和mtdev库来实现的。qTUIO是国外一位开发者编写的第三方库,这个第三方库在本地UDP套接字上实现了一个基于TUIO协议的监听器,然后把监听到的事件转发到QT的内部事件系统。mtdev是一个独立的库,它可以将来自内核的MT事件转换为时隙类型的B协议,这些MT事件可能来自内核中所有的MT设备。

总的来说,mtdev库可以把内核上报的多点触摸事件,通过mtdev2tuio后台应用程序(后面会讲到这个应用程序的移植),转换为TUIO协议,然后QT应用程序可以使用qTUIO库对内核上报的触摸事件进行处理。

以下是多点触控应用程序(涂鸦画板)运行时的界面:

界面描述:

(1)手写板界面,可以用多个手指同时涂鸦,最多支持5点同时触摸。

(2)Options里面有clear screen按钮,可以进行清屏。

本章节主要分以下两个步骤进行讲述:

(1) 在i.MX6UL开发板上移植 qTUIO 库,使其支持嵌入式QT多点触摸应用程序开发。

(2) 基于 qTUIO 库,编写一个QT多点触控应用程序。(手写板应用程序)

一、在i.MX6UL开发板上移植qTUIO库

在i.MX6UL开发板上移植qTUIO库,需要依赖以下的第三方库:liblo,mtdev,mtdev2tuio,qTUIO。

通过以下网址,下载以上的第三方依赖库:

https://github.com/x29a/qTUIO

https://github.com/olivopaolo/mtdev2tuio

http://bitmath.org/code/mtdev/

http://liblo.sourceforge.net/

如果不能访问以上网址,也可以使用作者下载好的文件:

链接:https://pan.baidu.com/s/17l6LonZuh8U7axVRQ4TV-w        提取码:gvo7

(1)下载完成后,把下载好的文件,通过FileZilla工具上传到ubuntu系统,作者上传到ubuntu的/opt/work/tools/qt_multitouch/目录,以上依赖库的交叉编译也是基于该目录进行,把下载好的文件进行解压,并创建好各个依赖库的安装目录,如下图所示。

以上依赖库的交叉编译顺序是:liblo  -->  mtdev  -->  mtdev2tuio  -->  qTUIO。交叉编译完的文件,统一存放在 imx6ul-rootfs目录,方便移植到开发板。

(2)在ubuntu系统的命令行终端,执行以下命令,配置交叉编译环境。

#export CC=/opt/EmbedSky/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
#export CXX=/opt/EmbedSky/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++

(3)先交叉编译liblo库,执行以下命令进行交叉编译:

#cd /opt/work/tools/qt_multitouch/liblo-0.26
#export SKIP_RMDIR_CHECK=yes
#./configure --prefix=/opt/work/tools/qt_multitouch/liblo_install --host=arm
#make clean
#make
#make install

交叉编译成功后,会在 liblo_install 目录下生成bin、include、lib目录,如下图所示:

执行以下命令,把生成的三个目录都复制到imx6ul-rootfs文件夹:

#cp  /opt/work/tools/qt_multitouch/liblo_install/*  /opt/work/tools/qt_multitouch/imx6ul-rootfs/  -a

(4)然后,再交叉编译mtdev库,执行以下命令进行交叉编译:

#cd /opt/work/tools/qt_multitouch/mtdev-1.1.3
#./configure --prefix=/opt/work/tools/qt_multitouch/mtdev_install --host=arm
#make clean
#make
#make install

交叉编译成功后,会在 mtdev_install 目录下生成 bin、include、lib 目录,如下图所示:

执行以下命令,把生成的三个目录都复制到imx6ul-rootfs文件夹:

#cp  /opt/work/tools/qt_multitouch/mtdev_install/*  /opt/work/tools/qt_multitouch/imx6ul-rootfs/  -a

(5)接着,再交叉编译 mtdev2tuio-master 后台程序,mtdev2tuio 后台程序是连接mtdev与qTUIO的桥梁,在运行基于qTUIO库编写的应用程序前,需要先运行mtdev2tuio,与以上两个依赖库不同,mtdev2tuio-master源码里面已经有Makefile文件,交叉编译过程可以基于此Makefile进行,修改 /opt/work/tools/qt_multitouch/mtdev2tuio-master/Makefile 内容,如下图所示:

修改完Makefile文件后,执行以下命令,进行交叉编译:

#cd /opt/work/tools/qt_multitouch/mtdev2tuio-master
#make clean
#make

交叉编译完成后,会在源码目录下生成 mtdev2tuio 应用程序,如下图所示:

执行以下命令,把mtdev2tuio应用程序复制到 imx6ul-rootfs的bin目录:

#cd  /opt/work/tools/qt_multitouch/mtdev2tuio-master/
#cp  ./mtdev2tuio  /opt/work/tools/qt_multitouch/imx6ul-rootfs/bin  -a

(6)最后,交叉编译qTUIO库。qTUIO库是一个QT工程,其工程的.pro文件以及源码目录是:/opt/work/tools/qt_multitouch/qTUIO-master/src,可以使用qmake工具进行生成Makefile文件,再交叉编译。执行以下命令,进行交叉编译。

#cd /opt/work/tools/qt_multitouch/qTUIO-master
#rm -rf /opt/work/tools/qt_multitouch/qTUIO-master/lib/*
#cd src/
#/opt/EmbedSky/TQIMX6UL/TQ_COREB/imx6ul_rootfs/opt/qt-4.8.7/bin/qmake
#make clean
#make

交叉编译成功后,会在/opt/work/tools/qt_multitouch/qTUIO-master/lib文件夹下生成qTUIO的动态链接库,如下图所示:

执行以下命令,把这些动态链接库,复制到imx6ul-rootfs的lib目录:

#cd  /opt/work/tools/qt_multitouch/qTUIO-master/
#cp  ./lib/*  /opt/work/tools/qt_multitouch/imx6ul-rootfs/lib  -a

(7)完成以上工作后,imx6ul-rootfs目录下各个文件夹里面的内容分别如下图所示:

imx6ul-rootfs/bin目录的内容

imx6ul-rootfs/include目录的内容

imx6ul-rootfs/lib目录的内容

(8)最后,把imx6ul-rootfs/bin目录的文件复制到i.MX6UL开发板的/bin目录,把imx6ul-rootfs/include目录的文件复制到i.MX6UL开发板的/include目录,把imx6ul-rootfs/lib目录的文件复制到i.MX6UL开发板的/usr/lib目录,复制完成后,如下图所示:

(9)至此,qTUIO库已经全部移植到i.MX6UL开发板,开发板已经支持运行基于qTUIO库编写的多点触摸应用程序,为了方便应用程序运行前不用手动运行mtdev2tuio后台程序,我们把该后台程序设置为开机自启动,修改 /etc/embedsky_env文件,如下图所示:

/bin/mtdev2tuio  /dev/input/cap_ts  & 表示监控 /dev/input/cap_ts节点,该节点是电容触摸屏的设备节点,内核里面的的电容触摸事件都是通过该节点进行上报,应用程序通过该节点捕获电容触摸事件,然后进行处理。

二、基于qTUIO库编写QT多点触控应用程序

(1)先用Qt Creator构建一个工程,命名为:010_multi_touch,关于如何构建工程,请参考“第一个嵌入式QT应用程序”的具体内容。与以往的程序不同,此次构建的工程,基类选择QMainWindow类。

(2)在编写代码前,我们需要把上一步骤移植好的qTUIO动态库和头文件复制到工程中,复制完成后,如下图所示:

其中,3rdparty目录直接从 /opt/work/tools/qt_multitouch/qTUIO-master/src 复制,并删除目录里面所有的非 .h 文件,只保留 .h 头文件。

(3)在工程目录上,右键 --> 添加库,如下图所示:

(4)选择添加“外部库”,点击下一步,在弹出的对话框中,平台选择Linux,库文件选择刚刚添加进工程的libqTUIO.so,然后点击下一步,如下图所示:

(5)动态链接库添加完成后,010_multi_touch.pro文件如下图所示:

(6)为了方便在界面上进行涂鸦绘画,我们创建一个ScribbleArea类,这个类继承于QWidget类,包含了清屏函数,以及重构的绘画事件函数,窗口大小调整函数,系统事件捕获函数,等等。类的具体内容如下图所示:

class ScribbleArea : public QWidget
{Q_OBJECTpublic:ScribbleArea(QWidget *parent = 0);public slots:void clearImage();   //清屏函数protected:void paintEvent(QPaintEvent *event);    //绘画事件函数void resizeEvent(QResizeEvent *event);  //窗口大小调整的事件函数bool event(QEvent *event);   //系统事件处理函数private:void resizeImage(QImage *image, const QSize &newSize);   //重新调整窗口大小QList<QColor> myPenColors;  //画笔颜色QImage image;   //窗口图像
};

(7)在ScribbleArea类的构造函数中,我们设置该类对象可以捕获触摸事件,并初始化设置画笔的颜色,该类的构造函数如下图所示:

ScribbleArea::ScribbleArea(QWidget *parent) : QWidget(parent)
{setAttribute(Qt::WA_AcceptTouchEvents);   //接收touch事件setAttribute(Qt::WA_StaticContents);      //设置静态的窗口部件myPenColors<< QColor("green")<< QColor("purple")<< QColor("red")<< QColor("blue")<< QColor("yellow")<< QColor("pink")<< QColor("orange")<< QColor("brown")<< QColor("grey")<< QColor("black");
}

(8)当系统有触摸事件上报时,应用程序会调用bool ScribbleArea::event(QEvent *event)函数,实际上,这个被重构的event函数不仅仅只在触摸事件发生时被调用,对于一般的系统事件,这个函数也会被调用,在这个event函数里面,我们只处理QEvent::TouchBegin,QEvent::TouchUpdate,QEvent::TouchEnd事件,其他时间忽略不进行处理。event函数的内容如下图所示:

//系统事件处理函数
bool ScribbleArea::event(QEvent *event)
{switch (event->type()){case QEvent::TouchBegin:     //触摸开始事件case QEvent::TouchUpdate:    //触摸更新事件case QEvent::TouchEnd:       //触摸结束事件{//获取触摸事件中所有的触摸点列表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 movedcontinue;default:{QRectF rect = touchPoint.rect();  //获取触摸点的矩形区域if (rect.isEmpty())   //如果矩形区域空白{qreal diameter = qreal(20);rect.setSize(QSizeF(diameter, diameter));  //重置触摸点的大小rect.setX(touchPoint.pos().x() - 0);    //重置触摸点的x,y位置rect.setY(touchPoint.pos().y() - 0);}QPainter painter(&image);painter.setPen(Qt::NoPen);   //不使用画笔painter.setBrush(myPenColors.at(touchPoint.id() % myPenColors.count())); //使用画刷painter.drawEllipse(rect); //根据给定的矩形区域,绘制一个椭圆点painter.end();    //绘制完成int rad = 2;update(rect.toRect().adjusted(-rad,-rad, +rad, +rad));  //更新绘制的区域}break;}}break;}default:return QWidget::event(event);}return true;
}

在该函数里面,只处理三种触摸事件,先获取触摸事件里面的所有触摸点,然后根据该触摸点的坐标和矩形大小,绘制椭圆点,然后调用update函数更新绘制的区域,update函数被调用的时候,void ScribbleArea::paintEvent(QPaintEvent *event)事件函数就会被触发。

(9)图形会在void ScribbleArea::paintEvent(QPaintEvent *event)事件函数里面绘制,函数的内容如下图所示:

//paintEvent重绘事件,在调用QWidget::update()函数后被触发
void ScribbleArea::paintEvent(QPaintEvent *event)
{QPainter painter(this);const QRect rect = event->rect();    //构造一个矩形painter.drawImage(rect.topLeft(), image, rect);  //重新绘制这个矩形
}

(10)在MainWindow的窗体构造函数里实例化一个ScribbleArea对象,并把该对象设置为MainWindow的中心窗体,然后绘制一个菜单栏,并重置窗体的大小。代码如下图所示:

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{scribbleArea = new ScribbleArea;    //实例化一个scribbleArea对象setCentralWidget(scribbleArea);     //设置中心窗体createActions();     //设置清屏按钮createMenus();       //创建菜单栏setWindowTitle(tr("Finger Paint"));    //修改窗体titleresize(800, 480);    //重置窗体大小
}

(11)在应用程序的入口int main(int argc, char *argv[])函数里面,使用QTuio类实例化一个对象qTUIO,该对象引用了MainWindow类对象进行实例化,然后运行qTUIO.run()函数,这样,qTUIO就可以监听系统的多点触摸事件,当系统有多点触摸事件上报时,qTUIO会把这些事件转换为Qt内部可以处理的系统事件,方便Qt应用程序进行处理,main函数的内容如下图所示:

int main(int argc, char *argv[])
{QApplication app(argc, argv);MainWindow window;window.show();QTuio qTUIO(&window);qTUIO.run();return app.exec();
}

(12)至此,整个多点触摸应用程序已经开发完成,编译下载到开发板,应用程序运行的现象如下图所示。

关于qTUIO库的实现机制和实现原理,作者没有进行太多深入的研究和分析,网上对于该库的讲解资料也比较少。根据移植过程的分析,大概可以推断系统的MultiTouch事件会被mtdev库捕获,然后这些事件会通过mtdev2tuio通过TUIO协议转发到qTUIO库,最后qTUIO库把这些多点触摸事件转换为Qt系统内部可处理的事件。qTUIO库的源代码里提供了这个库的使用例程,例程源码在 qTUIO-master/examples/ 目录里面,感兴趣的开发者可以进行移植测试。如对qTUIO库有比较深入的研究,或者发现以上的移植过程有纰漏,欢迎联系作者并指正,谢谢。

嵌入式Linux应用程序开发-(10)i.MX6UL基于嵌入式QT实现电容屏多点触控相关推荐

  1. 嵌入式Linux应用程序开发视频教程-曹国辉-专题视频课程

    嵌入式Linux应用程序开发视频教程-1834人已学习 课程介绍         本课程是嵌入式研发精英培养计划的核心课程,重点讲解嵌入式Linux应用程序开发核心技术,包括嵌入式Linux开发工具的 ...

  2. 《嵌入式 Linux应用程序开发标准教程(第2版)》——第1章 Linux快速入门 1.1 嵌入式Linux基础...

    本节书摘来自异步社区<嵌入式 Linux应用程序开发标准教程(第2版)>一书中的第1章,第1.1节,作者 华清远见嵌入式培训中心,更多章节内容可以访问云栖社区"异步社区" ...

  3. 《嵌入式 Linux应用程序开发标准教程(第2版)》——1.1 嵌入式Linux基础

    本节书摘来异步社区<嵌入式 Linux应用程序开发标准教程(第2版)>一书中的第1章,第1.1节,作者:华清远见嵌入式培训中心,更多章节内容可以访问云栖社区"异步社区" ...

  4. 嵌入式linux 添加中断,《嵌入式linux应用程序开发完全手册》中断控制器操作(外部中断)学习笔记...

    <嵌入式linux应用程序开发完全手册>中断控制器操作(外部中断)学习笔记 一.ARM中断体系 当一个"异常"发生时,或者说当收到一个中断触发信号时,ARM9将会自动完 ...

  5. 嵌入式LINUX系统程序开发

    嵌入式LINUX系统程序开发 1.Ubuntu 18.04镜像源配置 2.Ubuntu上用gcc进行编写程序 2.1.gcc的安装 2.2.gcc的常用命令 2.3.编译运行程序 3.Windows下 ...

  6. 《从实践中学嵌入式Linux应用程序开发》pdf完整版资源分享

    <从实践中学嵌入式Linux应用程序开发> 内容简介: <从实践中学嵌入式linux应用程序开发>结合大量实例,讲解了嵌入式linux应用程序设计各个方面的基本方法及必要的核心 ...

  7. 《嵌入式Linux应用程序开发详解》PDF完整版及源代码

     <嵌入式Linux应用程序开发详解>PDF完整版及源代码 免费下载地址在 http://linux.linuxidc.com 用户名与密码都是www.linuxidc.com 具体目 ...

  8. 嵌入式Linux应用程序开发-(1)第一个嵌入式QT应用程序

    第一个嵌入式QT应用程序 在成功安装 Qt Creator 开发环境后,我们通过一个简单的嵌入式Qt应用程序,来说明一下如何构建和编译一个Qt界面应用程序. 关于如何安装并构建 Qt Creator ...

  9. 嵌入式linux qt 开源,嵌入式Linux应用程序开发-(1)第一个嵌入式QT应用程序

    第一个嵌入式QT应用程序 在成功安装Qt Creator开发环境后,我们通过一个简单的嵌入式Qt应用程序,来说明一下如何构建和编译一个Qt界面应用程序. 关于如何安装并构建Qt Creator开发环境 ...

最新文章

  1. WebStorm错误--无法显示文件夹目录
  2. 计算机二本生不学编程还能干什么6,不建议二本考生报考的6个专业,除非真的感兴趣!...
  3. s:action,s:param的用法
  4. php4 class,PHP在类中获得当前class名称_php
  5. app每秒并发数_性能测试连载 (38) jmeter 线程数与性能测试的负载模式
  6. kafka介绍和集群环境搭建
  7. 数据结构—链表-单链表应用-删除元素最大的节点
  8. python小型登录系统_python实现用户登录系统
  9. 一张图让你读懂鹅厂的物联网框架
  10. Linux系统下poll的使用方式
  11. web自动化测试---第一个自动化测试用例
  12. 网络编程(基于udp协议的套接字/socketserver模块/进程简介)
  13. MatConvnet工具箱文档翻译理解五
  14. fx2n4ad模块中文手册_特殊功能模块FX2N-4AD用户指南手册三菱FX2N-4AD手册 - 广州凌控...
  15. 感染所有html病毒代码,非常简单的病毒代码汇总
  16. kafka开启kerberos,报错server not found in kerberos database
  17. 打印表格留标题怎么设置_WPS怎么设置打印表格每页都有标题?
  18. 基于 Verilog 的经典数字电路设计(3)选择器
  19. vue slideup_像jQuery的slideUp / slideDown一样,但是对于Vue
  20. 电脑怎么用c语言写丘比特,C语言丘比特#includebr/#includebr/ 爱问知识人

热门文章

  1. ubuntu 16.04安装WPS出现系统缺失字体
  2. 苹果电脑系统恢复数据怎么操作?
  3. 零均值归一化互相关(Zero Mean Normalized Cross-Correlation)
  4. 嵌入式开发笔记-Arduino UNO入门
  5. nprogress插件 进度条
  6. 精通安卓性能优化-第七章(二)
  7. Ubuntu20.04 上学习DPDk21.11
  8. 用友U8 admin忘记密码?
  9. 什么是翻拍识别_图像识别api
  10. java获取界面输入数字_Java练习题-从键盘接受一个数字,列出该数字的中文表示格式...