開発者必見!Qt Widgetsにおけるジェスチャー制御の高度なテクニック


QGesture::GestureCancelPolicy は、ジェスチャーの受理が他のジェスチャーを自動的にキャンセルするかどうかに関する動作を定義する列挙型です。このポリシーは、ジェスチャーが受理されたときに、他のターゲットに属するアクティブなジェスチャーをどのように処理するかを制御します。

定数

この列挙型には、以下の2つの定数が含まれます。

  • CancelAllInContext
    ジェスチャーの受理が、同じコンテキスト内のすべてのアクティブなジェスチャーをキャンセルすることを意味します。コンテキストは、通常、親ウィジェットとそのすべての子ウィジェットを含むウィジェットツリーを指します。
  • CancelNone
    デフォルトの値で、ジェスチャーの受理が他のジェスチャーに影響を与えないことを意味します。

以下の例は、QGesture::GestureCancelPolicy を使用して、スワイプジェスチャーが受理されたときに、同じウィジェット上のすべてのジェスチャーをキャンセルする方法を示しています。

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

protected:
    void mousePressEvent(QMouseEvent *event) override;

private:
    QSwipeGesture *swipeGesture;
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    swipeGesture = new QSwipeGesture(this);
    swipeGesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
    connect(swipeGesture, &QSwipeGesture::gestureAccepted, this, &MyWidget::handleSwipeGesture);
}

void MyWidget::mousePressEvent(QMouseEvent *event)
{
    swipeGesture->start(event);
}

void MyWidget::handleSwipeGesture()
{
    // スワイプジェスチャーが受理されたときに実行する処理
}

このコードでは、QSwipeGesture オブジェクトが作成され、QGesture::CancelAllInContext に設定されています。これは、スワイプジェスチャーが受理されたときに、同じウィジェット上のすべてのジェスチャーがキャンセルされることを意味します。

  • 特定のアプリケーションのニーズに合わせて、このポリシーをカスタマイズすることができます。
  • QGesture::GestureCancelPolicy は、ジェスチャー認識システム全体の動作を制御するために使用できます。


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

protected:
    void mousePressEvent(QMouseEvent *event) override;

private:
    QSwipeGesture *swipeGesture;
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    swipeGesture = new QSwipeGesture(this);
    swipeGesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
    connect(swipeGesture, &QSwipeGesture::gestureAccepted, this, &MyWidget::handleSwipeGesture);
}

void MyWidget::mousePressEvent(QMouseEvent *event)
{
    swipeGesture->start(event);
}

void MyWidget::handleSwipeGesture()
{
    // スワイプジェスチャーが受理されたときに実行する処理
}

例2: ピンチジェスチャーが受理されたときに、同じコンテキスト内のすべてのアクティブなジェスチャーをキャンセルする

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

protected:
    void touchEvent(QTouchEvent *event) override;

private:
    QPinchGesture *pinchGesture;
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    pinchGesture = new QPinchGesture(this);
    pinchGesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
    connect(pinchGesture, &QPinchGesture::gestureAccepted, this, &MyWidget::handlePinchGesture);
}

void MyWidget::touchEvent(QTouchEvent *event)
{
    pinchGesture->start(event);
}

void MyWidget::handlePinchGesture()
{
    // ピンチジェスチャーが受理されたときに実行する処理
}

説明

上記の例では、QGesture::GestureCancelPolicy を使用して、ジェスチャーの受理が他のジェスチャーを自動的にキャンセルする方法を示しています。

  • 例2 では、QPinchGesture オブジェクトが作成され、QGesture::CancelAllInContext に設定されています。これは、ピンチジェスチャーが受理されたときに、同じコンテキスト内のすべてのアクティブなジェスチャーがキャンセルされることを意味します。
  • 例1 では、QSwipeGesture オブジェクトが作成され、QGesture::CancelAllInContext に設定されています。これは、スワイプジェスチャーが受理されたときに、同じウィジェット上のすべてのジェスチャーがキャンセルされることを意味します。

これらの例は、QGesture::GestureCancelPolicy を使用して、ジェスチャー認識システムの動作を制御する方法を示すほんの一例です。特定のアプリケーションのニーズに合わせて、このポリシーをカスタマイズすることができます。

  • ジェスチャー認識システムは複雑なシステムであり、QGesture::GestureCancelPolicy はその一部に過ぎません。ジェスチャー認識システムを理解するには、他の関連するクラスや関数についても学ぶ必要があります。


しかし、QGesture::GestureCancelPolicy を使用しなくても、ジェスチャーのキャンセル動作を制御することは可能です。以下、いくつかの代替方法を紹介します。

ジェスチャーシグナルを直接処理する

QGesture クラスは、ジェスチャーが開始されたとき、更新されたとき、および完了したときにシグナルを発行します。これらのシグナルを直接処理することで、他のジェスチャーをキャンセルするかどうかを制御することができます。

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

protected:
    void mousePressEvent(QMouseEvent *event) override;

private:
    QSwipeGesture *swipeGesture;
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    swipeGesture = new QSwipeGesture(this);
    connect(swipeGesture, &QSwipeGesture::gestureStarted, this, &MyWidget::handleGestureStarted);
    connect(swipeGesture, &QSwipeGesture::gestureUpdated, this, &MyWidget::handleGestureUpdated);
    connect(swipeGesture, &QSwipeGesture::gestureFinished, this, &MyWidget::handleGestureFinished);
}

void MyWidget::mousePressEvent(QMouseEvent *event)
{
    swipeGesture->start(event);
}

void MyWidget::handleGestureStarted()
{
    // スワイプジェスチャーが開始されたときに実行する処理
    // 他のジェスチャーをキャンセルするかどうかをここで判断する
}

void MyWidget::handleGestureUpdated()
{
    // スワイプジェスチャーが更新されたときに実行する処理
}

void MyWidget::handleGestureFinished()
{
    // スワイプジェスチャーが完了したときに実行する処理
}

この方法では、よりきめ細かなキャンセル制御が可能になります。ただし、コードが複雑になり、保守が難しくなる可能性があります。

ジェスチャーフィルターを使用する

QGestureFilter クラスを使用することで、ジェスチャーイベントをフィルタリングし、特定のジェスチャーをキャンセルすることができます。

class MyGestureFilter : public QGestureFilter
{
public:
    bool filter(QGestureEvent *event) override
    {
        // ジェスチャーイベントをフィルタリングする処理
        // 特定のジェスチャーをキャンセルするかどうかをここで判断する

        return true; // イベントを許可
        return false; // イベントをキャンセル
    }
};

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

protected:
    void mousePressEvent(QMouseEvent *event) override;

private:
    QSwipeGesture *swipeGesture;
    MyGestureFilter *gestureFilter;
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    swipeGesture = new QSwipeGesture(this);
    gestureFilter = new MyGestureFilter;
    swipeGesture->installFilter(gestureFilter);
    connect(swipeGesture, &QSwipeGesture::gestureAccepted, this, &MyWidget::handleSwipeGesture);
}

void MyWidget::mousePressEvent(QMouseEvent *event)
{
    swipeGesture->start(event);
}

void MyWidget::handleSwipeGesture()
{
    // スワイプジェスチャーが受理されたときに実行する処理
}

この方法は、特定のジェスチャーをキャンセルする必要がある場合に役立ちます。ただし、すべてのジェスチャーイベントをフィルタリングする必要があるため、パフォーマンスが低下する可能性があります。

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

QGesture クラスを継承して、独自のジェスチャークラスを作成することができます。このクラスでは、ジェスチャーの開始、更新、および完了を制御する独自のシグナルとスロットを作成することができます。

class MySwipeGesture : public QSwipeGesture
{
public:
    MySwipeGesture(QObject *parent = 0);

signals:
    void gestureStarted(const QGesture *gesture);
    void gestureUpdated(const QGesture *gesture);
    void gestureFinished(const QGesture *gesture);

protected:
    void startGesture(Q