13

まず、QWidget実行時までの長さがわからないリストがあります。次に、それらを表示する場所を作成し、QListWidget誰かがそれらをクリックすると、シグナルを使用してcurrentItemChanged(QListWidgetItem*, QListWidgetItem*)それをキャッチし、クリックされたアイテムのインデックスを取得します。

今、私はで同様のことをしたいと思いますQMenu。とそのアクションが構築されるときにリストはわかりますがQMenu、これをハードコーディングすることはできません。

アクションを作成し、それらのシグナルをキャッチして、メニューリスト内のアクションの位置(インデックス)に応じて異なることを行う同じスロットに接続するにはどうすればよいですか?他のアプリケーションがこれを使用するため、これを解決する方法が必要です。マッピングを調べてみましたが、その使い方がわかりませんでした。

senderスロットをつかもうとしましたが、そこから有用な情報を得ることができませんでした。

4

3 に答える 3

20

インデックス(またはその他のデータ)は、アクションが作成されたときに各アクションに関連付けてQAction::setData、信号QMenu::triggered(QAction*)をスロットに接続できます。

QAction::data()その後、スロットパラメータの機能を介してデータを取得できるようになります。

MyClass::MyClass() {
    // menu creation
    for(...) {
        QAction *action = ...;
        action->setData(10);
        ...
        menu->addAction(action);
    }
    // only one single signal connection
    connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(mySlot(QAction*)));
}

void MyClass::mySlot(QAction *action) {
   int value = action->data().toInt();

}

他の方法:信号マッピングまたはの使用は、 QtQuaterlyのその記事でsender()説明されています。

于 2012-02-08T04:13:28.693 に答える
4

これにアプローチするためのより一般的な(QMenuに固有ではない)方法は、QActionGroupクラスです。これにより、特定のメニュー項目を関連グループとして分離したり、異なるウィジェットをグループ化したりすることができます。

void MyClass::InitMenu(QMenu* menu)
{
    QActionGroup* actions1 = new QActionGroup(menu);
    actions1->setExclusive(false);
    actions1->addAction(menu->addAction(tr("Action1")))->setData(1);
    actions1->addAction(menu->addAction(tr("Action2")))->setData(2);
    actions1->addAction(menu->addAction(tr("Action3")))->setData(3);
    actions1->addAction(menu->addAction(tr("Action4")))->setData(4);
    actions1->addAction(menu->addAction(tr("Action5")))->setData(5);
    connect(actions1, SIGNAL(triggered(QAction*)), SLOT(MySlot(QAction*)));

    QActionGroup* actions2 = new QActionGroup(menu);
    actions2->addAction(menu->addAction(tr("Undo Action1")))->setData(1);
    actions2->addAction(menu->addAction(tr("Undo Action2")))->setData(2);
    //...
    connect(actions2, SIGNAL(triggered(QAction*)), SLOT(MyUndoSlot(QAction*)));
}

とスロットで:

void MyClass::MySlot(QAction* triggeredAction)
{
    // use either the action itself... or an offset
    int value = triggeredAction->data().toInt()
}
于 2015-07-15T03:59:59.080 に答える
0

また、QMapとを設定することもできます。メニューにアクションを追加するQActionsintsすぐに、前のアクションと+1異なる値でマップに追加することもできます。次に、汎用スロットに配線QAction::triggeredします。そこから、を呼び出して信号の送信者を取得し、sender()それをに動的にキャストしてQAction、マップ内の値を検索します。

class MyClass {
public:
    void Init();
private slots:
    void onTriggered();
private:
    QMap<QAction*, int> _actionToInt;
}


MyClass::Init() {
    QMenu* menu = new QMenu();
    // Loop for illustration purposes
    // For general purpose keep an index and increment it every time you add
    for(int i=0; i<10; ++i) {
        QAction* action = menu->addAction("Item1");
        _actionToInt.insert(action, i);
        connect(action, &QAction::triggered, this, &MyClass::onTriggered);
    }
}

void MyClass::onTriggered() {
    QAction* action = qobject_cast<QAction*>(sender());
    //For safety purposes
    if (action && _actionToInt.contains(action) {
        //And here you have your index!
        int index = _actionToInt.value(action);
    }
}
于 2018-08-15T19:51:48.963 に答える