如何通过QSignalMapper或其他方式将QString从QMenu传递到Qt槽 [英] How to pass a QString to a Qt slot from a QMenu via QSignalMapper or otherwise

查看:714
本文介绍了如何通过QSignalMapper或其他方式将QString从QMenu传递到Qt槽的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a QMenu with many submenus. These are dynamically created i.e. the names menus come from a db and created in a loop. Now i wanted to fire the same slot triggered() or similar when a menu is clicked, but i needed the QString menu name to be passed to slot so i could perform menu specific actions. I have tried this i.e. passing a QAction * to the triggered event and used setData but i am getting the run time error.


object :: connect:没有此类信号QAction :: triggered(QAction *)

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是一个数据成员构造函数

Alternately, i have also tried QSignalMapper where signalMapper is a data member initialized in the constructor

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没有被调用。

In the second case, i don't get any error, however the slot function playChannel is not being called. Would really appreciate if some one could help resolving it.

更新1:我看到的其他例子的唯一区别是,我看到的是,通常人们将来自几个小部件的信号连接到单个插槽(假定不同的按钮)。在我的情况下,我连接几个子菜单(不同的名称)到一个插槽。

Update 1: The only difference that i see from other examples i have seen is that usually people are connecting signals from several widgets to a single slot (say different buttons). In my case i am connecting several sub menus (with different names) to a single slot. Should this make any difference?

更新2:它在解决方案中建议的更正后有效下面的为QSignalMapper。还有事实,我使用SubMenu作为参数setMapping,其中作为MenuAction项应该已被使用。但现在我得到事件多次触发,即在主菜单中有所选子菜单类别的条目的次数。如果频道类型是英语(主菜单)有四个条目),HBO,星电影等(子菜单),我选择HBO,然后事件与字符串HBO发射四次。它工作正常,如果我创建一个单独的信号映射器为每个子菜单。但我希望一个单一的mapper应该使用,我在这里做不正确的东西。

Update 2: It worked after the correction suggested in the solution below for QSignalMapper. Also the fact that i was using SubMenu as argument to setMapping , where as MenuAction item should have been used instead. But now i am getting event fired multiple times i.e. as many times as there are entries in the main menu for the selected sub menu category. If channel type is English (main menu) with four entries), HBO, star movies etc. (sub menu), and i choose HBO, then event is fired four times with string HBO. It works fine if i create a separate signal mapper for each submenu. But i was hoping a single mapper should be used and i am doing something incorrectly here. Some more details in the comments to the answer.

推荐答案

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

After adding the QAction to the menu, you only have to connect QMenu to the slot. You don't connect each action individually to the slot:

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 确保该插槽不会重新连接多次。



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

As I don't know how you if you delete subMenu each time the dynamic menu is filled, the Qt::UniqueConnection ensure that the slot won't be reconnected multiple times.


For the signal mapper version, you should only connect the actions to the mapper in the loop. The connection from the mapper to the slot should only be done once.

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 *

And for that case, the slot playChannel should accept a QString instead of a QAction*.

这篇关于如何通过QSignalMapper或其他方式将QString从QMenu传递到Qt槽的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆