目录
一、通过图形化方式,在界面上创建出一个控件
二、通过代码方式,创建Hello World
三、Qt 内存泄漏问题
(一) 对象树
一、通过图形化方式,在界面上创建出一个控件
创建项目后,打开双击forms文件夹中的ui文件,可以进入到图形化设计ui的界面。
在左侧找到Display Widgets模块,将Label拉到
双击这个Label模块。可以进行修改,在右下角,也可以对这个控件进行修改。
修改之后,我们的界面相当于存在了一个Label的控件。
在Qt Designer右上角,通过树形结构,显示出来当前界面上都有哪些控件。
保存之后,查看头文件,源文件,其实并没有任何变化,
当我用文本编辑器打开ui文件的时候,会发现多出了一段代码。
在我们运行的时候,会自动的根据多出来的几段代码,编译出来带有Hello World界面的程序。
二、通过代码方式,创建Hello World
一般通过代码来构造界面的时候,通常会把构造界面的代码放到Widget的构造函数中。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLabel *label = new QLabel(this); // 创建Label对象
label->setText("Hello World"); // 设置控件中,要显示的文本文件
}
Qt诞生于1991年,当时C++还没有形成标准,C++更没有标准库这样的改变,当时如何表示一个字符串,可以使用C风格字符串,也可以使用C++的string,Qt为了让自己的开发变得顺畅,就自己发明了一套轮子,搞了一系列的基础类,来支持Qt的开发,包括不限于:字符串QString,动态数组QVector,链表QList,字典QMap等等。
很多年之后,C++中的容器等已经打磨的很好了,但是Qt自己包装好的这些容器类,也不可能删除,就只能和现有的标准库中的容器类共存了。
在QString中,也提供了C风格字符串作为参数的构造函数,不显示构造QString。
运行程序,就显示出了Hello World了,只不过是在左上角,默认的就是在左上角,如果想放到其他位置,可以通过resize来设置。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLabel *label = new QLabel(this); // 创建Label对象
label->setText("Hello World"); // 设置控件中,要显示的文本文件
label->resize(230,240);
}
三、Qt 内存泄漏问题
上面的代码中,label是new出来的一个对象,但是最后却没有使用delete,这不会出现内存泄漏问题吗?内存泄漏,文件描述符泄露等同类问题都是非常严重的。
上述代码并不会产生内存泄漏。label对象会在合适的时候被析构释放(虽然没有手写delete,但却是能释放)
之所以能够把对象释放掉,主要是因为把这个对象是挂到了对象树上。
(一) 对象树
可以看到这个结构类似于一个树形,这里的树上的每一个结点都是一个对象,通过这个树形结构,就把界面上要显示的这些控件都组织起来了。这里的树上的这些对象,统一销毁是最好不过的,如果某个对象提前销毁,此时就会导致对应的控件就在界面上不存在了。所以前面代码中,通过new的方式创建对象,也就是为了把这个对象的生命周期,交给Qt的对象树统一来进行管理。如果这个对象树是在栈上的变量创建的,就可能会存在一些提前释放的问题。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// QLabel *label = new QLabel(this); // 创建Label对象
// label->setText("Hello World"); // 设置控件中,要显示的文本文件
QLabel label(this);
label.setText("hello world");
}
无法显示出来hello world。