• 一个稍微复杂的Qt程序

    《第一个Qt程序》中使用 MainWindow 作为主界面,内置一个 QLabel 控件,所有代码都写在 main() 函数内部。本节我们将主要代码封装到一个类的内部,然后在 main() 函数中创建该类的对象,这貌似更加符合 C++ 规范。

    编写代码

    我们在 D:\QtDemo 文件夹创建三个代码文件,分别是 MyMainWindow.h、MyMainWindow.cpp 和 main.cpp,各个文件的具体代码如下所示。

    1) MyMainWindow.h 文件代码:

    #ifndef MYMAINWINDOW_H
    #define MYMAINWINDOW_H
    
    #include <QtWidgets/QMainWindow>
    #include <QtWidgets/QLabel>
    
    class MyMainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        MyMainWindow();
        ~MyMainWindow();
    private:
        QLabel *m_pLabel;
    };
    
    #endif

    MYMAINWINDOW_H 可以防止头文件被重复包含,不了解的读者请猛击《防止C语言头文件被重复包含》。

    Q_OBJECT 是一个宏,这种写法对初学者来说是非常陌生的,它是 Qt 自己的语法扩展。Qt 的这种做法像极了早期的 C++:

    • C++ 在C语言的基础上发展而来,C++ 扩展了C语言的语法,早期的 C++ 代码都是先被转换为C语言代码,再使用C语言编译器编译。
    • Qt 是基于 C++ 的,但是它对 C++ 的语法进行了扩展(比如信号和槽机制、内省机制等),并增加了一些关键字(例如 signals、slots、emit 等),在真正编译之前,扩展语法先被转换成 C++ 代码(通过 moc 工具),然后再使用 C++ 编译器编译。

    Qt 想要的功能 C++ 没有,怎么办?那就自己上,亲自实现这个功能!为了支持这些扩展功能,Qt 甚至实现了一个微型编译器——元对象编译器(Meta-Object Compiler, moc)。

    C++ 为了保持程序运行的高效性,仅通过 RTTI(Run-Time Type Information,运行时类型识别)提供了非常简陋的内省机制,几乎没有用武之地。Qt 抛弃了 C++ 自带的内省机制,另起炉灶,创造了更加强大的元对象(meta object)系统,以此来支持完整的内省机制。

    Q_OBJECT 宏就声明了 Qt 元对象系统必须的函数和成员变量,之后我们会用 moc 工具生成元对象系统的实体函数代码。继承 Qt 类时建议在类声明的开头添加 Q_OBJECT 宏,否则有时会出现莫名其妙的错误;如果你使用了信号和槽机制,Q_OBJECT 宏就是必须添加的,因为信号和槽依赖于元对象系统。

    2) MyMainWindow.cpp 文件代码:

    #include "MyMainWindow.h"
    
    MyMainWindow::MyMainWindow(): QMainWindow(){
        this -> setWindowTitle("MyMainWindow演示");  //设置标题
        this -> resize(360, 140);  //设置客户区大小
    
        m_pLabel = new QLabel("C", this);
        m_pLabel -> setGeometry(130, 50, 160, 30);  //设置Label控件的几何尺寸
    }
    
    MyMainWindow::~MyMainWindow(){
        delete m_pLabel;
        m_pLabel = NULL;
    }

    该源文件里只有一个构造函数和一个析构函数。注意析构函数,它删除之前 new 的标签控件对象,并把指针设置为 NULL。

    3) main.cpp 文件代码:

    #include <QtWidgets/QApplication>
    #include "MyMainWindow.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        MyMainWindow w;
        w.show();
    
        return app.exec();
    }

    main 函数还是一如既往的简单,由于使用自定义的 MyMainWindow 作为主窗口类,所以是包含了 MyMainWindow.h 和 QApplication 两个头文件。

    编译代码

    需要手工编写的代码就这些,接下来的任务就是如何编译生成可执行程序了。

    前面提到 Qt 元对象系统,Qt 是基于 C++ 开发的,而 C++ 本身并没有元对象系统。元对象系统是 Qt 专门为 C++ 做的扩展功能,用于支持非常强大的信号/槽机制、内省机制等,后面我们会详细讲解,本节我们重点学习 moc 工具的使用。下面逐步介绍编译链接本节程序的过程。

    1) 进入文件夹

    打开 Qt 命令行工具,进入代码所在文件夹:

    cd /d D:\QtDemo

    2) 使用 moc 工具

    使用 moc 工具生成 MyMainWindow 类的元对象系统代码文件 moc_MyMainWindow.cpp :

    moc MyMainWindow.h -o moc_MyMainWindow.cpp

    moc 工具会搜索头文件 MyMainWindow.h 里面所有的 Q_OBJECT 宏,并生成相应的元对象系统实际源代码,输出保存为 moc_MyMainWindow.cpp 文件。

    3) 编译和链接 .cpp 文件

    加上刚才手动编写的 MyMainWindow.cpp 和 main.cpp,我们总共要编译三个 C++ 源码文件:

    g++  moc_MyMainWindow.cpp MyMainWindow.cpp main.cpp  -std=c++0x  -I"D:\Qt\5.9\mingw53_32\include"  -L"D:\Qt\5.9\mingw53_32\lib"  -lQt5Core -lQt5Gui -lQt5Widgets  -o main

    4) 运行 main.exe

    生成 main.exe 之后,在 Qt 命令行工具里输入main.exe命令就可以执行该程序,看到显示的效果。

    生成main.exe的整个流程
    生成 main.exe 的整个流程

更多...

加载中...