美文网首页
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