Copy了一份实现单指滑动手势的源码。
Qt的SwipeGesture居然是要三个手指同时操作(这里是说用widget而不是用quick控件,实际上quick控件才是Qt为移动开发打造的)。把源码拿出来看了半天,看是能够看懂,可以就是改了就无法编译了。在GitHub上用搜索功能,终于找到了直接可用的方案(神奇的GitHub):
头文件,这里面的宏定义MINIMUM_DISTANCE = 50是可以根据需要修改的
// customGesture.h
#ifndef CUSTOMGESTURE_H
#define CUSTOMGESTURE_H
#include <QGesture>
#include <QGestureRecognizer>
#include <QSwipeGesture>
/**
* @brief The SwipeGestureRecognizer class
* needed because the defalt implementation of swipe is a little bit odd: it only triggers on 3 finger swipes! (5.3)
*
* http://developer.android.com/design/patterns/gestures.html
* http://qt-project.org/doc/qt-5/gestures-overview.html
*/
class SwipeGestureRecognizer : public QGestureRecognizer
{
public:
SwipeGestureRecognizer();
private:
#ifdef FOR_DESKTOP
static const int MINIMUM_DISTANCE = 50;
#endif
#ifdef FOR_MOBILE
static const int MINIMUM_DISTANCE = 50;
#endif
typedef QGestureRecognizer parent;
bool IsValidMove(int dx, int dy);
qreal ComputeAngle(int dx, int dy);
virtual QGesture* create(QObject* pTarget);
virtual QGestureRecognizer::Result recognize(QGesture* pGesture, QObject *pWatched, QEvent *pEvent);
void reset (QGesture *pGesture);
};
class SwipeGestureUtil {
public:
static QSwipeGesture::SwipeDirection GetHorizontalDirection(QSwipeGesture *pSwipeGesture);
static QSwipeGesture::SwipeDirection GetVerticalDirection(QSwipeGesture *pSwipeGesture);
};
#endif // CUSTOMGESTURE_H
源文件
// customGesture.cpp
#include <QMouseEvent>
#include <QDebug>
#include <cmath>
#include "customgesture.h"
SwipeGestureRecognizer::SwipeGestureRecognizer()
{
}
bool
SwipeGestureRecognizer::IsValidMove(int dx, int dy)
{
// The moved distance is to small to count as not just a glitch.
if ((qAbs(dx) < MINIMUM_DISTANCE) && (qAbs(dy) < MINIMUM_DISTANCE)) {
return false;
}
return true;
}
// virtual
QGesture*
SwipeGestureRecognizer::create(QObject* pTarget)
{
//qDebug("SwipeGestureRecognizer::create() called");
QGesture *pGesture = new QSwipeGesture(pTarget);
return pGesture;
}
// virtual
QGestureRecognizer::Result
SwipeGestureRecognizer::recognize(QGesture* pGesture, QObject *pWatched, QEvent *pEvent)
{
QGestureRecognizer::Result result = QGestureRecognizer::Ignore;
QSwipeGesture *pSwipe = static_cast<QSwipeGesture*>(pGesture);
switch(pEvent->type()) {
case QEvent::MouseButtonPress: {
QMouseEvent* pMouseEvent = static_cast<QMouseEvent*>(pEvent);
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
pSwipe->setProperty("startPoint", pMouseEvent->posF());
#else
pSwipe->setProperty("startPoint", pMouseEvent->localPos());
#endif
result = QGestureRecognizer::MayBeGesture;
//qDebug() << "Swipe gesture started (start point=" << pSwipe->property("startPoint").toPointF() << ")";
}
break;
case QEvent::MouseButtonRelease: {
QMouseEvent* pMouseEvent = static_cast<QMouseEvent*>(pEvent);
const QVariant& propValue = pSwipe->property("startPoint");
QPointF startPoint = propValue.toPointF();
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
QPointF endPoint = pMouseEvent->posF();
#else
QPointF endPoint = pMouseEvent->localPos();
#endif
// process distance and direction
int dx = endPoint.x() - startPoint.x();
int dy = endPoint.y() - startPoint.y();
//bugfix: startPoint.isNull because we sometimes get false events with startpoint 0 -> wrong swipe detected!
if ( (!IsValidMove(dx, dy)) || ( startPoint.isNull() ) ) {
// Just a click, so no gesture.
result = QGestureRecognizer::CancelGesture;
//qDebug("Swipe gesture canceled");
} else {
// Compute the angle.
//qDebug() << " startPoint= " << startPoint << " endPoint=" << endPoint << " dx=" << dx << " dy=" << dy;
qreal angle = ComputeAngle(dx, dy);
pSwipe->setSwipeAngle(angle);
result = QGestureRecognizer::FinishGesture;
//qDebug("Swipe gesture finished");
}
}
break;
default:
break;
}
return result;
}
void
SwipeGestureRecognizer::reset(QGesture *pGesture)
{
pGesture->setProperty("startPoint", QVariant(QVariant::Invalid));
parent::reset(pGesture);
}
qreal
SwipeGestureRecognizer::ComputeAngle(int dx, int dy)
{
double PI = 3.14159265;
// Need to convert from screen coordinates direction
// into classical coordinates direction.
dy = -dy;
double result = atan2((double)dy, (double)dx) ;
result = (result * 180) / PI;
// Always return positive angle.
if (result < 0) {
result += 360;
}
return result;
}
/*
==========================================================================
*/
QSwipeGesture::SwipeDirection
SwipeGestureUtil::GetHorizontalDirection(QSwipeGesture *pSwipeGesture)
{
qreal angle = pSwipeGesture->swipeAngle();
if (0 <= angle && angle <= 45) {
return QSwipeGesture::Right;
}
if (135 <= angle && angle <= 225) {
return QSwipeGesture::Left;
}
if (315 <= angle && angle <= 360) {
return QSwipeGesture::Right;
}
return QSwipeGesture::NoDirection;
}
QSwipeGesture::SwipeDirection
SwipeGestureUtil::GetVerticalDirection(QSwipeGesture *pSwipeGesture)
{
qreal angle = pSwipeGesture->swipeAngle();
if (45 < angle && angle < 135) {
return QSwipeGesture::Up;
}
if (225 < angle && angle < 315) {
return QSwipeGesture::Down;
}
return QSwipeGesture::NoDirection;
}
使用代码就很简单了,比如某个窗体的头文件
class rangeReport : public QWidget
{
Q_OBJECT
// ...
private:
// ...
SwipeGestureRecognizer *fftRecognizer;
Qt::GestureType fftType;
void swipeTriggered(QSwipeGesture *gesture);
bool event(QEvent *event);
bool gestureEvent(QGestureEvent *event);
int currentGraph;
void registerGesture();
};
而源文件就是要注册这个手势识别器,并实现手势之后的响应
rangeReport::rangeReport(rangeType type):
ui(new Ui::rangeReport)
{
ui->setupUi(this);
registerGesture();
// ...
}
// ...
bool rangeReport::event(QEvent *event)
{
if (event->type() == QEvent::Gesture){
//qDebug()<<"grab!";
return gestureEvent(static_cast<QGestureEvent*>(event));
}
return QWidget::event(event);
}
void rangeReport::swipeTriggered(QSwipeGesture *gesture)
{
if (gesture->state() == Qt::GestureFinished) {
if (gesture->horizontalDirection() == QSwipeGesture::Left
|| gesture->verticalDirection() == QSwipeGesture::Up) {
if(currentGraph != chart.size() - 1){
currentGraph ++;
ui->graph1->setChart(chart[currentGraph]);
}
} else {
if(currentGraph != 0){
currentGraph --;
ui->graph1->setChart(chart[currentGraph]);
} //?ui->tabWidget->count():ui->tabWidget->currentIndex() + 1 );
}
update();
}
}
bool rangeReport::gestureEvent(QGestureEvent *event)
{
//qDebug() << "gestureEvent():" << event;
if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
swipeTriggered(static_cast<QSwipeGesture *>(swipe));
else if (QGesture *pan = event->gesture(Qt::PanGesture))
//panTriggered(static_cast<QPanGesture *>(pan));
return true;
}
void rangeReport::registerGesture()
{
fftRecognizer = new SwipeGestureRecognizer();
fftType = QGestureRecognizer::registerRecognizer(fftRecognizer);
grabGesture(fftType);
}
最后还是要吐槽一下sqlite:我觉得这个数据库的性能特别好,查询速度很快,占用资源也少。不过为什么不支持全外连接语句让我用连接和并集写全外连接不是白白增加工作量吗?