首先,我有一个QWidget
的列表,我不知道运行时的长度。然后我创建一个QListWidget
我在其中显示它们,当有人点击它们时,我使用信号currentItemChanged(QListWidgetItem*, QListWidgetItem*)
来捕获它并获得被点击项目的索引。
现在我想在QMenu
中做类似的事情。 QMenu
及其操作构建后我会知道列表,但我无法对此进行硬编码。
如何根据菜单列表中的操作位置(索引)创建操作,捕获信号并将它们连接到同一个插槽,这些插槽会执行不同的操作?必须有一些方法来解决这个问题,因为其他应用程序使用它。我试着看一下映射,但我无法理解如何使用它。
我试图抓住广告位中的sender
,但无法从中获取任何有用的信息。
答案 0 :(得分:16)
您可以将索引(或任何其他数据)与使用QAction::setData
创建的每个操作相关联,并将信号QMenu::triggered(QAction*)
连接到您的广告位。
然后,您就可以通过slot参数的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()
的使用,在that article of Qt Quaterly中有解释。
答案 1 :(得分:4)
QActionGroup类是更通用的(不是特定于QMenu)方法。这允许您将特定菜单项隔离为相关组,或将不同小部件组合在一起。
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()
}
答案 2 :(得分:0)
您还可以拥有QMap
和QActions
中的ints
,并将动作添加到菜单后,还可以将其添加到地图中,其值为+与上一个不同。然后,您可以将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);
}
}