QPinchGesture::rotationAngleのプログラミング解説


使い方

QPinchGesture::rotationAngle を使用するには、まずジェスチャーを検出する必要があります。これを行うには、QObject::gestureEvent() メソッドを再実装し、QPinchGesture イベントを処理する必要があります。

void MyWidget::gestureEvent(QGestureEvent *event)
{
    if (QGesture *gesture = event->gesture(Qt::PinchGesture)) {
        QPinchGesture *pinchGesture = static_cast<QPinchGesture *>(gesture);

        if (pinchGesture->state() == QGesture::Started) {
            // ジェスチャーが開始されたとき
            startRotationAngle = pinchGesture->rotationAngle();
        } else if (pinchGesture->state() == QGesture::Updated) {
            // ジェスチャーが更新されたとき
            qreal rotationDelta = pinchGesture->rotationAngle() - startRotationAngle;
            rotateObject(rotationDelta);
            startRotationAngle = pinchGesture->rotationAngle();
        }
    }
}

上記の例では、rotateObject() 関数は、オブジェクトを rotationDelta だけ回転します。

  • QPinchGesture::totalRotationAngle() は、ジェスチャー全体での累積的な回転角度を返します。
  • QPinchGesture::lastRotationAngle() は、前のジェスチャーイベントで報告された回転角度を返します。
  • QPinchGesture::rotationAngle() は、ジェスチャーが開始されてからの累積的な回転角度を返します。

以下の例は、画像をピンチジェスチャーで回転する方法を示しています。

class ImageWidget : public QWidget
{
public:
    ImageWidget(QWidget *parent = 0);

protected:
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

private:
    QImage image;
    qreal rotationAngle;
};

ImageWidget::ImageWidget(QWidget *parent) : QWidget(parent)
{
    image = QImage("image.png");
    rotationAngle = 0.0;
}

void ImageWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.translate(width() / 2, height() / 2);
    painter.rotate(rotationAngle);
    painter.drawImage(-image.width() / 2, -image.height() / 2, image);
}


#include <QApplication>
#include <QLabel>
#include <QImage>
#include <QPinchGesture>

class ImageWidget : public QLabel
{
public:
    ImageWidget(const QImage &image, QWidget *parent = 0);

protected:
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

private:
    QImage m_image;
    qreal m_rotationAngle;
};

ImageWidget::ImageWidget(const QImage &image, QWidget *parent) : QLabel(parent)
{
    m_image = image;
    m_rotationAngle = 0.0;

    setAttribute(Qt::WA_AcceptTouchEvents);
}

void ImageWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.translate(width() / 2, height() / 2);
    painter.rotate(m_rotationAngle);
    painter.drawImage(-m_image.width() / 2, -m_image.height() / 2, m_image);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QImage image("image.png");
    ImageWidget widget(image);
    widget.show();

    return app.exec();
}

説明

  1. ImageWidget クラスは、QLabel クラスを継承したカスタムウィジェットです。
  2. コンストラクタは、画像と親ウィジェットを受け取り、画像をメンバー変数に保存します。
  3. paintEvent() メソッドは、画像を回転させて描画します。
  4. main() 関数は、QApplication インスタンスを作成し、ImageWidget ウィジェットを作成して表示します。

このコードを実行すると、画像が表示され、ユーザーがピンチジェスチャーで画像を回転できるようになります。

  • "image.png" は、実際に使用する画像ファイル名に置き換えてください。
  • このコードは、Qt 6.x でコンパイルして実行することを想定しています。


QPinchGesture::centerPoint() を使用して回転を計算する

QPinchGesture::centerPoint() は、ピンチ ジェスチャーの中心点を取得するためのプロパティです。 この情報を使用して、ジェスチャー開始時の 2 点と現在の 2 点間の角度差を計算することで、回転角度を計算することができます。

利点

  • ジェスチャーの中心点に焦点を当てる必要がある場合に役立ちます。
  • QPinchGesture::rotationAngle を使用しない方法で回転角度を取得できます。

欠点

  • ジェスチャーの中心点の正確な位置が常に必要です。
  • QPinchGesture::rotationAngle よりも計算量が多くなります。


void MyWidget::gestureEvent(QGestureEvent *event)
{
    if (QGesture *gesture = event->gesture(Qt::PinchGesture)) {
        QPinchGesture *pinchGesture = static_cast<QPinchGesture *>(gesture);

        if (pinchGesture->state() == QGesture::Started) {
            // ジェスチャーが開始されたとき
            startCenterPoint = pinchGesture->centerPoint();
        } else if (pinchGesture->state() == QGesture::Updated) {
            // ジェスチャーが更新されたとき
            QPointF currentCenterPoint = pinchGesture->centerPoint();
            qreal angleDelta = calculateAngle(startCenterPoint, currentCenterPoint);
            rotateObject(angleDelta);
            startCenterPoint = currentCenterPoint;
        }
    }
}

qreal MyWidget::calculateAngle(const QPointF &p1, const QPointF &p2)
{
    qreal dx = p2.x() - p1.x();
    qreal dy = p2.y() - p1.y();
    return qAtan2(dy, dx);
}

QTransform を使用してオブジェクトを回転する

QTransform クラスは、2D 変換を表現するために使用できます。 回転、拡大縮小、移動などの操作をオブジェクトに適用するために使用できます。

利点

  • より柔軟な回転操作が可能になります。
  • QPinchGesture::rotationAngle を使用せずにオブジェクトを回転できます。

欠点

  • オブジェクトの状態を管理する必要があります。
  • QPinchGesture::rotationAngle よりも複雑な場合があります。


class ImageWidget : public QWidget
{
public:
    ImageWidget(const QImage &image, QWidget *parent = 0);

protected:
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

private:
    QImage image;
    QTransform transform;
};

ImageWidget::ImageWidget(const QImage &image, QWidget *parent) : QWidget(parent)
{
    image = image;
    transform.translate(width() / 2, height() / 2);
}

void ImageWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setTransform(transform);
    painter.drawImage(-image.width() / 2, -image.height() / 2, image);
}

void MyWidget::gestureEvent(QGestureEvent *event)
{
    if (QGesture *gesture = event->gesture(Qt::PinchGesture)) {
        QPinchGesture *pinchGesture = static_cast<QPinchGesture *>(gesture);

        if (pinchGesture->state() == QGesture::Updated) {
            // ジェスチャーが更新されたとき
            qreal rotationDelta = pinchGesture->totalRotationAngle();
            transform.rotate(rotationDelta);
            update();
        }
    }
}

カスタム ジェスチャー クラスを作成する

独自のジェスチャー ロジックを実装する必要がある場合は、カスタム ジェスチャー クラスを作成することができます。 これにより、ジェスチャーの開始、更新、終了時に実行するコードを完全に制御できます。

利点

  • ジェスチャーの動作を完全に制御できます。
  • 独自のジェスチャー ロジックを実装できます。
  • Qt Gestures フレームワークの深い理解が必要です。
  • 複雑で時間のかかる作業になる可能性があります。