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

标签 c++ qt4 qstring qmenu qt-signals

我有一个带有许多子菜单的 QMenu。这些是动态创建的,即名称菜单来自数据库并在循环中创建。现在我想在单击菜单时触发相同的插槽 triggered() 或类似的,但我需要将 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: 在解决方案 below 中建议的更正后它起作用了对于 QSignalMapper。还有一个事实是,我使用 SubMenu 作为 setMapping 的参数,而应该使用 MenuAction 项。但是现在我多次触发事件,即与主菜单中所选子菜单类别的条目一样多。如果 channel 类型是英语(主菜单),有四个条目)、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 确保插槽不会被删除重新连接多次。


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

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*

关于c++ - 如何通过 QSignalMapper 或其他方式将 QString 从 QMenu 传递到 Qt 插槽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14151443/

相关文章:

c++ - 精确到 Qstring 的数字

C++ c 字符串分隔符为 ' '

c++ - 重载 operator= 不起作用

performance - 使用 QT 的平滑文本动画(选框文本效果)

qt - 更改 QTableWidget 的选择颜色

android - 将 jstring 转换为 QString

c++ - 如何在特定行中打印 QString

c++ - 为什么我需要转发声明类 foo 而不是类 bar,即使 'foo.h' 和 'bar.h' 都包含在内?

c++ - C++11 <type_traits> 模板参数类型推导失败

c++ - 单击 QPushButton 时,将数据从 QLineEdit 转换为 QString。