如何通过QSignalMapper或其他方式从QMenu传递QString到Qt插槽



我有一个带有许多子菜单的QMenu。这些是动态创建的,即名称菜单来自数据库并在循环中创建。现在我想在单击菜单时触发相同的插槽触发器()或类似,但我需要QString菜单名称传递给插槽,以便我可以执行菜单特定的操作。我已经尝试过这个,即传递一个QAction *触发的事件,并使用setData,但我得到运行时错误。

object::connect: No such signal QAction::triggered(QAction *)

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
        QAction *subMenuAct = subMenu->addAction(tr(c_name)); // c_name the menu name
        subMenuAct->setData(ch_name);
        connect(subMenuAct, SIGNAL(triggered(QAction *)), this, SLOT(playChannel(QAction *))); // playChannel is the slot
}
void <ClassName>::playChannel(QAction *channelAction)
{
     QString str = channelAction->data().toString();
    qDebug() << "Selected - " << str;
}

或者,我也尝试过QSignalMapper,其中signalMapper是在构造函数中初始化的数据成员

signalMapper = new QSignalMapper(this);

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
       QAction *subMenuAct = subMenu->addAction(tr(c_name));
       connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
       signalMapper->setMapping(subMenu, ch_name);
       connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString)));
}

在第二种情况下,我没有得到任何错误,但是插槽函数playChannel没有被调用。如果有人能帮忙解决这个问题,我将非常感激。

更新1:我从其他例子中看到的唯一区别是,通常人们将几个小部件的信号连接到单个插槽(说不同的按钮)。在我的情况下,我连接几个子菜单(具有不同的名称)到单个插槽。这有什么区别吗?

更新2:在QSignalMapper的解决方案中建议的更正后,它工作了。另外,我使用SubMenu作为setMapping的参数,而MenuAction项应该被使用。但现在我得到事件触发多次,即多次有在主菜单中所选子菜单类别的条目。如果频道类型为英语(主菜单),有四个条目),HBO,明星电影等(子菜单),并且我选择HBO,那么事件将使用字符串HBO触发四次。它的工作很好,如果我为每个子菜单创建一个单独的信号映射器。但我希望一个单一的映射器应该使用,我在这里做了一些错误的事情。

QAction添加到菜单后,您只需将QMenu连接到插槽。您不需要将每个动作单独连接到插槽:

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
    ch_name = <name from the database for the channel j>;
    QAction *subMenuAct = subMenu->addAction(tr(ch_name));
    subMenuAct->setData(ch_name);
}
connect(subMenu, SIGNAL(triggered(QAction *)), 
        this, SLOT(playChannel(QAction *)), Qt::UniqueConnection);

因为我不知道你如何如果你删除subMenu每次动态菜单填充,Qt::UniqueConnection确保插槽不会被多次重新连接。


对于信号映射器版本,您应该只将操作连接到循环中的映射器。从映射器到插槽的连接应该只做一次。

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
   ch_name = <name from the database for the channel j>;
   QAction *subMenuAct = subMenu->addAction(tr(ch_name));
   connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
   signalMapper->setMapping(subMenuAct, ch_name);   
}
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString)));

在这种情况下,插槽playChannel应该接受QString而不是QAction*

相关内容

  • 没有找到相关文章

最新更新