QT对象模型与容器类-信号和槽(1)

QT对象模型与容器类
核心机制:对象模型 信号和槽,属性系统,对象树与拥有权,元对象系统等。
容器类:Container Class QString QByteArray QVariant和正则表达式的使用等相关内容。
一个强大的无缝对象通信机制:信号和槽 signals and slots
可查阅、可设计的对象属性系统 object properities
强大的事件过滤器 events and event filters
信号和槽机制是 Qt 的核心机制,可以让编程人员将互不相关的对象绑定在一起,实现对象之间的通信。
信号
当对象改变其状态时,信号就由该对象发射 (emit) 出去,而且对象只负责发送信号,它不知道另一端是谁在接收这个信号。这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用。

用于接收信号,而且槽只是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且对象并不了解具体的通信机制。
信号与槽的连接
所有从 QObject 或其子类 ( 例如 Qwidget ) 派生的类都能够包含信号和槽。因为信号与槽的连接是通过 QObject 的 connect() 成员函数来实现的。

connect(sender, SIGNAL(signal), receiver, SLOT(slot));

其中 sender 与 receiver 是指向对象的指针,SIGNAL() 与 SLOT() 是转换信号与槽的宏。
一个信号可以连接多个槽
当信号发射时,会以不确定的顺序一个接一个的调用各个槽。
多个信号可以连接同一个槽
即无论是哪一个信号被发射,都会调用这个槽。
信号直接可以相互连接
发射第一个信号时,也会发射第二个信号。
连接可以被移除
这种情况用得比较少,因为在对象被删除时,Qt会自动移除与这个对象相关的所有连接。语法如下:
disconnect(sender, SIGNAL(signal), receiver, SLOT(slot));

在Qt中我们有一种可以替代回调的技术。我们使用信号和槽。当 一个特定事件发生的时候,一个信号被发射。Qt的窗口部件有很多预定义的信号, 但是我们总是可以通过继承来加入我们自己的信号。槽就是一个可以被调用处理特定 信号的函数。Qt的窗口部件又很多预定义的槽,但是通常的习惯是你可以加入自己的 槽,这样你就可以处理你所感兴趣的信号。

从QObject类或者它的一个子类 (比如QWidget类)继承的所有类可以包含信号和槽。 当对象改变它们的状态的时候,信号被发送,从某种意义上讲,它们也许对外面的 世界感兴趣。这就是所有的对象通讯时所做的一切。它不知道也不注意无论有没有 东西接收它所发射的信号。这就是真正的信息封装,并且确保对象可以用作一个软 件组件。

声明一个信号要使用signals关键字:
(1)在signals前面不能用public,private和protected等限定符,因为信号默认是public函数
(2)可以从任何地方进行发射,但是只建议定义该信号的类及其子类中发射该信号
(3)信号只用声明,不需要也不能对他进行定义实现
(4)信号没有返回值,只能是void类型的。
(5)只有QOject类及其派生的子类才能使用信号和槽机制
使用信号和槽还必须在类声明的最开始处,添加Q_OBJECT宏,在这个程序中,类的声明是自动生成的,已经添加了这个宏。

class myDialog : public QDialog
{
    Q_OBJECT              //必须在类的声明的开始处添加宏

public:
    explicit myDialog(QWidget *parent = 0);
    ~myDialog();
private:
    Ui::myDialog *ui;
signals:
    void dlgReturn(int); //自定义的信号
};

#endif // MYDIALOG_H

转到槽

void myDialog::on_pushButton_clicked()
{
    int value = ui->spinBox->value();//获取输入的数值
    emit dlgReturn(value);           //发射信号
    close();                         //关闭对话框
}

然后在widget.h文件中添加自定义槽的声明:

private slots:
    void showValue(int value);

槽就是普通的C++函数,声明槽要使用slots关键字
一个槽可以是private,public或者protected类型,槽也可以声明为虚函数,和普通的成员函数一样。
槽的最大特点是可以和信号关联

信号与槽应该注意以下几点:
需要继承自QObject或者其他类
在类声明的最开始处添加Q_OBJECT宏
在槽中参数的类型号和信号参数相对应,且不能比信号的参数多。
信号只用声明,并没有定义,且返回值为void类型

信号和槽的关联使用的是Qobject类的connect()函数,该函数的原型如下:

[static]QMetaObject::Connection QObject::connect(const QObjcet *sender,   //发射信号的对象
                                                 const char * signal,     //要发射的信号
                                                 const QObject *receiver, //接收信号的对象
                                                 const char *method,      //要执行的槽
                                           Qt::ConnectionType type = Qt::AutoConnection)

第四个参数是要执行的槽,这里是SLOT,必须使用slots关键字。connect()函数的返回值为:QMetaObjectConnect类型
该返回值可以用来用于QObject::disconnect(const QMetaObject::Connection&connection)函数来断开关联。
对于信号和槽的参数问题:基本原则是,信号中的参数类型要和槽中的参数类型相对应,而且信号的参数可以多余槽中的·参数但不能反过来。
最后一个参数,表明type表明了关联的方式:

重点:MyDialog类中使用了emit发射了信号之后,就会立即执行槽,只有等槽执行完了以后,才会执行emit语句后面的代码。

Qt::AutoConnection:
Qt::DirectConnecitonQt::QueuedConnection:
Qt::BlockQueuedConnection
Qt::UniqueConnection

Connect()函数另一种常用的基于函数指针的重载形式如下:

[static]QMetaObject::Connection QObject::connect(const QObject *sender,
                                                 PointerToMemberFunction signal, //指针对象::信号
                                                 const QObject *receiver,
                                                 PointerToMemberFunction method, //指针对象::槽
                                          Qt::ConnectionType type = Qt::AutoConnection)

指定信号和槽两个参数时,不在使用SIGNAL()和SLOT宏
信号槽机制共有三种方法:
(1)SIGNAL SLOT法
例子:

   connect(dlg,SIGNAL(dlgReturn(int)),this,SLOT(showValue(int)));

(2)重载法(指针对象法)
例子:
connect(dlg,&MyDialog::dlgReturn,this,&Widget::showValue);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值