其他分享
首页 > 其他分享> > c-如何通过QSignalMapper或其他方式将QString从QMenu传递到Qt插槽

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

作者:互联网

我有一个带有许多子菜单的QMenu.这些是动态创建的,即名称菜单来自数据库,并在循环中创建.现在,我想在单击菜单时触发相同的slot trigger()或类似的插槽,但是我需要将QString菜单名称传递到插槽,以便执行菜单特定的操作.我尝试了this,即将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:它在解决方案Q001中针对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 *.

标签:qmenu,qstring,c,qt4,qt-signals
来源: https://codeday.me/bug/20191010/1888415.html