Qt WidgetsでQGraphicsSceneContextMenuEvent::pos()を使ってアイテム上の右クリック処理を行う方法


QGraphicsSceneContextMenuEvent::pos() は、Qt Widgets ライブラリにおける QGraphicsSceneContextMenuEvent クラスのメソッドで、コンテキストメニューが要求された時点におけるマウスカーソルのアイテム座標を取得します。これは、アイテム上のどこで右クリックされたのかを特定するために使用されます。

構文

QPointF pos() const;

戻り値

マウスカーソルのアイテム座標を表す QPointF オブジェクトを返します。

void MyGraphicsView::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    QPointF itemPos = event->pos();
    qDebug() << "Context menu requested at item position: " << itemPos;

    // アイテム上の右クリック処理を行う
    QGraphicsItem *item = scene()->itemAt(itemPos);
    if (item) {
        // アイテム上の右クリック処理を行う
    }
}

この例では、contextMenuEvent() メソッド内で QGraphicsSceneContextMenuEvent::pos() メソッドを使用して、コンテキストメニューが要求された時点におけるマウスカーソルのアイテム座標を取得しています。取得した座標は qDebug() 関数で出力し、scene()->itemAt() メソッドを使用して、その座標にあるアイテムを取得しています。アイテムを取得できた場合は、そのアイテムに対する右クリック処理を行うことができます。

  • QGraphicsSceneContextMenuEvent::pos() メソッドは、マウスカーソルがアイテム上にある場合にのみ有効です。マウスカーソルがアイテム上になければ、このメソッドは不定値を返します。
  • QGraphicsSceneContextMenuEvent::pos() メソッドは、アイテム座標を返します。シーン座標またはスクリーン座標を取得するには、scenePos() メソッドまたは screenPos() メソッドを使用する必要があります。


#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QMenu>

class MyGraphicsItem : public QGraphicsItem
{
public:
    MyGraphicsItem(const QString &text, QGraphicsItem *parent = nullptr);

protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
};

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

protected:
    virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
};

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

    QGraphicsScene scene;
    MyGraphicsItem *item1 = new MyGraphicsItem("Item 1", &scene);
    item1->setPos(100, 100);
    MyGraphicsItem *item2 = new MyGraphicsItem("Item 2", &scene);
    item2->setPos(200, 200);
    scene.addItem(item1);
    scene.addItem(item2);

    MyGraphicsView view(&scene);
    view.show();

    return app.exec();
}

MyGraphicsItem::MyGraphicsItem(const QString &text, QGraphicsItem *parent)
    : QGraphicsItem(parent)
{
    setText(text);
    setFlag(QGraphicsItem::ItemIsSelectable);
    setFlag(QGraphicsItem::ItemIsFocusable);
}

void MyGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event);
    update();
}

QVariant MyGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
    if (change == ItemSelectedChange) {
        update();
    }
    return QGraphicsItem::itemChange(change, value);
}

MyGraphicsView::MyGraphicsView(QWidget *parent)
    : QGraphicsView(parent)
{
    setContextMenuPolicy(Qt::CustomContextMenu);
}

void MyGraphicsView::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    QPointF itemPos = event->pos();
    qDebug() << "Context menu requested at item position: " << itemPos;

    QGraphicsItem *item = scene()->itemAt(itemPos);
    if (item) {
        QMenu menu(this);
        menu.addAction("Action 1");
        menu.addAction("Action 2");
        menu.exec(event->screenPos());
    }
}

このコードは以下の動作を行います。

  1. MyGraphicsItem クラスと MyGraphicsView クラスを定義します。
  2. MyGraphicsItem クラスは、テキストとフラグ (ItemIsSelectableItemIsFocusable) を持つグラフィックスアイテムです。
  3. MyGraphicsView クラスは、コンテキストメニューポリシーを Qt::CustomContextMenu に設定します。
  4. main() 関数は、QGraphicsSceneMyGraphicsItem のインスタンスを作成し、シーンに追加します。
  5. MyGraphicsView インスタンスを作成し、表示します。
  6. MyGraphicsItem::mousePressEvent() メソッドは、アイテムがクリックされたときにアイテムを更新します。
  7. MyGraphicsItem::itemChange() メソッドは、アイテムが選択されたときにアイテムを更新します。
  8. MyGraphicsView::contextMenuEvent() メソッドは、コンテキストメニューが要求されたときに、マウスカーソルのアイテム座標を取得し、その座標にあるアイテムに対して右クリック処理を行います。


scenePos() メソッドを使用する

QGraphicsSceneContextMenuEvent::scenePos() メソッドは、マウスカーソルのシーン座標を取得します。シーン座標は、アイテム座標とは異なり、シーン内のすべてのアイテムに対して共通の座標系です。

QPointF scenePos = event->scenePos();

screenPos() メソッドを使用する

QGraphicsSceneContextMenuEvent::screenPos() メソッドは、マウスカーソルのスクリーン座標を取得します。スクリーン座標は、デスクトップ上のすべてのウィンドウに対して共通の座標系です。

QPointF screenPos = event->screenPos();

アイテム座標に変換する

マウスカーソルのシーン座標またはスクリーン座標を取得したら、QGraphicsItem::mapToItemCoordinate() メソッドを使用して、アイテム座標に変換することができます。

QGraphicsItem *item = scene()->itemAt(scenePos);
if (item) {
    QPointF itemPos = item->mapToItemCoordinate(scenePos);
    // アイテム上の処理を行う
}

カスタムイベントを使用する

QGraphicsSceneContextMenuEvent の代わりに、カスタムイベントを使用することができます。カスタムイベントには、マウスカーソルのアイテム座標を含む任意のデータを格納することができます。

class MyGraphicsItem : public QGraphicsItem
{
public:
    MyGraphicsItem(const QString &text, QGraphicsItem *parent = nullptr);

protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
};

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

protected:
    virtual void customContextMenuRequested(QGraphicsItem *item, QPointF pos);
};

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

    QGraphicsScene scene;
    MyGraphicsItem *item1 = new MyGraphicsItem("Item 1", &scene);
    item1->setPos(100, 100);
    MyGraphicsItem *item2 = new MyGraphicsItem("Item 2", &scene);
    item2->setPos(200, 200);
    scene.addItem(item1);
    scene.addItem(item2);

    MyGraphicsView view(&scene);
    view.connect(&view, &MyGraphicsView::customContextMenuRequested, &view, &MyGraphicsView::contextMenuEvent);
    view.show();

    return app.exec();
}

MyGraphicsItem::MyGraphicsItem(const QString &text, QGraphicsItem *parent)
    : QGraphicsItem(parent)
{
    setText(text);
    setFlag(QGraphicsItem::ItemIsSelectable);
    setFlag(QGraphicsItem::ItemIsFocusable);
}

void MyGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event);
    update();
}

QVariant MyGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
    if (change == ItemSelectedChange) {
        update();
    }
    return QGraphicsItem::itemChange(change, value);
}

MyGraphicsView::MyGraphicsView(QWidget *parent)
    : QGraphicsView(parent)
{
    setContextMenuPolicy(Qt::NoContextMenu);
}

void MyGraphicsView::customContextMenuRequested(QGraphicsItem *item, QPointF pos)
{
    QMenu menu(this);
    menu.addAction("Action 1");
    menu.addAction("Action 2");
    menu.exec(pos);
}
  1. MyGraphicsItem クラスと MyGraphicsView クラスを定義します。
  2. MyGraphicsItem クラスは、テキストとフラグ (ItemIsSelectableItemIsFocusable) を持つグラフィックスアイテムです。
  3. MyGraphicsView クラスは、コンテキストメニューポリシーを Qt::NoContextMenu に設定します。
  4. customContextMenuRequested() シグナルを定義します。このシグナルは、