动态生成的菜单项 - 确定单击了哪一个

时间:2014-07-24 20:41:54

标签: qt

我正在解析一个包含菜单栏项列表的XML文档。换句话说,如果我在XML树中有5个元素,那么我将创建5个QAction *变量并将它们添加到QMenu。所以项目的数量是动态的,在编译时是不知道的。

问题在于弄清楚如何进行回调。由于我不知道QAction *变量的数量,我不能简单地为每个变量创建一个回调:

connect(action, SIGNAL(clicked()), this, SLOT(item1Clicked()));
connect(anotherAction, SIGNAL(clicked()), this, SLOT(item2Clicked()));
connect(yetAnotherAction, SIGNAL(clicked()), this, SLOT(item3Clicked()));
....

我考虑过创建一个回调:

void menuItemClicked(int index)

但问题是我无法将无参数clicked()信号连接到menuItemClicked(int)广告位。

还有其他策略吗?

更新 - 到目前为止

class MainWindow
{
private slots:
  void helpDocumentation(int);
  ...

然后

void MainWindow::helpDocumentation(int index)
{
  // do some logging
}

void MainWindow::MainWindow()
{
QDomElement rootElement = doc.documentElement();
  QDomNodeList nodes = doc.elementsByTagName("document");
  QMenu * documentationMenu = helpMenu->addMenu("Documentation");
  QSignalMapper * signalMapper = new QSignalMapper(this);

  for (int i = 0; i < nodes.length(); ++i)
  {
    QDomNode node = nodes.item(i);

    QDomElement element = node.toElement();
    if (!element.isNull())
    {
      // Item is an element.
      QString fileAttr = element.attribute("file");
      QString nameAttr = element.attribute("name");

      documentationItems.push_back(qMakePair(fileAttr, nameAttr));

      QAction * action = new QAction(nameAttr, helpMenu);
      connect(action, SIGNAL(clicked()), signalMapper, SLOT(map()));
      signalMapper->setMapping(action, i);
      documentationMenu->addAction(action);
    }
  }

  connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(helpDocumentation(int)));
}

项目将添加到菜单栏,但不会调用helpDocumentation(int)插槽。

2 个答案:

答案 0 :(得分:4)

只需使用插槽内的sender()函数,它就会告诉你哪个QAction触发了信号。

QObject * s = sender();

if(s==action)
{
    //Do something here
}
else if(s==anotherAction)
{
    //Do something here
}
else if(s==yetAnotherAction)
{
    //Do something here
}

如果您绝对需要索引参数,请查找QSignalMapper。它完全符合您的要求:将多个无参数信号连接到单个插槽,将参数作为整数,为每个连接的信号关联一个唯一的整数索引。

首先创建信号映射器:

QSignalMapper * signalMapper = new QSignalMapper(this);

您将每个信号连接到signalMapper map()插槽:

connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));
connect(anotherAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
connect(yetAnotherAction, SIGNAL(triggered()), signalMapper, SLOT(map()));

然后告诉信号映射器哪个发件人有哪个索引:

signalMapper->setMapping(action, 0);
signalMapper->setMapping(anotherAction, 1);
signalMapper->setMapping(yetAnotherAction, 2);

然后将出站映射(int)信号连接到您的插槽

connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(menuItemClicked(int)));

顺便说一句,signalmapper是一个非常简单的类,它使用sender()并查找将QObject *发送者与整数索引相关联的哈希表。

答案 1 :(得分:3)

一种选择是使用galinette指出的QSignalMapper

更专注于行动:QActionGroup。为此,您可以使用QAction::setData()将元数据附加到您的操作,您可以在处理QActionGroup::triggered(QAction *)信号时访问这些数据。