Qt GUIの操作性を向上させる:QNativeGestureEvent::delta() 関数によるジェスチャー情報の取得と活用


用途

QNativeGestureEvent::delta() 関数は、以下の用途に使用できます。

  • ジェスチャーによる拡大・縮小率を計算する
  • ジェスチャーによる回転角度を計算する
  • ジェスチャーによる移動量を計算する

戻り値

QNativeGestureEvent::delta() 関数の戻り値は、ジェスチャーの種類によって異なります。

  • RotateNativeGesture
    回転角度をラジアン単位で返します。
  • ZoomNativeGesture
    拡大・縮小の倍率を返します。
  • PanNativeGesture
    ビューポート、ウィジェット、またはアイテムを移動またはパンする必要がある距離をピクセル単位で返します。

以下のコードは、PanNativeGesture イベントの delta() 関数を使用して、ビューポートを移動する方法を示しています。

void handleGestureEvent(QGestureEvent *event) {
  if (event->type() == QGestureEvent::Type::PanGesture) {
    QNativeGestureEvent *nativeEvent = static_cast<QNativeGestureEvent *>(event);
    QPointF delta = nativeEvent->delta();
    viewport->move(viewport->pos() + delta);
  }
}
  • ジェスチャーの種類によっては、delta() 関数が常に意味のある値を返すとは限りません。詳細については、Qt ドキュメントを参照してください。
  • QNativeGestureEvent::delta() 関数は、ジェスチャーが開始されてからの差分値を返します。絶対値ではありません。
  • Qt のバージョンによって、API や動作が異なる場合があります。
  • 本解説は、Qt 6.7.1 を基に作成されています。


class MyWidget : public QWidget {
public:
  MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
  void handleGestureEvent(QGestureEvent *event) override {
    if (event->type() == QGestureEvent::Type::PanGesture) {
      QNativeGestureEvent *nativeEvent = static_cast<QNativeGestureEvent *>(event);
      QPointF delta = nativeEvent->delta();
      viewport->move(viewport->pos() + delta);
    }
  }

private:
  QGraphicsView *viewport;
};

例 2: ZoomNativeGesture イベントを使用してビューポートを拡大・縮小する

class MyWidget : public QWidget {
public:
  MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
  void handleGestureEvent(QGestureEvent *event) override {
    if (event->type() == QGestureEvent::Type::ZoomGesture) {
      QNativeGestureEvent *nativeEvent = static_cast<QNativeGestureEvent *>(event);
      qreal zoomFactor = nativeEvent->zoomFactor();
      viewport->scale(zoomFactor, zoomFactor);
    }
  }

private:
  QGraphicsView *viewport;
};

例 3: RotateNativeGesture イベントを使用してビューポートを回転する

class MyWidget : public QWidget {
public:
  MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
  void handleGestureEvent(QGestureEvent *event) override {
    if (event->type() == QGestureEvent::Type::RotateGesture) {
      QNativeGestureEvent *nativeEvent = static_cast<QNativeGestureEvent *>(event);
      qreal rotationAngle = nativeEvent->rotationAngle();
      viewport->rotate(rotationAngle);
    }
  }

private:
  QGraphicsView *viewport;
};

説明

上記のコード例では、PanNativeGesture、ZoomNativeGesture、RotateNativeGesture イベントを使用して、ビューポートを移動、拡大・縮小、回転する方法を示しています。

  • 取得したジェスチャーの状態に基づいて、アプリケーションの動作を調整します。
  • ジェスチャーの種類に応じて、delta(), zoomFactor(), または rotationAngle() メソッドを使用して、ジェスチャーの状態を取得します。
  • event->type() メソッドを使用して、ジェスチャーの種類を判断します。
  • handleGestureEvent() 関数は、ジェスチャーイベントが検出されたときに呼び出されます。
  • ジェスチャーイベントの処理は、パフォーマンスに影響を与える可能性があります。パフォーマンスが重要な場合は、イベント処理を最適化する必要があります。
  • ジェスチャーイベントを処理する際には、ジェスチャーの開始位置と終了位置を考慮する必要があります。
  • 上記のコード例はあくまでも例であり、具体的な実装はアプリケーションの要件に応じて変更する必要があります。


代替方法

以下に、QNativeGestureEvent::delta() の代替方法をいくつか紹介します。

QGestureEvent::totalDelta() 関数を使用する

QGestureEvent::totalDelta() 関数は、ジェスチャーが開始されてからの差分値を返します。delta() 関数とは異なり、totalDelta() 関数はジェスチャーの種類に関係なく常に同じ値を返します。

void handleGestureEvent(QGestureEvent *event) {
  if (event->type() == QGestureEvent::Type::PanGesture) {
    QPointF delta = event->totalDelta();
    viewport->move(viewport->pos() + delta);
  }
}

QGestureEvent::localPos() 関数を使用する

QGestureEvent::localPos() 関数は、ジェスチャーの現在の位置を返します。この情報を使用して、ジェスチャーによる移動量を計算することができます。

void handleGestureEvent(QGestureEvent *event) {
  if (event->type() == QGestureEvent::Type::PanGesture) {
    QPointF pos = event->localPos();
    QPointF lastPos = event->lastLocalPos();
    QPointF delta = pos - lastPos;
    viewport->move(viewport->pos() + delta);
  }
}

QGestureEvent::screenPos() 関数を使用する

QGestureEvent::screenPos() 関数は、ジェスチャーの現在の位置をスクリーン座標で返します。この情報を使用して、ジェスチャーによる移動量を計算することができます。

void handleGestureEvent(QGestureEvent *event) {
  if (event->type() == QGestureEvent::Type::PanGesture) {
    QPoint pos = event->screenPos();
    QPoint lastPos = event->lastScreenPos();
    QPoint delta = pos - lastPos;
    viewport->move(viewport->pos() + delta);
  }
}

QGestureEvent::boundingRect() 関数を使用する

QGestureEvent::boundingRect() 関数は、ジェスチャーの境界矩形を返します。この情報を使用して、ジェスチャーによる移動量を計算することができます。

void handleGestureEvent(QGestureEvent *event) {
  if (event->type() == QGestureEvent::Type::PanGesture) {
    QRectF rect = event->boundingRect();
    QRectF lastRect = event->lastBoundingRect();
    QRectF delta = rect - lastRect;
    viewport->move(viewport->pos() + delta.topLeft());
  }
}

選択の指針

どの代替方法を使用するかは、状況によって異なります。

  • ジェスチャーによる移動量を計算したい場合は、localPos() 関数、screenPos() 関数、または boundingRect() 関数を使用します。
  • ジェスチャーの現在の位置を取得したい場合は、localPos() 関数または screenPos() 関数を使用します。
  • ジェスチャーの種類に関係なく常に同じ値を取得したい場合は、totalDelta() 関数を使用します。
  • ジェスチャーイベントの処理は、パフォーマンスに影響を与える可能性があります。パフォーマンスが重要な場合は、イベント処理を最適化する必要があります。
  • ジェスチャーイベントを処理する際には、ジェスチャーの開始位置と終了位置を考慮する必要があります。
  • 上記の代替方法は、あくまでも例であり、具体的な実装はアプリケーションの要件に応じて変更する必要があります。