关于Qt编写程序在触屏上的实现各种滑动触控以及手势我通过网上资料查询最先想到的是各种鼠标事件,但是鼠标事件不支持多点的触控,所以又查询得知了touchEvent,支持的多点的触控,比如做一个双指缩放图片的大小的简单daemon。首先是在win7平台配置多点触控的模拟环境使用的是WPF Multi-Touch,这个如何配置怎么使用在网上可以查到。
要下载和配置的请看这个网址https://www.cnblogs.com/gnielee/archive/2010/08/16/multi-touch-simulator.html
touchEvent
然后写一个简单的触控缩放daemon,首先要让系统接收触控事件
this->setAttribute(Qt::WA_AcceptTouchEvents);
然后去重写event()函数,在里面处理触摸事件
bool scrollbar::event(QEvent *event) {
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd: {
//此处是处理函数接收触控事件的event
}
default:
break;
}
return QWidget::event(event);
}
关于单点的触控这里就不多讲了,这里主要是说一下多点的,用双指实现缩放功能
QTouchEvent *touchEvent = static_cast
QList
if (touchPoints.count() == 1) {
//判断单点触控
}
if (touchPoints.count() == 2) {
//判断两点也就是双指缩放动作
}
然后在两点动作里面获取这四个点,因为缩放动作每一个都有一个起始点和终止点,两指的动作也就是四个点。
比如双指进行一个放大操作,有四个点,缩小操作同理
QPointF p1 = touchPoints.at(0).startPos();
QPointF p2 = touchPoints.at(0).lastPos();
QPointF p3 = touchPoints.at(1).startPos();
QPointF p4 = touchPoints.at(1).lastPos();
这里获取了这四个点。然后通过这四个点来处理放大缩小
首先来处理是否进行缩放操作,我做的处理是当这两条路径夹角大于90度才进行缩放操作
dealMultiTouch(QPointF p1, QPointF p2, QPointF p3, QPointF p4) {
if (p1 == p2 || p3 == p4) {
} else {
double delta1 = QLineF(p1, p2).length();
double delta2 = QLineF(p3, p4).length();
double delta = delta1;
if (delta1 < delta2) {
delta = delta1;
} else {
delta = delta2;
}
double x1 = p2.x() - p1.x();
double y1 = p2.y() - p1.y();
double x2 = p4.x() - p3.x();
double y2 = p4.y() - p3.y();
double aaa = x1 * x2 + y1 * y2;
double bbb = sqrt((pow(x1, 2) + pow(y1, 2)) * (pow(x2, 2) + pow(y2, 2)));
double cosA = aaa / bbb;
if (cosA < 0) {
//通过向量算出两者之间的夹角的余弦值,因为范围是(0,180,所以大于90度,余弦值必定小于0
double endL = QLineF(p2, p4).length();
double startL = QLineF(p1, p3).length();
//然后来判断是放大还是缩小操作算出两指起始点以及终止点之间的距离,如果起始点间的距离大于
//终止点间的距离则是缩小,反正放大
if (endL > startL)
{
//放大操作
}
else {
//缩小操作
}
update();//此处更新控件使之放大缩小
}
}
}
效果图如下:
缩放操作完成。
QGesture
上面可以看到做的非常麻烦一次获取四个点来处理,后来百度才知道QT的手势QGesture做比这个方便,然后也查了一下相关资料。自己把上面写的daemon改成QGesture来实现。
QGesture有几种手势,这里主要说PinchGesture 也就是缩放操作的手势,首先是头文件
#include
#include
#include
相关函数
bool event(QEvent *event);
bool gestureEvent(QGestureEvent *event);
void pinchTriggered(QPinchGesture *);
别忘了
grabGesture(Qt::PanGesture);
grabGesture(Qt::PinchGesture);
grabGesture(Qt::SwipeGesture);
来注册手势,我们只需要第二个就行了。
然后同样的重写event()函数
event(QEvent *event) {
if (event->type() == QEvent::Gesture)
return gestureEvent(static_cast
return QWidget::event(event);
}
设置缩放手势的函数
gestureEvent(QGestureEvent *event) {
if (QGesture *pinch = event->gesture(Qt::PinchGesture))
pinchTriggered(static_cast
return true;
}
在pinchTriggered里面处理缩放
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
m_scale = gesture->totalScaleFactor();
}
}
我写的这个daemon里面有一个成员变量来控制缩放系数m_scale,处理完后update(),在paintEvent里面根据m_scale来绘制图片大小。
注意点
touchEvent的单点和多点之间如果都有处理函数容易相互影响,注意处理,如果设置了鼠标事件函数比如按下、释放鼠标等事件处理也会和QGesture之间影响,我是用一个变量当缩放手势时,通过这个变量来屏蔽鼠标处理的那个函数,还有就是QGesture还有PanGesture等等,这个是手指划过的手势,但是我在模拟和触屏上面实验都没有效果,网上查了一下好像这个是qt 的一个坑,单指划过默认当成鼠标事件了。