タブレットペンの接線方向の圧力 (tangentialPressure) を使った Qt GUI アプリ開発のヒントとコツ


QTabletEvent::tangentialPressure()関数は、タブレットデバイスでペンが触れている場所にかかる接線方向の圧力を取得します。これは、スタイラスなどのペンツールで描画や操作を行う際に、筆圧だけでなく、ペンの傾きや方向も考慮した表現が可能になる機能です。

用途

  • ジェスチャー操作

    • 回転操作
    • ズーム操作
    • 2本指スクロール
    • 傾斜線や破線などの描画
    • ぼかしや影付けなどの効果
    • 筆圧感度を活かしたブラシツール

使用方法

QTabletEvent *event = ...; // タブレットイベントを取得

double tangentialPressure = event->tangentialPressure();

戻り値

  • 接線方向の圧力 (-1.0 ~ 1.0 の範囲)
    • 0.0:ニュートラルな状態
    • 正の値:右方向への圧力
    • 負の値:左方向への圧力

注意点

  • 接線方向の圧力は、ペン先の接地面に対する角度と、ペンの傾きによって決定されます。
  • デバイスがサポートしていない場合は、0.0 が返されます。
  • すべてのタブレットデバイスが接線方向の圧力をサポートしているわけではありません。


#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QTabletEvent>

class DrawingScene : public QGraphicsScene
{
public:
    DrawingScene(QObject *parent = nullptr) : QGraphicsScene(parent) {}

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override
    {
        lastPos = event->scenePos();
    }

    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
    {
        QPen pen;
        pen.setWidth(5);
        pen.setColor(Qt::black);

        QGraphicsLineItem *line = new QGraphicsLineItem(lastPos, event->scenePos());
        line->setPen(pen);

        addItem(line);

        lastPos = event->scenePos();
    }

    void tabletEvent(QTabletEvent *event) override
    {
        if (event->type() == QEvent::TabletMove) {
            double tangentialPressure = event->tangentialPressure();

            QPen pen;
            pen.setWidth(tangentialPressure * 10);
            pen.setColor(Qt::black);

            QGraphicsLineItem *line = new QGraphicsLineItem(lastPos, event->scenePos());
            line->setPen(pen);

            addItem(line);

            lastPos = event->scenePos();
        }
    }

private:
    QPointF lastPos;
};

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

    DrawingScene scene;
    QGraphicsView view(&scene);
    view.show();

    return app.exec();
}
  1. DrawingSceneクラスを定義します。これは、描画を行うためのシーンを表すクラスです。
  2. mousePressEvent() メソッドは、マウスが押されたときに呼び出されます。このメソッドでは、最後のマウス座標を保存します。
  3. mouseMoveEvent() メソッドは、マウスが移動したときに呼び出されます。このメソッドでは、新しい線を作成し、最後のマウス座標と現在のマウス座標を結ぶように設定します。
  4. tabletEvent() メソッドは、タブレットイベントが発生したときに呼び出されます。このメソッドでは、イベントの種類が QEvent::TabletMove であるかどうかを確認します。
  5. イベントの種類が QEvent::TabletMove である場合、tangentialPressure() 関数を使用して接線方向の圧力を取得します。
  6. 取得した接線方向の圧力を使用して、線の幅を設定します。
  7. 新しい線を作成し、最後のマウス座標と現在のマウス座標を結ぶように設定します。
  8. 最後のマウス座標を現在のマウス座標に更新します。


QTabletEvent::tangentialPressure() は、タブレットデバイスでペンが触れている場所にかかる接線方向の圧力を取得する関数です。しかし、この関数はすべてのタブレットデバイスでサポートされているわけではありません。また、古いバージョンの Qt では、この関数が存在しない場合があります。

このような場合、QTabletEvent::tipPressure() 関数を使用して、ペン先の垂直方向の圧力を取得し、そこから接線方向の圧力を推定することができます。

推定方法

  1. ペン先の垂直方向の圧力 (tipPressure) を取得します。
  2. ペンの傾き (tiltAngle) を取得します。
  3. 以下の式を使用して、接線方向の圧力 (tangentialPressure) を推定します。
tangentialPressure = tipPressure * sin(tiltAngle)

注意点

  • ペンの傾きが正確に取得できない場合、推定精度が低くなります。
  • この方法はあくまでも推定であり、実際の接線方向の圧力とは異なる場合があります。

代替方法

上記の方法以外にも、以下の代替方法があります。

  • 画像処理技術を使用する
    • ペン先の画像を解析し、そこから接線方向の圧力を推定することができます。
  • ペンツール専用の API を使用する
    • 多くのペンツールには、独自の API が用意されており、接線方向の圧力などの情報を取得することができます。