Qt Creator中使用QSignalMapper给QPushButton槽传参失效问题
问题描述
在Qt Creator开发游戏时,尝试用QSignalMapper实现三个设置按钮点击时传递整数1、2、3到setDesiredSetting(int)槽函数,但点击按钮后槽函数未触发,终端无qInfo输出。相关代码如下:
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QLineEdit> #include <QSignalMapper> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private: Ui::MainWindow *ui; private slots: void setDesiredSetting(int desiredSetting); }; #endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // Desired game theme selected QSignalMapper mapper; connect(ui->themeOneButton, SIGNAL(released()), &mapper, SLOT (map())); mapper.setMapping(ui->themeOneButton, 1); connect(&mapper, SIGNAL(mapped(int)), this, SLOT (setDesiredSetting(int))); //connect(ui->themeTwoButton, &QPushButton::clicked, this, &MainWindow::setDesiredSetting(2)); //connect(ui->themeThreeButton, &QPushButton::clicked, this, &MainWindow::setDesiredSetting(3)); } void MainWindow::setDesiredSetting(int desiredSetting) { qInfo("Setting selected: %d \n", desiredSetting); }
问题原因
QSignalMapper生命周期失效:你在MainWindow构造函数中声明了局部QSignalMapper mapper,构造函数执行完毕后该局部对象会被立即销毁,后续按钮点击时信号没有可发送的目标,自然无法触发槽函数。- 注释代码写法错误:
connect(ui->themeTwoButton, &QPushButton::clicked, this, &MainWindow::setDesiredSetting(2));这种写法是直接调用了函数,而非传递槽函数地址,Qt信号槽不支持这种传参方式。
正确实现方式
方法1:修复QSignalMapper用法
将QSignalMapper改为类成员变量,保证其生命周期与MainWindow一致:
修改mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QLineEdit> #include <QSignalMapper> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); // 添加析构函数 private: Ui::MainWindow *ui; QSignalMapper* m_signalMapper; // 声明为成员变量 private slots: void setDesiredSetting(int desiredSetting); }; #endif // MAINWINDOW_H
修改mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); m_signalMapper = new QSignalMapper(this); // 初始化,指定父对象自动管理内存 // 绑定所有按钮到mapper的map槽 connect(ui->themeOneButton, &QPushButton::released, m_signalMapper, &QSignalMapper::map); connect(ui->themeTwoButton, &QPushButton::released, m_signalMapper, &QSignalMapper::map); connect(ui->themeThreeButton, &QPushButton::released, m_signalMapper, &QSignalMapper::map); // 设置按钮与整数的映射关系 m_signalMapper->setMapping(ui->themeOneButton, 1); m_signalMapper->setMapping(ui->themeTwoButton, 2); m_signalMapper->setMapping(ui->themeThreeButton, 3); // 绑定mapper的信号到目标槽函数 connect(m_signalMapper, &QSignalMapper::mappedInt, this, &MainWindow::setDesiredSetting); } MainWindow::~MainWindow() { delete ui; } void MainWindow::setDesiredSetting(int desiredSetting) { qInfo("Setting selected: %d \n", desiredSetting); }
方法2:使用Lambda表达式(Qt 5及以上推荐)
无需QSignalMapper,直接通过Lambda表达式传递参数,代码更简洁:
修改mainwindow.cpp构造函数部分
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 绑定三个按钮,通过Lambda传递对应参数 connect(ui->themeOneButton, &QPushButton::released, this, [this](){ setDesiredSetting(1); }); connect(ui->themeTwoButton, &QPushButton::released, this, [this](){ setDesiredSetting(2); }); connect(ui->themeThreeButton, &QPushButton::released, this, [this](){ setDesiredSetting(3); }); } void MainWindow::setDesiredSetting(int desiredSetting) { qInfo("Setting selected: %d \n", desiredSetting); }
内容的提问来源于stack exchange,提问作者DemonSlayer
相关产品推荐
相关产品推荐

