QSignalMapper介绍
该类收集一组无参数的信号,并使用与发送信号的对象对应的整数、字符串或对象参数重新发出它们。在大多数情况下,可以使用lambdas将自定义参数传递给槽。这样成本更低,并且可以简化代码。
该类支持使用setMapping()将特定字符串、整数、对象和小部件映射到特定对象。
然后,对象的信号可以连接到map()插槽,该插槽将发出一个与原始信号对象相关的值的信号(可以是mappedInt(), mappedString()和mappedObject())。最后可以使用removemaps()删除映射。
Signal 信号
该类主要有以下三个信号可以进行绑定,这取决于你使用setMapping()
时传入的标识类型。
void mappedInt(int i) void mappedObject(QObject *object) void mappedString(const QString &text)
slots
对象的信号可以关联到map()
中,根据自己需求选择合适的重载版本。
void map(QObject *sender) void map()
根据标识获取对象
通过mapping
可以根据特定的标识获取原本的对象。
QObject *mapping(int id) const QObject *mapping(const QString &id) const QObject *mapping(QObject *object) const
给对象设置标识
通过setMapping
方法可以给对象设置标识。
void setMapping(QObject *sender, int id) void setMapping(QObject *sender, const QString &text) void setMapping(QObject *sender, QObject *object)
删除映射
不需要映射时,通过removeMappings方法传入对应的对象即可删除映射。
void removeMappings(QObject *sender)
实例
现假设有多个按钮(QPushButton),需要根据不同的按钮点击输出不同的词语,那么我们就可以完美的使用QSignalMapper来处理。
代码
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); signalMapper.setMapping(ui->pushButton, "type1"); connect(ui->pushButton, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_2, "type2"); connect(ui->pushButton_2, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_3, "type3"); connect(ui->pushButton_3, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_4, "type4"); connect(ui->pushButton_4, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_5, "type5"); connect(ui->pushButton_5, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); connect(&signalMapper, &QSignalMapper::mappedString, this, &MainWindow::ShowName); } MainWindow::~MainWindow() { delete ui; } void MainWindow::ShowName(QString str) { // 相同的逻辑抽出来 qDebug() << "ShowName:"; if(str == "type1") { qDebug() << u8"天菜"; } else if(str == "type2") { qDebug() << u8"傻子"; } else if(str == "type3") { qDebug() << u8"秀才"; } else if(str == "type4") { qDebug() << u8"天才"; } else if(str == "type5") { qDebug() << u8"77"; } }
需求升级
现在点击哪个按钮,需要将哪个按钮禁用掉。那么通过QSignalMapeer
更加简单。
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); signalMapper.setMapping(ui->pushButton, ui->pushButton); connect(ui->pushButton, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_2, ui->pushButton_2); connect(ui->pushButton_2, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_3, ui->pushButton_3); connect(ui->pushButton_3, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_4, ui->pushButton_4); connect(ui->pushButton_4, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); signalMapper.setMapping(ui->pushButton_5, ui->pushButton_5); connect(ui->pushButton_5, &QPushButton::clicked, &signalMapper, QOverload<>::of(&QSignalMapper::map)); connect(&signalMapper, &QSignalMapper::mappedObject, this, &MainWindow::ShowObject); } void MainWindow::ShowObject(QObject *btn) { ((QPushButton*)(btn))->setEnabled(false); }
总结
上述的实例场景可能都有点勉强,但是实际工作中,使用的场景很多,例如功能区的按钮,弹窗类的按钮需要根据自身的大小放到对应的位置,正常情况下·,你可能就会写很多个槽进行实现,虽然可能不完全一样,但是逻辑都是相同的,代码看着也冗余。