我的QT Creator学习笔记(十七)——Qt对象模型之信号和槽机制

参考文献:《Qt Creator 快速入门》第三版 霍亚飞编著

Qt在标准C++对象模型的基础上添加了一些特性,形成了自己的对象模型,这些特性有:

1、一个强大的无缝对象通信机制----信号和槽(signals and slots)

2、可查询可设计的对象属性系统(object properties)

3、强大的事件和事件过滤器(events and event filters)

4、基于上下文的国际化字符串翻译机制(string translation for internationalization)

5、完善的定时器(timers)驱动,可以在一个事件驱动的gui中处理多个任务

6、分层结构的、可查询的对象树(Object trees),它使用一直很自然的方式来组织对象拥有权(object ownership)

7、守卫指针即QPointer,它在引用对象被销毁是自动将其设置为0;

8、动态的对象转换机制(dynamic cast);

9、支持创建自定义类型(custom type)

信号和槽机制是Qt的核心特征,用于两个对象之间的通信。当一个特殊的事件发生时便可以发送一个信号,比如按钮被单击时发送clicked()信号;而槽就是一个函数,它在信号发射后被调用来响应这个信号。Qt的部件类中已经定义了一些信号和槽,更常用的做法是子类化部件,然后添加自定义的信号和槽来实现想要的功能。

1、信号和槽的使用例子

来一个大栗子,栗子功能主界面中创建对话框,对话框可以输入数值,当单机确定按钮时关闭对话框,并将输入的数值通过信号发射处,最后主界面接收到该信号并显示数值。

新建Qt Widgets应用,项目名为mysignalslot,基类选择QWidget。项目建立后往项目中添加新文件,模板选择“Qt设计师界面类”,模板选择Dialog without Buttons,类名设置为MyDialog。完成后使用siganls关键字在mydialog.h中添加自定义信号声明,代码如下

signals:
    void dlgReturn(int);//自定义信号

signals前面不能加Public 、private等限定符,默认是Public 函数。可以从任何地方发射,但建议定义信号的类及其子类发射该信号。信号只用声明,不需要也不能对它进行定义实现。 信号没有返回值只能是void 类型。

进入mydialog.ui文件的设计模式,添加spin box 部件和一个push button部件,转到Button的单击信号对应的槽,修改代码如下,其中使用emit关键字发射信号。

void MyDialog::on_pushButton_clicked()
{
    int value=ui->spinBox->value();
    emit dlgReturn(value);//发射信号
    close();//关闭对话框
}

然后在widget.h中添加自定义槽的声明,如下

private slots:
    void showValue(int value);

槽要使用slots关键字声明,槽最大的特点是可以和信号关联,其他特性和普通c++函数一样。

进入widget.ui的设计模式,拖入label,文本改为“value:”。然后widget.cpp构造函数添加以下代码,将信号与槽关联

    MyDialog* dlg=new MyDialog(this);
    //将对话框中自定义信号与主界面中的自定义槽进行关联
    connect(dlg,SIGNAL(dlgReturn(int)),this,SLOT(showValue(int)));
    dlg->show();

添加自定义槽的实现如下

void Widget::showValue(int value)//自定义槽
{
   ui->label->setText(tr("value:%1").arg(value));
}

运行效果如下

我的QT Creator学习笔记(十七)——Qt对象模型之信号和槽机制_第1张图片我的QT Creator学习笔记(十七)——Qt对象模型之信号和槽机制_第2张图片

 

信号和槽应该注意的几点:

1、需要继承自QObject或其子类

2、在类声明的最开始处添加Q_OBJECT宏

3、槽中参数的类型要和信号参数的类型相对应,且不能比信号的参数多;

4、信号只用声明,没有定义,且返回值为void类型。

2、信号和槽的关联

信号和槽的关联使用QObject类的connect(),connect函数的讲解见我的另一篇博客认识qt 中connect函数。

3、信号和槽的自动关联

由字符串on、部件的objectName和信号名称3部分组成,中间用下划线隔开,这种形式命名的槽可以直接和信号关联,不用再使用connect函数。但是要使用调用connectSlotsByName()函数来支持信号和槽的关联(在setupUi函数中调用了该函数),并且必须使用setObjectName指定它们的objectName,才能正常使用自动关联。

代码例子:函数声明

private slots:
    void on_myButton_clicked();

在setupUi函数之前,定义部件并指定objectName代码如下

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    QPushButton* button=new QPushButton(this);//创建按钮
    button->setObjectName("myButton");//指定按钮的对象名
    ui->setupUi(this);
}

 

实现槽函数

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    QPushButton* button=new QPushButton(this);//创建按钮
    button->setObjectName("myButton");//指定按钮的对象名
    ui->setupUi(this);
}

自动关联使用不多,还是使用connect函数比较多。

4、断开关联

可以使用disconnect函数来断开信号和槽的关联,其原型如下

[static] bool QObject::disconnect(const QObject *sender, const char *signal, \
const QObject *receiver, const char *method)

从帮助文档中可以看到有以下几种使用方法

我的QT Creator学习笔记(十七)——Qt对象模型之信号和槽机制_第3张图片

 

最后信号和槽机制的特色和优越性:

1、类型安全的,相关联的信号和参数必须匹配

2、松耦合,信号发送者不知道也不需要知道接收者的信息

3、信号和槽可以使用任意类型的任意参数量的参数

 

 

 

 

你可能感兴趣的:(qt,creator学习笔记,c++,Qt5,类)