繁体   English   中英

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

[英]How to pass a QString to a Qt slot from a QMenu via QSignalMapper or otherwise

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

object :: connect:没有这样的信号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);

由于我不知道如果每次填充动态菜单时删除subMenuQt::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*

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM