1.信号与槽函数的作用(通信机制)
用来在组件和组件,组件和窗口之间通信
温故知新: Linux中进程间通信signal(你要捕捉的信号,函数指针)
QT信号 槽函数
信号:QT中给每个组件都定义了信号,每个信号都有它特定的触发条件(QT助手有介绍每个信号在什么条件下触发)
QT中所有的信号,本质上都是个函数,但是有点特殊,信号只有声明,没有源代码
比如:以按钮为例,常用的信号如下
[signal] void QAbstractButton::clicked(bool checked = false) //当按钮按下去,然后松开的时候自动触发这个信号
如何查看某个组件有哪些信号呢?
方法一:在QT助手中查看(前面有[signal]全部都是信号)
方法二:在QT creator开发环境中右键点击组件,选择转到槽,会自动弹出对话框,对话框中有所有的信号
槽函数:当某个信号触发的时候,跟这个信号对应的槽函数会被自动调用执行
2.如何关联信号与槽函数
第一种方法:借助集成开发环境,右键转到槽函数
头文件中会自动生成槽函数的声明
private slots: //声明了一个私有的槽函数
void on_pushButton_clicked(); //槽函数的原型声明
自动生成的槽函数,命名有规律
on_对象的名字_信号的名字();
注意:组件对象的名字是可以修改的(类对象视图中双击组件对象的名字,即可修改)
第二种方法:程序员调用connect函数手动关联信号与槽函数
connect(QObject *sender, PointerToMemberFunction signal,QObject *receiver, PointerToMemberFunction method)
参数:sender –》信号的发送者,指针
signal –》发送什么信号
receiver –》信号的接收者
method –》需要调用的槽函数
槽函数命名时候,可以跟自动生成的槽函数命名规律保持一致,也可以自行单独命名
比如:connect(ui->handlebt,SIGNAL(clicked(bool)),this,SLOT(fun())); //关联了handlebt这个按钮的clicked信号和槽函数fun()
QT使用技巧:头文件中声明了函数,右键选择refactor,可以在.cpp生成函数的定义
//右键转到槽,自动生成了槽函数的声明和定义,代码空着,留给程序员自由发挥
void MainWindow::on_mybt_clicked()
{
qDebug()<<"按钮被彭老师按下去,松开了";
}
void MainWindow::on_mybt_released()
{
qDebug()<<"按钮松开了";
}
void MainWindow::on_testbt_clicked()
{
qDebug()<<"另外一个按钮被点击了";
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//我手动关联ui中的按钮和槽函数
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(fun()));
//在主窗口类的构造函数中,新建一个按钮对象
QPushButton *mybt=new QPushButton("实现ui做法二:手动写代码创建了该按钮对象",this);
//设置坐标,宽高
mybt->setGeometry(200,300,300,70);
connect(mybt,SIGNAL(clicked()),this,SLOT(on_mybt_clicked()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::fun()
{
qDebug()<<"我自己写的槽函数fun调用了";
}
void MainWindow::on_mybt_clicked()
{
qDebug()<<"我自己写的槽函数on_mybt_clicked调用了";
}
补充知识点:
QObject –》QT中所有类的祖先
4.总结信号与槽的特点
第一个:一个类如果要使用信号以及槽函数,那么该类的定义中必须加上Q_OBJECT宏定义
Q_OBJECT:QT把它称为元对象系统,作用支持信号与槽这种机制
第二个:同一个槽函数,可以被不同对象的信号关联
第三个:同一个信号,可以关联多个不同的槽函数
多个槽函数的调用顺序跟你关联的先后顺序一致,先关联的先调用
第四个:信号带参数,槽函数可以带参数,也可以不带参数
区别:槽函数带参数,参数类型,参数个数必须跟信号保持一致,表示槽函数接收信号传递过来的参数
槽函数不带参数,表示我不想接收信号传递过来的参数
同一个信号可以关联不同的槽函数
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//同一个信号clicked关联三个不同的槽函数
connect(ui->bt,SIGNAL(clicked()),this,SLOT(fun3()));
connect(ui->bt,SIGNAL(clicked()),this,SLOT(fun1()));
connect(ui->bt,SIGNAL(clicked()),this,SLOT(fun2()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::fun1()
{
qDebug()<<"fun1调用了";
}
void MainWindow::fun2()
{
qDebug()<<"fun2调用了";
}
void MainWindow::fun3()
{
qDebug()<<"fun3调用了";
}
同一个槽函数被不同的对象信号所关联
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//三个按钮共用一个槽函数
connect(ui->bt1,SIGNAL(clicked()),this,SLOT(fun()));
connect(ui->bt2,SIGNAL(clicked()),this,SLOT(fun()));
connect(ui->bt3,SIGNAL(clicked()),this,SLOT(fun()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::fun()
{
qDebug()<<"三个按钮其中一个按钮被点击了";
}
信号带参数,槽函数带参数与不带参数
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//手动关联textChanged(const QString &text)信号
//connect(ui->le,SIGNAL(textChanged(QString)),this,SLOT(fun()));
connect(ui->le,SIGNAL(textChanged(QString)),this,SLOT(fun(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
//void MainWindow::fun()
void MainWindow::fun(QString arg)
{
//qDebug()<<"信号有带参数,但是槽函数就不写参数,你能把我怎么样";
qDebug()<<"信号有带参数,槽函数也带参数,参数是: "<<arg;
}
5.获取信号的发送者
作用:当多个组件对象共用一个槽函数的时候,程序员需要知道是哪个组件对象触发的信号,此时就要获取信号的发送者
QObject *sender() const
返回值:返回一个指针,该指针指向信号的发送者
QT中转换函数(子类指向父类)
qobject_cast(QObject *object) //模板函数
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//三个按钮共用一个槽函数
connect(ui->bt1,SIGNAL(clicked()),this,SLOT(fun()));
connect(ui->bt2,SIGNAL(clicked()),this,SLOT(fun()));
connect(ui->bt3,SIGNAL(clicked()),this,SLOT(fun()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::fun()
{
//区分,判断究竟是哪个按钮触发了fun()
//获取信号的发送者
QPushButton *p=qobject_cast<QPushButton *>(sender());
if(p==ui->bt1) //说明用户点击的是bt1
qDebug()<<"用户点击的是按钮1";
if(p==ui->bt2) //说明用户点击的是bt2
qDebug()<<"用户点击的是按钮2";
if(p==ui->bt3) //说明用户点击的是bt3
qDebug()<<"用户点击的是按钮3";
}
两种实现UI界面的做法区别
=====================================
1.哪两种实现UI的做法
做法一:通过ui设计师界面直接拖组件过来
QT会在构造函数的ui->setupUi(this);中帮你自动创建对象指针,并且分配堆空间(自动完成的)
通过ui设计师界面直接拖组件过来使用的一定是堆空间
做法二:程序员写代码,创建组件对象
此时所有的组件都是你自己编写代码实现的,跟ui->setupUi(this)没有任何关系
程序员自己编写代码创建对象无非就两种情况:
情况一:使用栈空间 QPushButton mybt(“登录”,this);
情况二:使用堆空间 QPushButton *mybt=new QPushButton(“登录”,this);2.这两种情况,我要使用组件对象,该如何使用??
通过ui设计师界面直接拖组件过来
ui->组件对象指针->成员方法()
比如:ui->pushButton->setFont(myfont);
程序员写代码,创建组件对象
对象.成员方法()
对象指针->成员方法()
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//在主窗口类的构造函数中,新建一个按钮对象
QPushButton *mybt=new QPushButton("实现ui做法二:手动写代码创建了该按钮对象",this);
//设置坐标,宽高
mybt->setGeometry(200,300,300,70);
//如何区分ui设计师拖过来的按钮,以及你自己手动创建的按钮
//我要把ui拖过来的按钮字体设置成楷体 18号字
QFont myfont("楷体",18);
ui->pushButton->setFont(myfont);
//我要把手动创建的按钮字体设置成楷体 18号字
mybt->setFont(myfont);
}
MainWindow::~MainWindow()
{
delete ui;
}