Как добавить список QActions в QMenu и обработать их одним слотом?
Во-первых, у меня есть список QWidget
, что я не буду знать длину до времени выполнения. Затем я создаю QListWidget
, где я их показываю, и когда кто-то нажимает на них, я использую сигнал currentItemChanged(QListWidgetItem*, QListWidgetItem*)
, чтобы поймать его и получить индекс щелкнутого элемента.
Теперь я хочу сделать аналогичную вещь в QMenu
. Я узнаю список, когда QMenu
и его действия будут созданы, но я не смогу это сделать.
Как я могу создавать действия, ловить их сигналы и подключать их к одному слоту, который выполняет разные действия в зависимости от позиции действия (индекса) в списке меню? Должен быть какой-то способ решить эту проблему, поскольку другие приложения используют это. Я попытался посмотреть на отображение, но я не мог понять, как использовать его для этого.
Я попытался захватить sender
в слоте, но не смог получить от него полезную информацию.
Ответы
Ответ 1
Вы можете связать индекс (или любые другие данные) с каждым действием, когда они созданы с помощью 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();
}
Другие методы: отображение сигналов или использование sender()
, объясняются в этой статье Qt Quaterly.
Ответ 2
Более общий (не специфический для 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()
}