0.信号和槽的概念
- 信号和槽是QT自行定义的一种通信机制,实现对象之间的数据交互。
- 当用户或系统触发了一个动作,导致某个控件的状态发生了改变,该控件就会发射一个信号,即调用其类中一个特定的成员函数(信号),同时还可能携带必要的参数。
- 槽和普通的成员函数几乎没有太多区别,可以是共有的、保护的或私有的,可以被重载,也可以被覆盖,其参数可以是任意类型,并可以像普通成员函数一样调用。
- 槽函数与普通成员函数的差别并不在于其语法特性,而在其功能。槽函数更多体现为对某种特定信号处理,可以将槽和其他对象建立连接,这样当发射信号是,槽函数将被触发和执行,进而完成具体功能。
1.信号的定义
class XX:public QObject{
Q_OBJECT
signals:
void signal_func(..); // 信号函数
}
注:信号函数只需声明,不能写定义。
2.槽的定义
class XX:public QObject{
Q_OBJECT
public slots:
void slot_func(...){...}; // 槽函数
}
注:槽函数可以连接到某个信号上,当信号被发射时,槽函数将被触发和执行,另外槽函数也可以当做普通的成员函数直接调用。
3.信号和槽的连接
QObject::connect(const QObject*sender,const char*signal,
const QObject*receiver,const char*method);
参数:
sender:信号发送对象指针
signal:要发送的信号函数,可以使用“SIGNAL(…)”宏进行类型转换
receiver:信号的接受对象指正
method:接受信号后要执行的槽函数,可以使用“SLOT(…)”宏进行转换
4.案例:创建Qt应用程序,包含标签和按钮两个控件,实现点击按钮关闭标签
- 按钮点击时发送信号:clicked()
- 实现标签关闭功能的槽:close()
#include "widget.h"
#include<QDialog>
#include<QLabel>
#include<QPushButton>
#include<QTextCodec>
#include <QApplication>
#pragma execution_character_set("utf-8")
int main(int argc, char *argv[])
{
// 创建Qt应用程序对象
QApplication app(argc,argv);
QDialog parent;
parent.move(50,50);
parent.resize(320,240);
// 创建标签控件,停靠在父窗口上面
QLabel label("我是小洋",&parent);
label.move(20,40);
// 创建按钮控件,停靠在父窗口上面
QPushButton button("我是按钮",&parent);
button.move(20,100);
button.resize(80,80);
QPushButton button2("退出",&parent);
button2.move(170,100);
button2.resize(80,80);
parent.show();
// 点击按钮关闭标签
QObject::connect(&button,SIGNAL(clicked(void)),
&label,SLOT(close(void)));
QObject::connect(&button2,SIGNAL(clicked(void)),
//&app,SLOT(closeAllWindows(void)));
//&app,SLOT(quit(void)));
&parent,SLOT(close(void)));
// 让应用程序进入事件
return app.exec();
}
5. 信号和槽连接的语法要求
- 信号和槽参数要一致
QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int))); // OK
QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int,int))); // ERROR
- 可以带省略参数
QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int,int=0))); // OK
- 信号函数的参数可以多于槽函数,多余参数将被省略
QObject::connect(A,SIGNAL(sigfun(int,int)),B,SLOT(slotfun(int))); // OK
6.信号和槽连接的应用
- 一个信号可以被连接到多个槽(一对多)
QObject::connect(A,SIGNAL(sigfun(int)),B1,SLOT(slotfun1(int))); // OK
QObject::connect(A,SIGNAL(sigfun(int)),B2,SLOT(slotfun1(int))); // OK
- 多个信号也可以连接到同一个槽(多对一)
QObject::connect(A1,SIGNAL(sigfun1(int)),B,SLOT(slotfun(int))); // OK
QObject::connect(A2,SIGNAL(sigfun2(int)),B,SLOT(slotfun(int))); // OK
- 两个信号可以直接连接(信号级联)
QObject::connect(A1,SIGNAL(sigfun1(int)),A2,SIGNAL(sigfun2(int))); // OK
7.案例:创建Qt应用程序,包含滑块(QSlider)和选值框(QSpinBox),通过信号和槽的机制,保持同步运行
1.QSlider // 滑块
- void setRange (int min, int max); // 设置滑动范围
- void setValue(int)[slot]; // 设置当前位置
- void vlaueChanged(int value)[signal]; // 滑块滑动时发送信号
2.QSpinBox // 选值框
- void setRange(int min, int max); // 设置数值改变范围
- void setValue(int)[slot]; // 设置当前数值
- void vlaueChanged(int value)[signal]; // 选值框数值改变时发送信号
#include "widget.h"
#include <QApplication>
#include <QDialog>
#include <QSlider>
#include <QSpinBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.resize(320,240);
// 创建水平滑块
QSlider slider(Qt::Horizontal,&w);
slider.move(20,100);
slider.setRange(0,200);
// 创建选值框控件
QSpinBox spin(&w);
spin.move(220,100);
spin.setRange(0,200);
// 滑块滑动让选值框数值随值改变
QObject::connect(&slider,SIGNAL(valueChanged(int)),
&spin,SLOT(setValue(int)));
// 选值框数值改变影响滑块
QObject::connect(&spin,SIGNAL(valueChanged(int)),
&slider,SLOT(setValue(int)));
w.show();
return a.exec();
}