力战者
力战者,天酬之!

初识QT

  一:   hello-world:

#include "mainwindow.h"
#include <QApplication>
#include <QLabel>
#include <qpushbutton.h>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //QLabel lable("hello world");
    QPushButton button("Quit");
   
    button.show();
    //lable.show();

    return a.exec();
}

注意:

QLabel *label = new QLabel("Hello, world");

  label 是没办法 delete 的这里存在着内存泄露。

  严重的是,label 是建立在堆上的,app 是建立在栈上的。这意味着,label 会在 app 之后析构。也就是说,label 的生命周期长于 app 的生命周期。这可是 Qt 编程的大忌。因为在 Qt 中,所有的 QPaintDevice 必须要在有 QApplication 实例的情况下创建和使用。大家好奇的话,可以提一句,QLabel 继承自 QWidget,QWidget 则是 QPaintDevice 的子类。之所以上面的代码不会有问题,是因为 app 退出时,label 已经关闭,这样的话,label 的所有 QPaintDevice 一般都不会被访问到了。但是,如果我们的程序,在 app 退出时,组件却没有关闭,这就会造成程序崩溃。

 

二: 信号槽

  信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,用自己的一个函数(称为槽(slot))来处理这个信号。

#include "mainwindow.h"
#include <QApplication>
#include <QLabel>
#include <qpushbutton.h>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //QLabel lable("hello world");
    QPushButton button("Quit");
    QObject::connect(&button, &QPushButton::clicked, &QApplication::quit);
    button.show();
    //lable.show();

    return a.exec();
}

QObject::connect() 有五个重载:

QMetaObject::Connection connect(const QObject *, const char *,const QObject *, const char *,Qt::ConnectionType);
 
QMetaObject::Connection connect(const QObject *, const QMetaMethod &,const QObject *, const QMetaMethod &,Qt::ConnectionType);
 
QMetaObject::Connection connect(const QObject *, const char *,const char *,Qt::ConnectionType) const;
 
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,const QObject *, PointerToMemberFunction,Qt::ConnectionType)
 
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,Functor);

connect() 函数最常用的一般形式:

connect(sender,   signal, receiver, slot);

  connect() 一般会使用前面四个参数,第一个是发出信号的对象,第二个是发送对象发出的信号,第三个是接收信号的对象,第四个是接收对象在接收到信号之后所需要调用的函数。也就是说,当 sender 发出了 signal 信号之后,会自动调用 receiver 的 slot 函数。

五个重载:

  第一个,sender 类型是 const QObject *,signal 的类型是 const char *,receiver 类型是 const QObject *,slot 类型是 const char *。这个函数将 signal 和 slot 作为字符串处理。

  第二个,sender 和 receiver 同样是 const QObject *,但是 signal 和 slot 都是 const QMetaMethod &。我们可以将每个函数看做是 QMetaMethod 的子类。因此,这种写法可以使用 QMetaMethod 进行类型比对。

  第三个,sender 同样是 const QObject *,signal 和 slot 同样是 const char *,但是却缺少了 receiver。这个函数其实是将 this 指针作为 receiver。

  第四个,sender 和 receiver 也都存在,都是 const QObject *,但是 signal 和 slot 类型则是 PointerToMemberFunction。看这个名字就应该知道,这是指向成员函数的指针。

  第五个,前面两个参数没有什么不同,最后一个参数是 Functor 类型。这个类型可以接受 static 函数、全局函数以及 Lambda 表达式。

 

由此我们可以看出,connect() 函数,sender 和 receiver 没有什么区别,都是 QObject 指针;主要是 signal 和 slot 形式的区别。

 

posted on 2019-05-08 16:20  力战者  阅读(513)  评论(0编辑  收藏  举报