侧边栏壁纸
博主头像
半生瓜のblog

THIS IS NO END.

  • 累计撰写 278 篇文章
  • 累计创建 3 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

【QT】QT元对象系统

xuanxuan
2021-01-13 / 0 评论 / 0 点赞 / 7 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于2024-02-14,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

QT元对象系统(Meta-Object-System)

元对象系统

元对象系统是一个基于标准C++的扩展,为QT提供了信号与槽机制、实时类型信息、动态属性系统。

元对象系统的三个基本条件:类必须继承自QObject、类声明Q_OBJECT宏(默认私有)、元对象编译器moc。

信号与槽机制是QT的核心机制,信号与槽是一种高级接口,应用于对象之间的通信。信号和槽是QT自行定义的一种通信机制,它独立于标准的C/C++语言,要正确的处理信号和槽,必须借助一个称为moc(Meta-Object-Compiler),也就是"元对象编译器"。

它为高层次的事件处理自动生成所需要的必要代码。QT程序在交由标准编译器编译之前,先要使用moc分析C++源文件。如果moc发现在一个类头文件中包含了函Q_OBJECT,则会生成以moc_className.cpp(自定义类名)的.cpp文件。这个源文件中包含了Q_OBJECT宏的实现代码。新的文件同样将进入编译系统,与源文件一起参与编译。构建生成的.o文件包含与moc生成的.cpp文件中。


信号与槽

产生的历史背景:

GUI用户界面中,当用户操作一个窗口部件时,需要其他窗口部件响应,传统方式经常使用callback(回调机制)来实现。所谓回调即事先将函数指针作为一个参数传递给另一个函数,然后在函数处理过程中适当地方调用函数。

回调机制有两个缺陷:类型不安全,不能保证调用过程中使用正确的参数,强耦合,处理函数必须知道调用哪个回调函数。

QT的信号与槽机制:

QT的信号与槽机制是类型安全的,松耦合,更灵活,更方便。

信号与槽(Signal & Slot)是QT编程的基础,也是QT的一大创新。因为有了信号与槽机制的编程,在QT中处理界面的各个组件的交互操作时变得更加直观个简单。

信号(Signal)就是在特定情况下被发射的事件,例如PushButton最常见的信号就是鼠标单击时发射的clicked()信号。发生信号使用QT的emit关键字。QT的signals关键字指出进入了信号的声明区,随后即可声明自己的信号。

槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以声明在类的任何部分(public、private or protected),可以具有任何参数,也可以被直接调用。

槽函数与一般的函数不同的是:槽函数可以与一个信号关联(connect),当信号被发射时, 关联的槽函数被自动执行。

信号与槽链接方式

image-20220112131738342

信号与槽链接( 一对一)

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    //自定义信号
    //信号的声明
    //信号不用实现也不能实现
signals:
    void Comeon(QString& str);

private slots:
    //同样可以手动添加槽方法-或者在设计模式中添加槽方法
    void on_WorldBtn_clicked();

    void on_CNBtn_clicked();

    void on_BJBtn_clicked();

    void startSend(QString& str);
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<qdebug.h>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //链接信号与槽
    //默认是自动关联
    //将信号和处理这个信号的槽方法相连接起来,connect只负责将它们两个链接在一起
    //至于谁发的,就无所谓了。
    connect(this,SIGNAL(Comeon(QString&)),this,SLOT(startSend(QString&)));
 //或者 //connect(this,&MainWindow::Comeon,this,&MainWindow::startSend);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_WorldBtn_clicked()
{
    //发射信号
    QString str = "Hello World!";
    emit Comeon(str);
}

void MainWindow::on_CNBtn_clicked()
{
    QString str = "Hello China!";
    emit Comeon(str);
}

void MainWindow::on_BJBtn_clicked()
{
    QString str = "Hello BeiJing!";
    emit Comeon(str);
}

void MainWindow::startSend(QString &str)
{
    //打印调试信息
     qDebug()<<str;
}

信号与槽链接(一对多)

一个信号对应多个槽方法。可以多个槽响应一个信号。

示例:

    connect(this,SIGNAL(Comeon(QString&)),this,SLOT(startSend(QString&)));
    connect(this,SIGNAL(Comeon(QString&)),this,SLOT(HelloCN()));
    connect(this,SIGNAL(Comeon(QString&)),this,SLOT(HelloCHP()));

注意:一般情况下多个槽方法的参数个数保持一致,但是,有的时候,可以不使用信号传过来的这个参数,所以槽方法的参数个数可以比信号传递的参数个数少,但是,不能比信号传递过来的参数数量多。

错误示范:

 connect(this,SIGNAL(Comeon(QString&)),this,SLOT(HelloCN(QString&,int)));

链接失败。


信号与槽链接(多对一)

多个信号链接一个槽方法。进一步反应了信号与槽机制的灵活性。

示例:

  connect(this,SIGNAL(Comeon(QString&)),this,SLOT(HelloCHP()));
  connect(this,SIGNAL(Comeon2()),this,SLOT(HelloCHP()));
  connect(this,SIGNAL(Comeon3()),this,SLOT(HelloCHP()));
  connect(this,SIGNAL(Comeon4()),this,SLOT(HelloCHP()));

参数设置见上《信号与槽链接(一对多)》。


信号与信号(一对一)

当一个信号发射时,发射另一个信号。

connect(this,SIGNAL(Comeon4()),this,SIGNAL(Comeon3())); 

断开信号与槽链接

断开一个信号和一个与它相链接的槽方法。

disconnect,参数同connect

    disconnect(this,SIGNAL(Comeon(QString&)),this,SLOT(startSend(QString&)));

断开所有与该信号相连接的槽方法。

与上面不同的是,后两个参数置为0,所有的对象,和所有的槽方法。

 disconnect(this,SIGNAL(Comeon(QString&)),0,0),;

断开指定对象的所有信号与的指定对象的所有槽方法

qDebug()<<"断开this所有信号与this的所有槽方法的链接";
disconnect(this,0,this,0);

disconnect(this,0,0,0);//断开this所有相关的对象的槽方法的链接

也可以通过connect函数的返回值来断开某个链接。

//获取返回值
......
    private:
            QMetaObject::Connection m_res;//返回值类型
......
       m_res = connect(this,SIGNAL(Comeon(QString&)),this,SLOT(startSend(QString&)));//获取返回值
......
    disconnect(m_res);//断开链接

总结-信号与槽机制的优越性:

  1. 信号与槽机制是类型安全的,相关联的信号与槽参数必需匹配(详细解释在上,相关联的槽方法的参数只能少不能多)
  2. 信号与槽是松耦合的,信号发送者不知道也不需要知道接受者的信息。
  3. 信号与槽可以使用任意类型的任意数量的参数。、

动态属性系统

在标准C++中,为了保证封装性,我们经常声明一个私有变量,然后声明两个共有函数例如set,get来对这个变量进行操作。

同理,在QT中我们可以使用宏Q_PROPERTY()来实现这些,函数可以使用QObject::property()和QObject::setProperty()。

在使用的时候,我们不用知道变量的所在类的任何细节,只需要知道名字即可。

Q_PROPERTY(type name
             (READ getFunction [WRITE setFunction] |
              MEMBER memberName [(READ getFunction | WRITE setFunction)])
             [RESET resetFunction]
             [NOTIFY notifySignal]
             [REVISION int]
             [DESIGNABLE bool]
             [SCRIPTABLE bool]
             [STORED bool]
             [USER bool]
             [CONSTANT]
             [FINAL])

示例:

......
    Q_PROPERTY(QString mask READ mask WRITE setMask NOTIFY maskChanged)
......
    QObject* obj  = myPc;
    qDebug()<<obj->property("mask").toString();
    qDebug()<<obj->property("mask").toString();
0

评论区