美文网首页
2018-01-11:Qt5界面开发中如何渲染出界面

2018-01-11:Qt5界面开发中如何渲染出界面

作者: ShapeYourself | 来源:发表于2018-01-11 20:12 被阅读0次

    在Qt5项目中要想让程序运行时显示出我们设计的界面,关键是要执行界面文件生成的类中的setupUi(QWidget *Widget)函数,否则界面是无法显示出来的.

    首先,我们来看一下自动生成的Qt5项目中是如何调用界面类中的setupUi()函数的.

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    
    namespace Ui {
    class Widget;
    }
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = 0);
        ~Widget();
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::Widget *ui;
    };
    
    #endif // WIDGET_H
    

    可以看出,在该头文件中,首先是前置声明了Ui界面类,也就是通过uic工具,将我们设计的.ui文件翻译成标准的界面头文件中的界面类.
    然后,定义了一个一个继承自QWidget的类Widget, 并且将界面类的作为其私有子对象.

    namespace Ui {
    class Widget;
    }
    ...
    
    private:
        Ui::Widget *ui;
    

    接着我们来看widget.cpp
    widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::on_pushButton_clicked()
    {
    
    }
    

    可以看出,在这里,继承自QWidget的Widget类的构造函数实现了对类Widget子对象ui实现了初始化操作

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this); #这里的this就是调用构造函数的对象
    }
    

    一种与上面等效的简单直接的方式如下:

    #include <QApplication>
    #include <QDialog>
    #include "ui_dialog.h"
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Ui::Dialog ui;
        QDialog *d=new QDialog;
        ui. setupUi(d);
        d->show();
        return a.exec();
    }
    

    main.cpp文件

    #include "widget.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w;
        w.show();
    
        return a.exec();
    }
    

    界面头文件
    ui_widget.h

    /********************************************************************************
    ** Form generated from reading UI file 'widget.ui'
    **
    ** Created by: Qt User Interface Compiler version 5.9.3
    **
    ** WARNING! All changes made in this file will be lost when recompiling UI file!
    ********************************************************************************/
    
    #ifndef UI_WIDGET_H
    #define UI_WIDGET_H
    
    #include <QtCore/QVariant>
    #include <QtWidgets/QAction>
    #include <QtWidgets/QApplication>
    #include <QtWidgets/QButtonGroup>
    #include <QtWidgets/QHeaderView>
    #include <QtWidgets/QPushButton>
    #include <QtWidgets/QWidget>
    
    QT_BEGIN_NAMESPACE
    
    class Ui_Widget
    {
    public:
        QPushButton *pushButton;
    
        void setupUi(QWidget *Widget)
        {
            if (Widget->objectName().isEmpty())
                Widget->setObjectName(QStringLiteral("Widget"));
            Widget->setEnabled(false);
            Widget->resize(927, 533);
            QIcon icon;
            icon.addFile(QStringLiteral("../../python3_project/heihei.png"), QSize(), QIcon::Normal, QIcon::Off);
            Widget->setWindowIcon(icon);
            Widget->setWindowOpacity(0.5);
            pushButton = new QPushButton(Widget);
            pushButton->setObjectName(QStringLiteral("pushButton"));
            pushButton->setGeometry(QRect(430, 250, 106, 29));
    
            retranslateUi(Widget);
            QObject::connect(pushButton, SIGNAL(clicked()), Widget, SLOT(close()));
    
            QMetaObject::connectSlotsByName(Widget);
        } // setupUi
    
        void retranslateUi(QWidget *Widget)
        {
            Widget->setWindowTitle(QApplication::translate("Widget", "MyWidget", Q_NULLPTR));
            pushButton->setText(QApplication::translate("Widget", "PushButton", Q_NULLPTR));
        } // retranslateUi
    
    };
    
    namespace Ui {
        class Widget: public Ui_Widget {};
    } // namespace Ui
    
    QT_END_NAMESPACE
    
    #endif // UI_WIDGET_H
    
    

    补充资料 1:
    使用new创建对象指针
    使用delete删除对象指针
    使用new创建对象对象的同时,会返回对象的指针,因此,我们需要定义一个类的指针变量来接收返回的对象指针.

    ClassName *object=new ClassName(param);
    delete object;
    

    除了这种通过new方法创建对象外,还有我们最常用的创建对象的方式:

    ClassName object(param);
    

    这样就声明了一个ClassName类型的object对象,C++会为它分配足够的存放对象所有成员的存储空间.
    注意:为节省存储空间,C++创建对象时仅分配用于保存数据成员的空间,而类中定义的成员函数则被分配到存储空间中的一个公用区域,由该类的所有对象共享.
    这种方法创建的对象,内存分配是分配到栈中的,由C++缺省创建和撤销,自动调用构造函数和析构函数.
    注意:该方法创建的对象调用类方法时,必须用“.”,而不能用“->”.
    使用这种方式创建的类对象,在创建之初就已经分配了内存空间. 而类指针,如果未经过对象初始化,则不需要delete释放, 因为没有初始化就没有为指针绑定的对象分配内存.
    一般来说,编译器将内存分为三部分:静态存储区域、栈、堆。静态存储区主要保存全局变量和静态变量,栈存储调用函数相关的变量、地址等,堆存储动态生成的变量
    C++中有三种创建对象的方法:

    #include <iostream>  
    using namespace std;  
    class A  
    {  
    private:  
        int n;  
    public:  
        A(int m):n(m)  
        { }  
        ~A(){}  
    };  
    int main()  
    {  
        A a(1);  //栈中分配  
        A b = A(1);  //栈中分配  
        A* c = new A(1);  //堆中分配  
      delete c;  
        return 0;  
    }
    

    第一种和第二种没什么区别,一个隐式调用,一个显式调用,两者都是在进程虚拟地址空间中的栈中分配内存,而第三种使用了new,在堆中分配了内存,而栈中内存的分配和释放是由系统管理,而堆中内存的分配和释放必须由程序员手动释放。采用第三种方式时,必须注意一下几点问题:

    new创建类对象需要指针接收,一处初始化,多处使用
    new创建类对象使用完需delete销毁
    new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
    new对象指针用途广泛,比如作为函数返回值、函数参数等
    频繁调用场合并不适合new,就像new申请和释放内存一样
    栈的大小远小于堆的
    栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率 比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在 堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会 分 到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

    参考文献

    补充资料 2
    什么是堆内存?什么是栈内存?
    栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结
    构中的栈。
    内存中的栈区处于相对较高的地址以地址的增长方向为上的话,栈地址是向下增长的。

    栈中分配局部变量空间,堆区是向上增长的用于分配程序员申请的内存空间。另外还有静态区是分配静态变量,全局变量空间的;只读区是分配常量和程序代码空间的;以及其他一些分区。

    相关文章

      网友评论

          本文标题:2018-01-11:Qt5界面开发中如何渲染出界面

          本文链接:https://www.haomeiwen.com/subject/ggktoxtx.html