Qt使用电容屏

时间:2024-02-16 07:22:43

Qt 5.x 相对于 4.8 及以前版本在窗口系统上有较大幅度改动,原来的 QWS 被 QPA 完全取代,导致输入设备配置简化了很多,执行界面程序也不需要再加上-qws


找到触摸屏event

用的 USB 接口驱动触摸屏,当你插入 usb 的电容屏时,在 dev/input 下面会出现相应的设备节点。假如cat /dev/event0,触摸屏幕有乱码输出,则说明 usb 触摸屏驱动产生中断并且将采集数据上报 input 子系统了。

另外也可以使用 hexdump 命令,它是 Linux 下的一个二进制文件查看工具,它可以将二进制文件转换为 ASCII、八进制、十进制、十六进制格式进行查看,默认显示十六进制格式,使用 -d 命令参数显示十进制,详细使用参考:Linux命令学习总结:hexdump


使用 hexdump 命令查看触摸信息,快速触摸屏幕右下角后的打印信息如下:

$ hexdump -d /dev/input/event0
0000000   15989   00000   18969   00004   00004   00004   00001   00009 # 其它事件
0000010   15989   00000   18969   00004   00001   00272   00001   00000 # BTN_MOUSE,按下
0000020   15989   00000   18969   00004   00003   00000   16333   00000 # ABS_X
0000030   15989   00000   18969   00004   00003   00001   09599   00000 # ABS_Y
0000040   15989   00000   18969   00004   00000   00000   00000   00000 # 同步事件
0000050   15989   00000   49415   00005   00004   00004   00001   00009 # 其它事件
0000060   15989   00000   49415   00005   00001   00272   00000   00000 # BTN_MOUSE,松开
0000070   15989   00000   49415   00005   00000   00000   00000   00000 # 同步事件

倒数第四、三、二行分别为 type、code 和 value,在 linux/input.h 都有定义,Linux 中输入设备的事件类型有:

#define EV_SYN 0x00 // 同步事件
#define EV_KEY 0x01 // 按键事件
#define EV_REL 0x02 // 相对坐标
#define EV_ABS 0x03 // 绝对坐标
#define EV_MSC 0x04 // 其它事件
  • type 是事件类型,为 3 就是 EV_ABS=0x03,为 0 就是 EV_SYN=0x00(作为事件的分隔)。

  • code 的话根据事件类型而定,如果是 type 为 EV_ABS,code 为 0 就是 ABS_X,code 为 1 就是 ABS_Y。

  • 然后 value 就是在 type 和 code 的前提下的值,比如 type 为 EV_ABS,code 为 0 就是 ABS_X,那么 value 就代表触摸点的 x 轴绝对值。

  • 比如 type 为 EV_KEY,code 为 272 就是 BTN_MOUSE,code 为 330 就是 BTN_TOUCH,那么 value 为 1 表示按下,为 0 表示松开。比如 type 为 EV_ABS,code 为 24 就是 ABS_PRESSURE,value 为 1 表示按下,为 0 表示松开。

测试看出触摸屏触摸产生的坐标值范围为 X:016384,Y:09600,同时该触摸屏没有上传 ABS_PRESSURE。


通过 cat /proc/bus/input/devices 应该就能够看到触摸设备的相关信息。比如:

$ cat /proc/bus/input/devices
I: Bus=0003 Vendor=222a Product=0001 Version=0110
N: Name="ILITEK ILITEK-TP"
P: Phys=usb-11000000.xhci-1.4/input1
S: Sysfs=/devices/soc/11000000.xhci/usb1/1-1/1-1.4/1-1.4:1.1/0003:222A:0001.0004/input/input2
U: Uniq=
H: Handlers=mouse0 js0 event0
B: PROP=0
B: EV=1b
B: KEY=1f0000 0 0 0 0 0 0 0 0
B: ABS=3
B: MSC=10

上面的信息有触摸屏 vid,pid,版本等,以及 ABS 表示触摸屏的绝对坐标掩码,掩码上面表示 16 进制,所以 3=0x0000003=0000 0000 0000 0000 0000 0000 0011,其中为 1 的比特的位置就表示触摸屏会报告这一类型的事件,前面的 bit0 和 bit1,那么看 linux/input.h 文件就表示事件 code 码有 ABS_X=0x00 , ABS_Y=0x01, 这两个分别表示触摸屏报告触摸的 x 坐标,y 坐标。而 bit24 为 0,则表示触摸屏驱动没有上传 ABS_PRESSURE。详情请参考:linux读取触摸屏事件数据


Qt使用电容屏

使用电容屏的 Qt 程序,不用移植 tslib 库,就可以直接读取输入设备文件(/etc/input/eventx),除非需要 tslib 校准。另外 Qt4 默认支持触屏,而 Qt5 需要设置环境变量才能支持触屏:

export QT_LOGGING_RULES=qt.qpa.input=true # 打印触屏信息
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0 # 指定输入设备的名称
export QT_QPA_EVDEV_MOUSE_PARAMETERS=/dev/input/event0 # 将触摸屏的点击事件配置成Qt的鼠标点击事件
export QT_QPA_FB_HIDECURSOR=1 # 为1则隐藏鼠标光标,为0则显示鼠标光标
  • 对于 Qt5,设置环境变量QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS
    ,Qt5 自身的 libinput 就会去/dev/input/eventX读取触摸屏数据(未校准),从而使触摸正常工作。
  • 将触摸屏的点击事件配置成 Qt 的鼠标点击事件后,会产生有一个鼠标光标。

电容屏的校准

触摸屏配置可分两种方式,一种是电容屏或由驱动校准的电阻屏配置,另一种是需要借助 tslib 校准的电阻屏配置。

所以电容屏本身是不需要校准的,不过和 Qt 配合的话就需要重新校准:

一、Qt 本身提供了一个校准软件,叫做 mousecalibration,不过只能支持 Embedded Linux(嵌入式 Linux),软件在 example->qws 目录下面,可以完成校准。但是由于不同的嵌入式平台采用的芯片差异性很大,所以这个校准程序往往无法使用。其详细说明参考:Mouse Calibration Example

二、使用 tslib校准:带 tslib 校准的方式需要移植最新版 tslib 库,再编译 Qt 源码或插件(Qt 自带的插件可以单独编译,自带插件不支持多点触摸),编译时加入 tslib 到编译选项。移植到嵌入式设备后,配置 tslib 校准服务开机启动,之后配置 Qt 宏默认使用 tslib 插件作为默认输入插件。


1、校准原理说明

分辨率转化和校准
其实触摸屏触摸产生的坐标值是绝对坐标,范围为 X:016384,Y:09600。所以,我们运行的 Qt 程序如果直接获取 /dev/input/eventx 产生的坐标的话,鼠标位置便会超出屏幕的显示范围(1920*1080),因此,我们需要进行一下坐标值转化。


参考:

linux内核usb触摸屏驱动bug调试- selected device is not a touchscreen I understand

Qt 5.x 多点触摸配置

树莓派触摸屏校准以及QT触摸屏相关问题解决

Qt使用电容屏

Qt-4.8.4使用电容触摸屏

Qt4.7.0 使用电容屏

5.8 的移植