ワンランク上のQtプログラミング: QMenu::actionAt() 関数でクリックアクションを自在に処理


QMenu::actionAt()関数は、指定されたポイント(x, y座標)がどのアクションに対応しているかを判断するために使用されます。これは、メニュー内のアクションをクリックしたときに、どのアクションが選択されたかを特定する際に役立ちます。

構文

QAction *QMenu::actionAt(const QPoint &pt) const;

パラメータ

  • pt: メニュー内の座標を表すQPointオブジェクト。

戻り値

  • 指定されたポイントに対応するアクションオブジェクト。アクションが存在しない場合はnullptrを返します。

QMenu menu;
QAction *action1 = menu.addAction("アクション1");
QAction *action2 = menu.addAction("アクション2");

QPoint point(10, 20); // アクション1の位置

QAction *selectedAction = menu.actionAt(point);

if (selectedAction) {
    if (selectedAction == action1) {
        // アクション1が選択されました
    } else {
        // アクション2が選択されました
    }
} else {
    // メニュー内のアクションをクリックしていない
}
  • QMenu::actionAt()関数は、メニュー内のサブメニューも考慮します。サブメニュー内のアクションをクリックした場合、そのアクションオブジェクトが返されます。
  • QMenu::actionAt()関数は、メニュー内の可視アクションのみを考慮します。非表示のアクションは返されません。

QMenu::actionAt()関数の利点

  • サブメニュー内のアクションも処理できます。
  • メニュー内のアクションをクリックしたときに、どのアクションが選択されたかを簡単に特定できます。
  • ポイントがメニュー内のアクション領域外にある場合は、nullptrが返されます。
  • メニュー内の非表示のアクションは考慮されません。


#include <QApplication>
#include <QMenu>
#include <QMainWindow>

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

    QMainWindow window;
    QMenu menu(&window);
    menu.addAction("アクション1");
    menu.addAction("アクション2");

    QAction *selectedAction;

    QObject::connect(&menu, SIGNAL(triggered(QAction*)), &window, SLOT(onActionTriggered(QAction*)));

    window.setContextMenuPolicy(Qt::CustomContextMenu);
    QObject::connect(&window, SIGNAL(customContextMenuRequested(const QPoint&)), &menu, SLOT(exec(const QPoint&)));

    window.show();

    return app.exec();
}

void MainWindow::onActionTriggered(QAction *action) {
    if (action) {
        QMessageBox::information(this, "選択されたアクション", action->text());
    }
}

このコードは、以下のことを行います。

  1. QMainWindowウィンドウを作成します。
  2. QMenuオブジェクトを作成し、ウィンドウに関連付けます。
  3. メニューに2つのアクションを追加します。
  4. triggeredシグナルをアクションに接続し、onActionTriggeredスロットを呼び出します。
  5. ウィンドウのコンテキストメニューポリシーをQt::CustomContextMenuに設定します。
  6. customContextMenuRequestedシグナルをウィンドウに接続し、execスロットを呼び出します。

ウィンドウを右クリックすると、メニューが表示されます。メニュー内のアクションをクリックすると、onActionTriggeredスロットが呼び出され、選択されたアクションのテキストがメッセージボックスに表示されます。

#include <QApplication>
#include <QMenu>
#include <QMainWindow>

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

    QMainWindow window;
    QMenu menu(&window);

    QMenu *subMenu = new QMenu("サブメニュー");
    subMenu->addAction("サブアクション1");
    subMenu->addAction("サブアクション2");

    menu.addAction("アクション1");
    menu.addMenu(subMenu);

    QAction *selectedAction;

    QObject::connect(&menu, SIGNAL(triggered(QAction*)), &window, SLOT(onActionTriggered(QAction*)));

    window.setContextMenuPolicy(Qt::CustomContextMenu);
    QObject::connect(&window, SIGNAL(customContextMenuRequested(const QPoint&)), &menu, SLOT(exec(const QPoint&)));

    window.show();

    return app.exec();
}

void MainWindow::onActionTriggered(QAction *action) {
    if (action) {
        QMessageBox::information(this, "選択されたアクション", action->text());
    }
}

説明

このコードは、上記のコードと似ていますが、サブメニューを含むように拡張されています。

  1. QMenuオブジェクトを作成し、ウィンドウに関連付けます。
  2. QMenuオブジェクトを作成し、サブメニューとして設定します。
  3. サブメニューに2つのアクションを追加します。
  4. メインメニューに2つのアクションを追加します。
  5. triggeredシグナルをアクションに接続し、onActionTriggeredスロットを呼び出します。
  6. ウィンドウのコンテキストメニューポリシーをQt::CustomContextMenuに設定します。
  7. customContextMenuRequestedシグナルをウィンドウに接続し、execスロットを呼び出します。
  • QMenu::sizeHint()関数を使用して、メニューの推奨サイズを取得できます。
  • QMenu::actionGeometry()関数を使用して、アクションのジオメトリを取得できます。


サブメニュー内のアクションを処理する場合

QMenu::actionAt() 関数は、サブメニュー内のアクションも処理できますが、より複雑なロジックが必要な場合は、別の方法の方が効率的かもしれません。

代替方法

  • サブメニューの triggered() シグナルを接続し、アクションが選択されたときにスロットを呼び出します。
  • QMenu::activeAction() 関数を使用して、現在選択されているアクションを取得します。


QMenu menu;
QMenu *subMenu = new QMenu("サブメニュー");
subMenu->addAction("サブアクション1");
subMenu->addAction("サブアクション2");

menu.addAction("アクション1");
menu.addMenu(subMenu);

QAction *selectedAction;

QObject::connect(subMenu, SIGNAL(triggered(QAction*)), &window, SLOT(onActionTriggered(QAction*)));

// ...

void MainWindow::onActionTriggered(QAction *action) {
    if (action) {
        QMessageBox::information(this, "選択されたアクション", action->text());
    }
}

メニュー内のすべてのアクションを処理する場合

QMenu::actionAt() 関数は、指定されたポイントに対応するアクションのみを返します。メニュー内のすべてのアクションを処理したい場合は、別の方法の方が効率的かもしれません。

代替方法

  • 各アクションの triggered() シグナルを接続し、アクションが選択されたときにスロットを呼び出します。
  • QMenu::actions() メソッドを使用して、メニュー内のすべてのアクションを取得します。


QMenu menu;
menu.addAction("アクション1");
menu.addAction("アクション2");

QVector<QAction *> actions = menu.actions();

for (QAction *action : actions) {
    QObject::connect(action, SIGNAL(triggered()), &window, SLOT(onActionTriggered()));
}

// ...

void MainWindow::onActionTriggered() {
    QAction *action = sender();
    if (action) {
        QMessageBox::information(this, "選択されたアクション", action->text());
    }
}

パフォーマンスが重要な場合

QMenu::actionAt() 関数は、メニュー内のすべてのアクションを検索する必要があるため、パフォーマンスが重要になる場合があります。

代替方法

  • ローカル座標を使用して、アクションを直接検索します。
  • QMenu::posAtGlobal() メソッドを使用して、グローバル座標をメニュー内のローカル座標に変換します。
QMenu menu;
menu.addAction("アクション1");
menu.addAction("アクション2");

QPoint globalPos = ...; // グローバル座標

QPoint localPos = menu.posAtGlobal(globalPos);

QAction *action = menu.actionAt(localPos);

if (action) {
    // ...
}