如何为QString从QMenu经由QSignalMapper或以其他方式传递给一个Qt槽(How

2019-07-17 19:32发布

我有许多子菜单一QMenu。 这些是动态创建的,即名称菜单归结从DB和创造了一个循环。 现在我想点击菜单时,火()触发同一插槽或相似的,但我需要的是通过QString的菜单名称插槽,所以我可以执行菜单的具体行动。 我已经试过这也就是传递的QAction *为触发事件,并使用使用setData但我得到的运行时错误。

对象::连接:没有这样的信号的QAction ::触发(*的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。 另外,事实证明我是使用子作为参数传递给setMapping,那里的MenuAction项目应该已经用于代替。 但现在我越来越触发的事件,因为在选定的子菜单分类的主菜单条目多次,即多次。 如果信道类型是英语(主菜单)有四个条目),HBO,明星电影等。(子菜单),我选择HBO,那么事件与字符串HBO发射四次。 如果我为每个子菜单单独的信号映射器,它工作正常。 但我希望一个映射器应使用,我在这里不正确的做事。 一些更详细的评论答案。

Answer 1:

加入后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*



文章来源: How to pass a QString to a Qt slot from a QMenu via QSignalMapper or otherwise