QSignalMapper这个类并不是个新鲜概念, 早在Qt2里就已经存在, 而且它的功能也是始终如一。 不过由于宣传力度不够(例子里涉及到它的很少)了解这个类人可能还不是很多, 所以特此撰文介绍此类的功能和用法。简单的理解,可以把SignalMapper这个类看成是信号的翻译和转发器, 它可以把一个无参数的信号翻译成带int参数、QString参数、QObject*参数或者QWidget*参数的信号, 并将之转发。这么一说大家有没有联想到该类的适用范围呢? 呵呵, 是不是一下就想到了如果我有一堆的button, 可以把clicked事件放在一个函数里处理, 只要给button编个号或者给button起个名就行了, 这样就不用给每个button写一个slot了,岂不是很方便?

下面这段代码就实现了该功能:

/***mainwin.h***/

#ifndef MAINWIN_H
#define MAINWIN_H #include <QWidget> class QSignalMapper;
class MainWin : public QWidget
{
Q_OBJECT public:
MainWin(QWidget *parent = );
~MainWin();
private slots:
void doClicked(const QString &btnname);
private:
QSignalMapper *signalMapper;
}; #endif // MAINWIN_H

/***mainwin.cpp***/

#include "mainwin.h"
#include <QSignalMapper>
#include <QLayout>
#include <QPushButton>
#include <QMessageBox> MainWin::MainWin(QWidget *parent)
: QWidget(parent)
{
QString buttontext = "btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn10";//10个button
QStringList texts = buttontext.split(","); signalMapper = new QSignalMapper(this);
QGridLayout *gridLayout = new QGridLayout; for (int i = ; i < texts.size(); ++i)
{
QPushButton *button = new QPushButton(texts[i]);
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));//原始信号传递给signalmapper
signalMapper->setMapping (button, texts[i]);
//设置signalmapper的转发规则, 转发为参数为QString类型的信号, 并把texts[i]的内容作为实参传递。
gridLayout->addWidget(button, i / , i % );
}
connect(signalMapper, SIGNAL(mapped (const QString &)), this, SLOT(doClicked(const QString &)));//将转发的信号连接到最终的槽函数
setLayout(gridLayout);
} void MainWin::doClicked(const QString& btnname)
{
QMessageBox::information(this,"Clicked",btnname+" is clicked!");
} MainWin::~MainWin()
{ }

/***main.cpp***/

#include <QApplication>
#include "mainwin.h" int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWin w;
w.show(); return a.exec();
}

从这个例子来看QSignalMapper的用法是非常简单的, 也很容易理解。

(1)首先把原始不带参数的信号连接到signalmapper的map槽函数, 这样signalmapper能在第一时间接收到原始信号;

(2)其次调用setMapper方法告诉signalmapper怎样去处理原始信号。 在这个例子中是把原始信号转化为一个带QString参数的信号

(3)最后接收转化后的带参数信号, 这里所把转化后的信号与槽函数连接, 在槽函数中获得需要的数据。

QSignalMapper类的功能核心是要建立一个从发出原始信号的object到需要的数据的映射(setMapper函数), 如果你的程序恰巧需要这样的功能,那么当然QSignalMapper就是当仁不让的最佳选择。 除了上述最常见的用法, 我们也来开动脑筋想想还有什么别的场合适合使用这个类呢?

在Qt的examples里有一个例子用到了QSignalMapper这个类, 在examples/mainwindow/mdi/mainwindow.cpp里。 它的用法是将QWidget指针作为参数, 然后菜单选中的信号映射到子Window的指针, 最终由QMainWindow来处理, 用于实现子窗口的切换。 这个用法很有些意思, 可以说是QSignalMapper的最佳用例, 建议大家学习一下。 这里截取其中最核心的代码, 有注释应该很好看懂吧, 如果还是有问题就留言:

//主类从QMainWindow派生
MainWindow::MainWindow()
{
//...
windowMapper = new QSignalMapper(this);
connect(windowMapper, SIGNAL(mapped (QWidget *)), this, SLOT(setActiveSubWindow(QWidget *)));
//转发的信号直接连接到QMainWindow的setActiveSubWindow槽
//...
} void MainWindow::updateWindowMenu()
{
//... QList windows = mdiArea->subWindowList();
separatorAct->setVisible(!windows.isEmpty());
for (int i = ; i < windows.size(); ++i)
{
MdiChild *child = qobject_cast(windows.at(i)->widget());
QString text;
if (i < )
{
text = tr("&%1 %2").arg(i + ) .arg(child->userFriendlyCurrentFile());
}
else
{
text = tr("%1 %2").arg(i + ) .arg(child->userFriendlyCurrentFile());
}
QAction *action = windowMenu->addAction(text);
action->setCheckable(true);
action ->setChecked(child == activeMdiChild());
connect(action, SIGNAL(triggered()), windowMapper, SLOT(map ()));//监控action的triggered信号
windowMapper->setMapping (action, windows.at(i));//建立action指针到QWidget*的映射 }
//...
}
}<pre name="code" class="cpp">void MainWindow::setActiveSubWindow(QWidget *window) // 设置活动子窗口
{
if (!window) // 如果传递了窗口部件,则将其设置为活动窗口
return;
ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
}

此外,在C:\Qt\4.8.4\examples\tools\inputpanel此例中也用到了信号映射器。

引自:http://blog.csdn.net/cuteqt/article/details/4306900

转自:http://blog.csdn.net/zzwdkxx/article/details/28437441

QSignalMapper类处理多信号关联同一个槽的方法(1)的更多相关文章

  1. QSignalMapper类处理多信号关联同一个槽的方法(2)

    例1: QSignMapper *mapper = new QSignMapper(this) QPushButton *btn1 = new QPushButton(this); btn1-> ...

  2. C++模板类与Qt信号槽混用

    一.正文 目前正在做一个视频处理相关的项目.项目的技术栈是这样的,UI层采用Qt来实现基本的数据展示和交互,底层音视频采用的是一套基于FFmpeg的视频处理框架.这是一套类似Microsoft Med ...

  3. qt信号signal和槽slot机制

    内容: 一.概述 二.信号 三.槽 四.信号与槽的关联 五.元对象工具 六.程序样例 七.应注意的问题 信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工 ...

  4. QRadioButton类中Toggled()信号的使用方法

    QRadioButton类中Toggled()信号的使用方法 1.说明 QRadioButton中,Toggled()信号是在Radio Button状态(开.关)切换时发出的,而clicked()信 ...

  5. duilib底层机制剖析:窗口类与窗口句柄的关联

    转载请说明原出处.谢谢~~ 看到群里朋友有人讨论WTL中的thunk技术,让我联想到了duilib的类似技术. 这些技术都是为了解决c++封装的窗口类与窗口句柄的关联问题. 这里是三篇关于thunk技 ...

  6. WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配

    原文:WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配 WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配 网上的 ...

  7. PyQt信号connect连接槽方法时报:native Qt signal is not callable错误

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在将一个信号连接到槽方法时,程序异常退出,捕获异常 ...

  8. laravel5.1 关联模型保存的方法(使用associate方法)

    模型定义 class User { public function customer() { return $this->hasOne('Customer'); } } class Custom ...

  9. Python面向对象 --- 类的设计和常见的内置方法

    面向对象:一种基于面向过程的新的编程思想.也就是说面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节:这种思想是将数据作为第一位,而方法或者说是算法作为其次,这是对数据一种 ...

随机推荐

  1. oc 调用c语言方法和oc的方法调用

    //c语方的方法 void sayHello(){ printf("Hello OC"); } int main(int argc, char * argv[]) { sayHel ...

  2. PopupWindow的简单使用(结合RecyclerView)

    Android弹窗: 在Android中弹出式菜单(以下称弹窗)是使用十分广泛一种菜单呈现的方式,弹窗为用户交互提供了便利.关于弹窗的实现大致有以下两种方式AlertDialog和PopupWindo ...

  3. LeetCode94 Binary Tree Inorder Traversal(迭代实现) Java

    题目: Given a binary tree, return the inorder traversal of its nodes' values. For example: Given binar ...

  4. git配置gitignore

    一.背景                                                                                                 ...

  5. Latex 转 word 技法大全

    Latex 转 word 技法大全 在稿件接收后,经常会遇到出版社要求变更稿件格式,其中最多的是latex变为word格式.如果手工操作,是非常麻烦的,还容易出错.如果钱多得花不了,可以让出版社找人去 ...

  6. 独立成分分析(Independent component analysis, ICA)

    作者:桂. 时间:2017-05-22 12:12:43 链接:http://www.cnblogs.com/xingshansi/p/6884273.html 前言 今天群里冒出这样一个问题:群里谁 ...

  7. unity Transform.TransformPoint

    正如unity api文档所说: Transforms position from local space to world space. 即Transform.TransformPoint是将局部坐 ...

  8. mod_fastcgi和mod_fcgid的区别

    mod_fcgid是一个跟mod_fastcgi二进制兼容的Apache module. 原 来的mod_fastcgi因为实现方式的限制,所以可能会创建了很多不必要的进程,而实际上只需要更少的进程就 ...

  9. 深入理解Docker Volume(二)

      一开始,认为Volume是用来持久化的,但是这实际上不对,因为认为Volume是用来持久化的同学一定是认为容器无法持久化,所以有了Volume来帮助容器持久化,事实上,容器会一直存在,除非你删除他 ...

  10. 在开发中写一些tool来提升自己的效率

    比如说,我在调试一个web-project的时候,因为eclipse默认编译好的.class文件放在/build/classes/中,但是我希望随时把这些class文件放到/WEB-ROOT/WEB- ...