QSignalMapper类可以看成是信号的翻译和转发器。
它可以把一个无参的信号翻译成带以下4种参数的信号再转发:int、QString、 QObject*以及QWidget *。
QSignalMapper类的功能核心是通过setMapping()函数建立一个从信号源Object----->到需要的数据的映射。
QSignalMapper的接收信号槽函数是map(),它将根据setMapping规则,转发出mapped()信号给别家。
QSignalMapper可将多个有类似处理方式signal用一个slot实现,相当于将N个一对一映射通过集中转换成多对一映射。
例子:N个button,把其clicked()事件的处理放在一个处理函数里;只要事先给button编号或者给button起好名字作为参数,无需给每个button写一个slot函数。
class ButtonWidget : public QWidget
{
Q_OBJECT
public:
ButtonWidget(const QStringList &texts, QWidget *parent = nullptr);
signals:
void clicked(const QString &text);
private:
QSignalMapper *signalMapper;
};
ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
: QWidget(parent)
{
signalMapper = new QSignalMapper(this);
QGridLayout *gridLayout = new QGridLayout;
for (int i = 0; i < texts.size(); ++i) {
QPushButton *button = new QPushButton(texts[i]);
connect(button, &QPushButton::clicked, signalMapper, &QSignalMapper::map); //设置信号转发给中继者
signalMapper->setMapping(button, texts[i]); //建立转发规则
gridLayout->addWidget(button, i / 3, i % 3);
}
connect(signalMapper, &QSignalMapper::mappedString, this, &ButtonWidget::clicked); //信号最终目的接收者
setLayout(gridLayout);
}
以上相应语句也可以写成:
connect(button,SIGNAL(clicked()),signalMapper,SLOT(map())); //设置信号转发给中继者
connect(signalMapper,SIGNAL(mapped(QString)),this,SLOT(doClicked(QString))); //信号最终目的接收者
connect(signalMapper, SIGNAL(mapped(QString)),this, SLOT(ShowName(QString))); //信号最终目的接收者
void Widget::ShowName(QString name) {
QMessageBox::information(this, "Name", name);
}
另外,现在比较简便直接的方式还是使用槽函数建立关联:
//获得当前窗体的所有以QAbstractButton为父类的对象
QList<QAbstractButton *> tbtns = ui->widgetTop->findChildren<QAbstractButton *>();
foreach (QAbstractButton *btn, tbtns) {
btn->setIconSize(icoSize);
}
//也可以先如下这样进行信号槽函数关联后,在槽函数中具体区分源对象:
connect(btn, SIGNAL(clicked(bool)), this, SLOT(buttonClicked()));
void formWindget::buttonClicked()
{
QAbstractButton *b = (QAbstractButton *)sender();
int count = btns.count();
int index = btns.indexOf(b);
ui->stackedWidget->setCurrentIndex(index);
for (int i = 0; i < count; i++) {
QAbstractButton *btn = btns.at(i);
btn->setChecked(btn == b);
}
}