3

在我的菜单中,我正在为菜单操作设置数据。如何在我的插槽中提取该数据?或者更好的是,除了连接插槽之外,我还可以连接一个能够提取操作数据的成员函数(如在第一个连接中)吗?动作数据旨在识别每个动作。作为一个sidenode,我不确定是否可以仅在一个操作上使用多个菜单操作条目openNote

void Traymenu::createMainContextMenu() {
      QAction *actionNewNote = m_mainContextMenu.addAction("Neue Notiz");

      actionNewNote->setIcon(QIcon("C:\\new.ico"));
      actionNewNote->setIconVisibleInMenu(true);

      QObject::connect(actionNewNote,&QAction::triggered,this,&Traymenu::newNote);

      QString menuEntryName;
      QAction *openNote;
      QVariant noteID;
      for (int i = 0; i<m_noteList.count(); i++) {
        std::string noteTitle = m_noteList[i].data()->getTitle();
        menuEntryName = QString::fromStdString(noteTitle);

        openNote = m_mainContextMenu.addAction(menuEntryName);
        connect(openNote,SIGNAL(triggered()),this,SLOT(s_showNote()));

        noteID.setValue(m_noteList[i].data()->getID());
        openNote->setData(noteID);
    }
    m_mainIcon.setContextMenu(&m_mainContextMenu);
}

和插槽:

void Traymenu::s_showNote() {
    QObject* obj = sender();
    //int noteID = data.toInt();
    //Search all notes in noteList for that ID and show it
}
4

2 回答 2

3

使用 QObject::sender()

您可以使用QObject::sender()来获取信号的发送者,然后qobject_cast将发送者指针转换为正确的类型。

void Traymenu::s_showNote()
{
    QAction* act = qobject_cast<QAction *>(sender());
    if (act != 0)
    {
        QVariant data = act->data();
        int noteID = data.toInt();
        showNote(noteID); // isolate showNote logic from "get my ID" stuff
     }
}

void Traymenu::showNote(int noteID)
{
    // Do the real work here, now that you have the ID ...
}

正如 Qt 文档警告的那样,“这个函数违反了面向对象的模块化原则。” 不过,这仍然是一种相当安全和标准的做法——只是有一些缺点。特别要注意的是,您承诺拥有一个s_showNote仅在作为插槽访问时才有效的方法(否则 sender 为 0)。

使用 QSignalMapper

或者,您可以使用QSignalMapper该类返回指向项目的指针或将唯一标识符(int 或 QString)与每个项目相关联。

像这样的东西:

void Traymenu::createMainContextMenu() 
{
  signalMapper = new QSignalMapper(this); // (or initialize elsewhere)

  // ... (create your newNote here same as before) ...

  QString menuEntryName;
  QAction *openNote;
  int noteID;
  for (int i = 0; i<m_noteList.count(); i++) {
    std::string noteTitle = m_noteList[i].data()->getTitle();
    menuEntryName = QString::fromStdString(noteTitle);

    openNote = m_mainContextMenu.addAction(menuEntryName);

    noteID = m_noteList[i].data()->getID();
    openNote->setData(QVariant(noteID)); // (if you still need data in the QActions)

    signalMapper->setMapping(openNote, noteID);
  }
  connect(signalMapper, SIGNAL(mapped(int)),
          this, SLOT(showNote(int)));

  m_mainIcon.setContextMenu(&m_mainContextMenu);
}

void Traymenu::showNote(int noteID) {
    // Now you have the ID ...
}

这种模式的好处是可以隔离所有丑陋的“等等,我如何获得我的标识符?” 东西放在一个地方,而不是让初始化代码和槽函数都有用于关联动作和 ID 的代码。

于 2014-02-24T15:57:34.130 回答
0

我会这样写:

void Traymenu::s_showNote() {
    QObject* obj = sender();
    QAction *action = qobject_cast<QAction *>(obj);
    int id = action->data().toInt();

    for (int i = 0; i < m_noteList.count(); i++) {
        if (m_noteList[i].data()->getID() == id) {
            [..]
        }
    }
}
于 2014-02-24T15:56:35.043 回答