Qt GUI における QEventPoint::id の詳細解説


QEventPoint::id は、Qt GUI におけるタッチスクリーンやマウスなどのポインティングデバイスイベントに関わる重要なプロパティです。これは、イベントに関与する個々のタッチポイントを識別するために使用されるユニークな整数值です。

機能

  • ジェスチャ認識やマルチタッチアプリケーションの開発に不可欠なツールです。
  • 特定のタッチポイントに関連するイベントを追跡し、処理することができます。
  • 複数のタッチポイントを同時に処理する場合に、それぞれのポイントを区別するために役立ちます。

使用方法

QEventPoint::id は、QEventPoint オブジェクトから直接取得できます。このオブジェクトは、QTouchEventQPointerEvent などのポインティングデバイスイベントから取得できます。

QEventPoint point = event->touchPoints()[0];
int pointId = point.id();

注意点

  • 特定のタッチポイントに関連するイベントを追跡するには、ID を他の情報 (位置、圧力など) と組み合わせて使用することがあります。
  • 複数のタッチポイントを処理する場合、各ポイントの ID を追跡することが重要です。
  • QEventPoint::id は、イベント発生時のみ有効です。イベント処理が完了すると、ID は再利用される可能性があります。

次の例では、QEventPoint::id を使用して、画面をタップしたときに特定のタッチポイントに関連するイベントを追跡する方法を示します。

void MyWidget::touchEvent(QTouchEvent *event)
{
    for (const QEventPoint &point : event->touchPoints()) {
        int pointId = point.id();
        if (point.state() == QEventPoint::Pressed) {
            // 新しいタッチポイントが押された場合
            m_touchPoints[pointId] = point.position();
        } else if (point.state() == QEventPoint::Moved) {
            // 既存のタッチポイントが移動した場合
            QPointF previousPosition = m_touchPoints[pointId];
            QPointF currentPosition = point.position();

            // 前後の位置に基づいて処理を行う
            // ...
        } else if (point.state() == QEventPoint::Released) {
            // タッチポイントが解放された場合
            m_touchPoints.remove(pointId);
        }
    }
}
  • QEventPoint::id は、Qt GUI 5.6 以降で使用できます。


#include <QApplication>
#include <QMainWindow>
#include <QPainter>
#include <QMouseEvent>

class MyWidget : public QMainWindow {
public:
    MyWidget() {
        setWindowTitle("ドラッグ可能な円");
        setFixedSize(200, 200);
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        painter.setPen(QPen(Qt::black));
        painter.setBrush(QBrush(Qt::red));

        int x = width() / 2;
        int y = height() / 2;
        int radius = 50;

        painter.drawEllipse(x - radius, y - radius, 2 * radius, 2 * radius);
    }

    void mousePressEvent(QMouseEvent *event) override {
        if (event->button() == Qt::LeftButton) {
            m_dragStartPosition = event->pos();
            m_dragging = true;
        }
    }

    void mouseMoveEvent(QMouseEvent *event) override {
        if (m_dragging) {
            int dx = event->pos().x() - m_dragStartPosition.x();
            int dy = event->pos().y() - m_dragStartPosition.y();

            update();
        }
    }

    void mouseReleaseEvent(QMouseEvent *event) override {
        if (event->button() == Qt::LeftButton) {
            m_dragging = false;
        }
    }

private:
    bool m_dragging = false;
    QPoint m_dragStartPosition;
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}

このコードでは、mousePressEvent メソッドでドラッグを開始し、mouseMoveEvent メソッドで円の位置を更新します。mouseReleaseEvent メソッドでドラッグを終了します。

このコードでは、QEventPoint::id は使用されていません。しかし、このコードを拡張して、複数の円をドラッグできるようにするには、QEventPoint::id を使用して、それぞれの円に関連するイベントを追跡することができます。

拡張例

次のコードは、上記のコードを拡張して、複数の円をドラッグできるようにしたものです。

#include <QApplication>
#include <QMainWindow>
#include <QPainter>
#include <QMouseEvent>
#include <QMap>

class MyWidget : public QMainWindow {
public:
    MyWidget() {
        setWindowTitle("ドラッグ可能な円");
        setFixedSize(200, 200);
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        painter.setPen(QPen(Qt::black));

        for (const auto &pair : m_circles) {
            int circleId = pair.first;
            const QPoint &center = pair.second;
            int radius = 50;

            painter.setBrush(circleColors[circleId]);
            painter.drawEllipse(center.x() - radius, center.y() - radius, 2 * radius, 2 * radius);
        }
    }

    void mousePressEvent(QMouseEvent *event) override {
        if (event->button() == Qt::LeftButton) {
            int circleId = findCircleIdAt(event->pos());
            if (circleId != -1) {
                m_dragStartPosition[circleId] = event->pos();
                m_dragging[circleId] = true;
            }
        }
    }

    void mouseMoveEvent(QMouseEvent *event) override {
        for (const auto &pair : m_circles) {
            int circleId = pair.first;
            const QPoint &center = pair.second;

            if (m_dragging[circleId]) {
                int dx = event->pos().x() - m_dragStartPosition[circleId].x();
                int dy = event->pos().y() - m_dragStartPosition[circleId].y();

                m


代替方法

  • ポインタ: 特定のタッチポイントに関連するイベントを追跡する必要がある場合は、QPointer オブジェクトを使用することができます。QPointer は、タッチポイントのポインタを保持し、イベント発生後も有効なままにします。
QPointer<QTouchPoint> m_currentTouchPoint;

void MyWidget::touchEvent(QTouchEvent *event)
{
    if (event->type() == QEvent::TouchBegin) {
        m_currentTouchPoint = event->touchPoints()[0];
    } else if (event->type() == QEvent::TouchMove) {
        if (m_currentTouchPoint) {
            // 現在のタッチポイントに関連するイベントを処理
            // ...
        }
    } else if (event->type() == QEvent::TouchEnd) {
        m_currentTouchPoint = nullptr;
    }
}
  • インデックス: 複数のタッチポイントを同時に処理する場合、QEventPoint::id の代わりに、タッチポイントのインデックスを使用することができます。インデックスは、イベント内のタッチポイントの順序に基づいています。
void MyWidget::touchEvent(QTouchEvent *event)
{
    for (int i = 0; i < event->touchPoints().size(); ++i) {
        const QEventPoint &point = event->touchPoints()[i];

        // タッチポイントのインデックス: i
        // ...
    }
}
  • インデックスは、イベント内のタッチポイントの順序に基づいているため、タッチポイントの順序が変更されると無効になります。
  • QPointer は、タッチポイントが解放された後も有効なままですが、タッチポイントが別のウィジェットに移動すると無効になります。
  • 代替方法を使用する場合は、その方法の制限を理解する必要があります。