Qt Widgets でスワイプジェスチャをもっと詳しく! QSwipeGesture::SwipeDirection を使いこなす


QSwipeGesture::SwipeDirection は、Qt Widgets モジュールで提供される QSwipeGesture クラスで使用される列挙型です。これは、ユーザーがタッチスクリーンやマウスを使って行ったスワイプジェスチャの方向を表すために使用されます。

QSwipeGesture::SwipeDirection には、以下の5つの値が定義されています。

  • Down: 下方向へのスワイプジェスチャです。
  • Up: 上方向へのスワイプジェスチャです。
  • Right: 右方向へのスワイプジェスチャです。
  • Left: 左方向へのスワイプジェスチャです。
  • NoDirection: スワイプジェスチャの方向が検知されませんでした。

使用方法

QSwipeGesture::SwipeDirection は、QSwipeGesture クラスの以下のプロパティを使用して取得できます。

  • verticalDirection: スワイプジェスチャの垂直方向を表します。
  • horizontalDirection: スワイプジェスチャの水平方向を表します。

これらのプロパティは、QGesture::state() メソッドが QGesture::Started または QGesture::Updated を返す場合にのみ有効です。

QSwipeGesture gesture(widget);
gesture.connect(&gesture, &QSwipeGesture::stateChanged,
                this, &MyWidget::onStateChanged);

void MyWidget::onStateChanged(QGesture::State state)
{
    if (state == QGesture::Started || state == QGesture::Updated) {
        QSwipeGesture *swipeGesture = static_cast<QSwipeGesture *>(gesture);

        QSwipeGesture::SwipeDirection horizontalDirection = swipeGesture->horizontalDirection();
        QSwipeGesture::SwipeDirection verticalDirection = swipeGesture->verticalDirection();

        if (horizontalDirection == QSwipeGesture::Left) {
            // 左方向へのスワイプ
        } else if (horizontalDirection == QSwipeGesture::Right) {
            // 右方向へのスワイプ
        }

        if (verticalDirection == QSwipeGesture::Up) {
            // 上方向へのスワイプ
        } else if (verticalDirection == QSwipeGesture::Down) {
            // 下方向へのスワイプ
        }
    }
}

この例では、QSwipeGesture オブジェクトを作成し、stateChanged シグナルを onStateChanged メソッドに接続しています。onStateChanged メソッドは、シグナルが送信されるたびに呼び出され、スワイプジェスチャの方向を判断します。

  • スワイプジェスチャの方向をより詳細に制御するには、QSwipeGesture::swipeAngle プロパティを使用できます。このプロパティは、スワイプジェスチャの方向とx軸との間の角度を返します。
  • QSwipeGesture::SwipeDirection は、スワイプジェスチャの開始点と終了点間のベクトルに基づいて決定されます。


#include <QApplication>
#include <QLabel>
#include <QGestureRecognizer>
#include <QHBoxLayout>

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

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    QLabel label_;
};

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent)
{
    label_.setText("スワイプ方向: なし");

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(&label_);

    QGestureRecognizer *gestureRecognizer = new QGestureRecognizer(this);
    gestureRecognizer->addType(Qt::SwipeGesture);
    QObject::connect(gestureRecognizer, &QGestureRecognizer::stateChanged,
                     this, &MyWidget::onStateChanged);
}

void MyWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(Qt::black);
    painter.drawRect(0, 0, width() - 1, height() - 1);
}

void MyWidget::onStateChanged(QGesture::State state)
{
    if (state == QGesture::Started || state == QGesture::Updated) {
        for (QGesture *gesture : gestureRecognizer->gestures()) {
            if (gesture->type() == Qt::SwipeGesture) {
                QSwipeGesture *swipeGesture = static_cast<QSwipeGesture *>(gesture);

                QSwipeGesture::SwipeDirection horizontalDirection = swipeGesture->horizontalDirection();
                QSwipeGesture::SwipeDirection verticalDirection = swipeGesture->verticalDirection();

                QString directionText;

                if (horizontalDirection == QSwipeGesture::Left) {
                    directionText += "左";
                } else if (horizontalDirection == QSwipeGesture::Right) {
                    directionText += "右";
                }

                if (verticalDirection == QSwipeGesture::Up) {
                    directionText += "上";
                } else if (verticalDirection == QSwipeGesture::Down) {
                    directionText += "下";
                }

                if (directionText.isEmpty()) {
                    directionText = "なし";
                }

                label_.setText("スワイプ方向: " + directionText);
            }
        }
    }
}

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

    MyWidget widget;
    widget.show();

    return app.exec();
}

このコードを実行すると、以下のようになります。

  • ユーザーがウィンドウをスワイプすると、ラベルのテキストがスワイプの方向に更新されます。
  • ウィンドウ内には、"スワイプ方向: なし" というラベルが表示されます。
  • ウィンドウが表示されます。

このコードは、QSwipeGesture::SwipeDirection を使用してスワイプジェスチャの方向を検出する方法を示す基本的な例です。実際のアプリケーションでは、このコードを拡張して、スワイプジェスチャに応じてさまざまなアクションを実行することができます。

  • コードを実行するには、Qt Widgets モジュールがインストールされている必要があります。
  • このコードは、Qt Creator 4.15.2 と Qt 6.7.1 を使用して作成されました。


しかし、状況によっては、QSwipeGesture::SwipeDirection の代わりに他の方法を使用する方が適切な場合があります。以下に、いくつかの代替方法を紹介します。

QGestureRecognizer と QPointF を使用する

QSwipeGesture::SwipeDirection の代わりに、QGestureRecognizerQPointF を使用して、スワイプジェスチャの方向をより詳細に制御することができます。

#include <QApplication>
#include <QLabel>
#include <QGestureRecognizer>
#include <QHBoxLayout>

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

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    QLabel label_;
};

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent)
{
    label_.setText("スワイプ開始点: (0, 0)");

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(&label_);

    QGestureRecognizer *gestureRecognizer = new QGestureRecognizer(this);
    gestureRecognizer->addType(Qt::SwipeGesture);
    QObject::connect(gestureRecognizer, &QGestureRecognizer::stateChanged,
                     this, &MyWidget::onStateChanged);
}

void MyWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(Qt::black);
    painter.drawRect(0, 0, width() - 1, height() - 1);
}

void MyWidget::onStateChanged(QGesture::State state)
{
    if (state == QGesture::Started || state == QGesture::Updated) {
        for (QGesture *gesture : gestureRecognizer->gestures()) {
            if (gesture->type() == Qt::SwipeGesture) {
                QSwipeGesture *swipeGesture = static_cast<QSwipeGesture *>(gesture);

                QPointF startPoint = swipeGesture->startPoint();

                label_.setText("スワイプ開始点: (" + QString::number(startPoint.x()) + ", "
                              + QString::number(startPoint.y()) + ")");
            }
        }
    }
}

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

    MyWidget widget;
    widget.show();

    return app.exec();
}
  • ユーザーがウィンドウをスワイプすると、ラベルのテキストがスワイプ開始点の座標に更新されます。
  • ウィンドウ内には、"スワイプ開始点: (0, 0)" というラベルが表示されます。
  • ウィンドウが表示されます。

このコードは、QSwipeGesture::SwipeDirection の代わりに、QGestureRecognizerQPointF を使用して、スワイプジェスチャの開始点の座標を取得する方法を示しています。

カスタムジェスチャー認識器を作成する

より複雑なスワイプジェスチャを検出したい場合は、カスタムジェスチャー認識器を作成することができます。

#include <QApplication>
#include <QLabel>
#include <QGestureRecognizer>
#include <QHBoxLayout>
#include <QEvent>

class MyGestureRecognizer : public QGestureRecognizer
{
public:
    MyGestureRecognizer(QObject *parent = nullptr);

protected:
    bool recognize(const QGesture *gesture, QGestureRecognizer::Result *result) const override;

private:
    QPointF startPoint_;
    QPointF endPoint_;
};

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

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    QLabel label_;
    MyGestureRecognizer gestureRecognizer_;
};

MyGestureRecognizer::MyGestureRecognizer(QObject *parent) :
    QGestureRecognizer(parent)
{
}

bool MyGestureRecognizer::recognize(const QGesture *gesture, QGestureRecognizer::Result *result) const
{
    if (gesture->type() == Qt::SwipeGesture) {
        QSwipeGesture *swipeGesture = static_cast<QSwipeGesture *>(gesture);

        startPoint_ = swipeGesture->startPoint();
        endPoint_ = swipeGesture->endPoint();