QT信号与槽函数

  • Post author:
  • Post category:其他


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;
}



版权声明:本文为hqb_newfarmer原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。