13

首先,我有一个QWidgets 列表,直到运行时我才知道它的长度。然后我创建一个QListWidget显示它们的位置,当有人点击它们时,我使用信号currentItemChanged(QListWidgetItem*, QListWidgetItem*)来捕捉它并获取点击项目的索引。

现在我想在QMenu. 我会在构建它及其操作时知道该列表QMenu,但我将无法对其进行硬编码。

如何创建动作,捕捉它们的信号并将它们连接到同一个插槽,根据菜单列表中动作的位置(索引)执行不同的操作?必须有某种方法来解决这个问题,因为其他应用程序使用它。我试图查看映射,但我无法理解如何使用它。

我试图抓住sender插槽,但无法从中获得任何有用的信息。

4

3 回答 3

20

您可以在创建每个操作时将索引(或任何其他数据)关联到每个操作,QAction::setData并将信号连接QMenu::triggered(QAction*)到您的插槽。

然后,您将能够通过QAction::data()slot 参数的函数检索数据。

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();

}

其他方法:信号映射或使用sender(),在Qt Quaterly 的那篇文章中进行了说明。

于 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

您还可以使用QMapofQActionsints,一旦您将操作添加到菜单中,您还可以将其添加到地图中,其值与前一个值不同 +1。然后,您可以QAction::triggered连接到一个通用插槽,从那里您可以通过调用获取信号的发送者,将sender()其动态转换为 a 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 回答