槽函数定义的规则
1.槽函数返回值类型为void
2.槽函数的参数不能多于信号的参数(只能小于等于信号的参数个数)
关联信号与槽错误的示例
按钮被点击触发一个点击信号,从而导致死循环,之后会导致程序中断。
m_btn = new QPushButton("Button", this);
//错误的示例
connect(m_btn, &QPushButton::clicked, m_btn, &QPushButton::click);
类成员函数函数做槽函数使用
类中做槽函数的成员函数一般写在public slots下,Qt5以及以上版本可以不写public slots。
#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QPushButton>
#include <QMessageBox>
//去掉控制台
#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
class Widget : public QWidget
{
Q_OBJECT // 使用信号与槽机制必须包含此宏
public:
Widget(QWidget* parent = nullptr)
:QWidget(parent)
{
setWindowTitle("自定义槽"); // 设置窗口标题
resize(640, 480); // 设置窗口大小
m_btn = new QPushButton("成员函数", this);
//使用信号与槽关联类成员函数
connect(m_btn, &QPushButton::pressed, this, &Widget::onPressSlot);
}
~Widget()
{
}
public slots:
void onPressSlot()
{
QMessageBox::information(this, "提示",
"类成员函数作为槽函数使用", QMessageBox::Ok);
}
private:
QPushButton* m_btn = nullptr;
};
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
静态类成员函数做槽函数使用
class Widget : public QWidget
{
Q_OBJECT // 使用信号与槽机制必须包含此宏
public:
Widget(QWidget* parent = nullptr)
:QWidget(parent)
{
setWindowTitle("自定义槽"); // 设置窗口标题
resize(640, 480); // 设置窗口大小
m_btn = new QPushButton("成员函数", this);
//使用信号与槽关联静态类成员函数
connect(m_btn, &QPushButton::pressed, this, &Widget::onPressSlot1);
}
~Widget()
{
}
public slots:
static void onPressSlot1()
{
QMessageBox::information(nullptr, "提示",
"静态类成员函数作为槽函数使用", QMessageBox::Ok);
}
private:
QPushButton* m_btn = nullptr;
};
全局函数做槽函数使用
void globalSlot()
{
QMessageBox::information(nullptr, "提示",
"全局函数作为槽函数使用", QMessageBox::Ok);
}
class Widget : public QWidget
{
Q_OBJECT // 使用信号与槽机制必须包含此宏
public:
Widget(QWidget* parent = nullptr)
:QWidget(parent)
{
setWindowTitle("自定义槽"); // 设置窗口标题
resize(640, 480); // 设置窗口大小
m_btn = new QPushButton("全局函数", this);
//使用信号与槽关联全局函数
connect(m_btn, &QPushButton::pressed, this, globalSlot);
}
~Widget()
{
}
public slots:
private:
QPushButton* m_btn = nullptr;
};
lambda表达式做槽函数使用
class Widget : public QWidget
{
Q_OBJECT // 使用信号与槽机制必须包含此宏
public:
Widget(QWidget* parent = nullptr)
:QWidget(parent)
{
setWindowTitle("自定义槽"); // 设置窗口标题
resize(640, 480); // 设置窗口大小
m_btn = new QPushButton("lambda", this);
//lambda表达式做槽函数使用
connect(m_btn, &QPushButton::pressed, this, []() {
QMessageBox::information(nullptr, "提示",
"lambda表达式作为槽函数使用", QMessageBox::Ok);
});
}
~Widget()
{
}
public slots:
private:
QPushButton* m_btn = nullptr;
};
使用lambda表达式的注意事项
这样使用是没有问题的,但是如果想让cnt的值每点击一次就++,就需要使用引用捕获的方式。
m_btn = new QPushButton("Button", this);
int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=]() {
m_btn->setText(QString::number(cnt));
});
注意事项一:
使用引用捕获的方式捕获cnt会导致错误,因为cnt是一个栈区变量,构造函数结束内存会被销毁。
m_btn = new QPushButton("Button", this);
int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=,&cnt]() {
m_btn->setText(QString::number(cnt++));
});
使用mutable的方式解决上述问题
m_btn = new QPushButton("Button", this);
int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=]() mutable{
m_btn->setText(QString::number(cnt++));
});
使用静态变量解决上述问题
m_btn = new QPushButton("Button", this);
static int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=](){
m_btn->setText(QString::number(cnt++));
});
注意事项二:
当m_btn是类成员变量时,使用引用捕获的方式捕获是没有错误的。
m_btn = new QPushButton("Button", this);
static int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [&](){
m_btn->setText(QString::number(cnt++));
});
当m_btn是局部变量的时候,使用引用捕获的方式会直接导致程序中断。因为此时的m_btn为栈区内存,构造函数结束之后内存被释放。因此,尽量避免使用引用捕获的方式去捕获。
auto m_btn = new QPushButton("Button", this);
static int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [&](){
m_btn->setText(QString::number(cnt++));
});