1. 信号和槽的概念
信号和槽是Qt框架中用于实现对象之间通信的机制。信号用来表示一个事件或状态的发生,而槽则是对这个事件或状态作出响应的函数。
在使用信号和槽时,一个对象发出信号,其他对象则可以连接到这个信号上,当信号被触发时,连接的槽函数将会被自动调用。
2.特点
1. 可以在不同的对象之间进行通信,使对象间的解耦更加灵活。
2. 一个信号可以连接多个槽函数,多个信号也可以连接到一个槽函数。
3. 信号和槽可以是不同的参数类型,可以通过信号参数和槽参数的转换进行匹配。
4. 信号和槽可以在同一个对象中定义和连接,也可以在不同的对象中进行连接。
使用信号和槽机制可以实现对象之间的相互交互和数据传递,使程序的结构更加清晰和可维护。
3. 系统自带的信号和槽
3.1 connect()函数最常用的一般形式
connect(sender, signal, receiver, slot);
3.2 参数解释
sender:发出信号的对象
signal:发送对象发出的信号
receiver:接收信号的对象
slot:接收对象在接收到信号之后所需要调用的函数(槽函数)
3.3 代码展示
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//创建一个按钮,点击按钮关闭窗口
this->close();
QPushButton *p = new QPushButton("关闭", this);
//设置链接,点击按钮会产生信号,调用窗口的close函数
connect(p, &QPushButton::clicked, this, &QWidget::close);
}
4. 按钮常用的信号
那么系统自带的信号和槽通常如何查找呢,这个就需要利用帮助文档了,在帮助文档中比如我们上面的按钮的点击信号,在帮助文档中输入 QPushButton,首先我们可以在Contents中寻找关键字 signals,信号的意思,但是我们发现并没有找到,这时候我们应该想到也许这个信号的被父类继承下来的,因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个
这里的clicked就是我们要找到,槽函数的寻找方式和信号一样,只不过他的关键字是slot
5. 自定义槽函数
.h头文件
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
QPushButton *button;
public slots:
//槽函数
void print();
};
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
button = new QPushButton;
button->setParent(this);
button->setText("王者荣耀");
//注册信号与槽的链接
//槽函数可以是普通的成员函数,还可以是槽函数
//如果信号没有参数,槽函数也不能有参数;如果信号有参数,槽函数可以有参数,也可以有参数
connect(button, &QPushButton::pressed, this, &Widget::print);
}
void Widget::print()
{
qDebug() << "王者荣耀之李白最强!";
}
6. 自定义信号
6.1 sonwidget.h
class Sonwidget : public QWidget
{
Q_OBJECT
public:
explicit Sonwidget(QWidget *parent = 0);
QPushButton *button2;
signals:
//信号没有返回值,可以有参数
//信号函数不需要定义,只需要声明
void show_hide_signal(int a);
public slots:
void emit_mysignal();
};
6.2 sonwidget.cpp
Sonwidget::Sonwidget(QWidget *parent) : QWidget(parent)
{
this->setWindowTitle("子窗口!");
button2 = new QPushButton("显示父窗口,隐藏子窗口!", this);
connect(button2, &QPushButton::clicked, this, &Sonwidget::emit_mysignal);
}
void Sonwidget::emit_mysignal()
{
//点击按钮的槽函数,发射信号
emit show_hide_signal(100);
}
6.3 widget.h
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
Sonwidget *sonwindow;
QPushButton *button1;
public slots:
void button_cb();
void signal_cb(int a);
};
6.4 widget.cpp
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
this->setWindowTitle("父窗口!");
this->sonwindow = new Sonwidget;
sonwindow ->show();
button1 = new QPushButton;
button1->setText("隐藏父窗口,显示子窗口!");
button1->setParent(this);
connect(button1, &QPushButton::clicked, this, &Widget::button_cb);
connect(sonwindow, &Sonwidget::show_hide_signal, this, &Widget::signal_cb);
}
void Widget::button_cb()
{
this->hide();
this->sonwindow->show();
}
void Widget::signal_cb(int a)
{
qDebug() << a;
this->show();
this->sonwindow->hide();
}
7. 自定义信号和槽的注意事项
自定义信号和槽是Qt框架中用于实现对象之间的通信的重要机制。在使用自定义信号和槽时,有一些注意事项需要注意:
1. 自定义信号和槽必须声明在QObject或其派生类中。只有继承自QObject的类才能使用信号和槽机制。
2. 自定义信号和槽的声明必须在类的头文件中进行。信号和槽的声明使用Q_SIGNALS和Q_SLOTS宏来标记。
3. 自定义信号和槽的函数原型必须与QObject类中的信号和槽原型一致。原型中的参数类型必须是QObject或其派生类的指针。
4. 自定义信号和槽可以被多次连接和断开连接。可以通过connect函数和disconnect函数来连接和断开自定义信号和槽。
5. 自定义信号和槽可以被重载。重载的信号和槽会根据参数类型的不同自动选择匹配的信号和槽。
6. 自定义信号和槽可以使用Qt元对象系统中提供的元对象宏来进行扩展和使用。例如,可以使用Q_EMIT宏来发射信号。
7. 自定义信号和槽可以在不同的线程中使用。但是在不同线程中使用信号和槽时,需要注意线程安全性。
总之,使用自定义信号和槽时需要注意信号和槽的声明、参数类型和重载等问题,以确保正确地实现对象之间的通信。
8. 信号与槽在QT4中的写法
SIGNAL和SLOT不会检查里面的字符串
这里使用了SIGNAL和SLOT这两个宏,将两个函数名转换成了字符串。注意到connect()函数的signal 和 slot 都是接受字符串,一旦出现连接不成功的情况,Qt4是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。
9. Lambda表达式
C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。首先看一下Lambda表达式的基本构成:
[capture](parameters) mutable ->return-type
{
statement
}
[函数对象参数] (操作符重载函数参数) mutable -> 返回值{函数体}
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
button = new QPushButton("点我有奖", this);
int a = 10;
int b = 20;
//槽函数可以是一个Lambda表达式
connect(button, &QPushButton::clicked, this, [&]() mutable->int{
a = 100;
qDebug() << a;
qDebug() << b;
qDebug() << "点我有奖";
});
}
注意:
- Lambda表达式中[]中写的是 = ,代表上面的函数中的局部变量是以值传递的方式传入到Lambda表达式中
- Lambda表达式中[]中写的是 &,代表上面的函数中的局部变量是以引用传递的方式传入到Lambda表达式中
- Lambda表达式中[]中写的是 a,代表上面的函数中的局部变量是以a传递的方式传入到Lambda表达式中
- Lambda表达式中[]中写的是 &a,代表上面的函数中的局部变量是以a的引用传递的方式传入到Lambda表达式中
- mutabl可以修饰了,作用是可以在Lambda修改传入变量的值
- -> 代表Lambda表达式返回值是一个int类型