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::DirectConneciton:
Qt::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);