Qt之深入理解gesture

Qt最新的版本4.7中有五個gesture,分別是QPanGesture, QPinchGesture, QSwipeGesture, QTapAndHoldGesture, and QTapGesture, 前三個比較常用,但用過的人仍然很少,很多人人對這個gesture意思感覺也陌生,更不用說對說出他們之間的區別了。這裏我先解釋一下:
Pan Gesture就是指一個手指在屏幕上滑動,當滑動距離超過一定大小時就產生了一個Pan Gesture的事件了,如下圖所示:

Pinch Gesture就是兩指放在屏幕上,靠近或者遠離,就像捏東西一樣,如下圖所示:

Swipe Gesture就是一個手指在屏幕上沿着一個固定的方向滑動,滑動一段距離時就產生了一個Swipe Gesture的事件,如下圖所示:

QTapAndHoldGesture和QTapGesture比較簡單這裏我就偷個懶不說了,哈哈。
Gesture是個手勢,但是個組合拳,過濾Gesture是消耗很大的,一般來說它要過濾好幾個事件,要與你要截獲的Gesture對比,看有沒有可能是你要的那個手勢,如果所有事件都會做很多無用功,因此只有真的我們需要截獲那個gesture時纔會讓系統幫我們這麼做。

我比較喜歡看源碼說事,就來看看
每個gesture都有對應的gesture recognizer(手勢識別類)來識別這個gesture,比如QPanGesture,它就有QPanGestureRecognizer。可有了gesture recognizer,系統就認識你這個gesture了嗎?不是,你還要將你的gesture recognizer註冊到QGestureManager中,而QGestureManager則統一管理所有的gesture recognizer,系統只要通過QGestureManager就可以來識別相應的gesture。讓我們來看看QGestureManager的構造函數源碼:
  1. QGestureManager::QGestureManager(QObject *parent)
  2.     : QObject(parent), state(NotGesture), m_lastCustomGestureId(0)
  3. {
  4.     qRegisterMetaType<Qt::GestureState>();
  5. #if defined(Q_WS_MAC)
  6.     registerGestureRecognizer(new QMacSwipeGestureRecognizer);
  7.     registerGestureRecognizer(new QMacPinchGestureRecognizer);
  8.   #if defined(QT_MAC_USE_COCOA)
  9.     registerGestureRecognizer(new QMacPanGestureRecognizer);
  10.   #endif
  11. #else
  12.     registerGestureRecognizer(new QPanGestureRecognizer);
  13.     registerGestureRecognizer(new QPinchGestureRecognizer);
  14.     registerGestureRecognizer(new QSwipeGestureRecognizer);
  15.     registerGestureRecognizer(new QTapGestureRecognizer);
  16. #endif
  17. #if defined(Q_OS_WIN)
  18.   #if !defined(QT_NO_NATIVE_GESTURES)
  19.     if (QApplicationPrivate::HasTouchSupport)
  20.         registerGestureRecognizer(new QWinNativePanGestureRecognizer);
  21.   #endif
  22. #else
  23.     registerGestureRecognizer(new QTapAndHoldGestureRecognizer);
  24. #endif
  25. }
複製代碼
上面的代碼很簡單這裏我只簡單說說,registerGestureRecognizer就是用來註冊gesture recognizer的,剛開始說的五個gesture在這裏都註冊了。
我們再了看看registerGestureRecognizer函數:
  1. Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer)
  2. {
  3.     //這裏也用你的recognizer創建一個你的gesture實例,如果沒有創建成功就
  4.     //返回Qt::GestureType(0),表示註冊失敗
  5.     QGesture *dummy = recognizer->create(0);
  6.     if (!dummy) {
  7.         qWarning("QGestureManager::registerGestureRecognizer: "
  8.                  "the recognizer fails to create a gesture object, skipping registration.");
  9.         return Qt::GestureType(0);
  10.     }
  11.     //Code A
  12.     //這裏如果發現你的gestureType是CustomGesture則會
  13.     //返回Qt::GestureType(Qt::CustomGesture + m_lastCustomGestureId)
  14.     //即在Qt::CustomGesture基礎上加一個數字,如果是註冊第一個的自定義的gesture,
  15.     //這裏的m_lastCustomGestureId就是1,再註冊就加2,以此類推
  16.     //這裏對我們理解自定義gesture很有幫助:)
  17.     Qt::GestureType type = dummy->gestureType();
  18.     if (type == Qt::CustomGesture) {
  19.         // generate a new custom gesture id
  20.         ++m_lastCustomGestureId;
  21.         type = Qt::GestureType(Qt::CustomGesture + m_lastCustomGestureId);
  22.     }
  23.     m_recognizers.insertMulti(type, recognizer);
  24.     delete dummy;
  25.     return type;
  26. }
複製代碼
上面代碼中註釋的應該比較全,這裏我只就Code A部分說一下,如果我自定義一個gesture時,無需管它的gesture類型,也不用重新實現它的gestureType方法,默認的就是Qt::CustomGesture,這裏的你的gesture類型id你可以通過調用QGestureRecognizer::registerRecognizer方法的返回值來獲得,也可以根據上面的代碼在Qt::CustomGesture基礎上加上相應的數字來得到。

說完這些,讓我們來看看有關gesture的事件傳遞的過程:
當你通過調用QWidget::grabGesture來截獲相應的gesture手勢時
如果你想截獲某個手勢,你需要調用QWidget::grabGesture方法來截獲相應的手勢類型,我們來看看QWidget::grabGesture方法源碼:
  1. void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
  2. {
  3.     Q_D(QWidget);
  4.     //這裏先向gestureContext,即手勢上下文,插入這個gesture類型
  5.     //gestureContext是屬於這個widget的QWidgetPrivate的,可見這裏的截獲事件緊限於這個widget
  6.     d->gestureContext.insert(gesture, flags);
  7.    // 創建gesture manager,這裏用的是單例模式,哈哈
  8.     (void)QGestureManager::instance(); 
  9. }
複製代碼
這樣之後,當事件最終通過經過QApplication::notify方法處理時,如果發現接受事件的widet有截獲gesture時,就會將事件叫給gesture manager來過濾。
整個過程事件傳遞如下圖所示:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章