coding
unsky
deepdim
thought

QT5从入门到放弃:(1)hello,qt!

开始学习使用c++进行QT5学习

QT是一个1998年开始创办的c++库,其界面设计等能力表现不俗,后来被诺基亚收购,之后诺基亚将其开源,后来诺基亚倒闭,QT右digital接着运营。伴随着c++的发展,QT也从QT1发展到QT5,充分运用了c++的新特性。

环境搭建

QT5的安装非常简单不需要复杂的配置,我使用
Qt 5.7.0 for Windows 64-bit (VS 2013, 904 MB)配合vs2013进行,先安装vs2013再安装QT即可。
具体的可已根据自己的配置选择不同的编译器等。我的配置如下:

hello,qt!

因为我使用的是qt5但是在学习的资料上还是很多使用QT4,其实他们是可以兼容的。在新建工程的时候选择,qt widgets application,就可以使用QT5下兼容qt4的情况。下面在详细的说。

在生成了项目之后,会自动生成六个文件:

现在先从一个基本的空项目开始学习。

基本工程文件.pro

在工程文件.pro里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#-------------------------------------------------
#
# Project created by QtCreator 2016-12-02T20:18:03
#
#-------------------------------------------------
QT += core gui //核心模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //如果使用了qt4则调用widgets
TARGET = helloworld //目标程序
TEMPLATE = app //模板类型,这里是QT widgets application
SOURCES += main.cpp\
hellpdialog.cpp
HEADERS += hellpdialog.h
FORMS += hellpdialog.ui

Qt的核心模块 core 和gui 核心模块

可以看出这个文件里包含了所有的工程信息,
其中
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets这句话的作用就是自动识别QT4并使用QT4语句。使QT5兼容QT4

主程序main.cpp

在这里我们使用空项目进行学习。
删光mian.cpp里的代码我们从最基本的开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<QApplication> //用于管理应用程序的资源,任何GUI程序都需要该类库
#include<QLabel>//标签类
#include<QDialog>//窗口类
//c++主程序
int main(int argc,char * argv[])
{
QApplication QAPP(argc,argv); //建立应用程序资源管理器QAPP
QDialog w; //新建窗口
QLabel winlabel(&w);//新建标签并且将其绑定到窗口上
winlabel.setText("hello,qt");//标签要表达的语句
w.show(); //窗口展示
return QAPP.exec();//返回
}

使用设计师ui

删光原来的工程(剩下main.cpp和helloworld.pro)
然后删掉
build-helloworld-Desktop_Qt_5_7_0_MSVC2013_64bit-Debug文件夹。(注意如果修改了.pro的内容而没有生效的话,要删掉这个文件夹,才可以生效)
然后新建文件:

命名为mydialog
在建立完之后,会生成

1
2
3
mydialog.h //mydiaglog ui类头文件
mydialog.cpp //子函数
mydialog.ui //ui文件

同时在构建之后,ui会在debug文件里生成 ui_mydalog.h

mydialog.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//避免多重包含
#ifndef MYDIALOG_H
#define MYDIALOG_H
#include <QDialog> //使用QDialog定义自己的类
namespace Ui {
class myDialog;
}
class myDialog : public QDialog
{
Q_OBJECT //宏,继承了普通c++类的基本功能
public:
explicit myDialog(QWidget *parent = 0);//构造函数
~myDialog(); //析构函数
private:
Ui::myDialog *ui; //私有变量 ui
};
#endif // MYDIALOG_H

这个程序比较重要,需要比较透彻的理解名字空间:
首先:

1
2
3
namespace Ui {
class myDialog;
}

是Ui::myDialog的前置声明,注意Ui::myDialog 和我们需要使用的类myDialog是两个不同的东西,在这里只进行了前置声明,而并没有具体的定义。

我们需要调用的类myDialog主要负责是主窗口的设计
这是一种组合设计的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
public:
explicit myDialog(QWidget *parent = 0);//构造函数
~myDialog(); //析构函数
```
这段代码主要负责主窗口的附属关系parent=0就是其是根窗口,处理的附属关系。
```cpp
private:
Ui::myDialog *ui; //私有变量 ui
};

myDialog的私有成员,负责具体的Ui实现,使用Ui::myDialog定义了一个ui指针。在整个过程中Ui::myDialog都只是被声明,而没有被定义。

ui_mydalog.h

在这个头文件里主要定义了ui类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/********************************************************************************
** Form generated from reading UI file 'mydialog.ui'
**
** Created by: Qt User Interface Compiler version 5.7.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MYDIALOG_H
#define UI_MYDIALOG_H
//以上两行是预处理命令,能够防止对这个头文件的多重包含
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
QT_BEGIN_NAMESPACE //QT名字命名空间的开始
//定义Ui_myDialog类
class Ui_myDialog
{
public:
QLabel *label;//定义标签
void setupUi(QDialog *myDialog) //生成界面函数
{
if (myDialog->objectName().isEmpty())
myDialog->setObjectName(QStringLiteral("myDialog"));
myDialog->resize(400, 300);
label = new QLabel(myDialog);
label->setObjectName(QStringLiteral("label"));
label->setGeometry(QRect(130, 90, 151, 131));
retranslateUi(myDialog);
QMetaObject::connectSlotsByName(myDialog);
} // setupUi
void retranslateUi(QDialog *myDialog)//实现了窗口内字符串的转换
{
myDialog->setWindowTitle(QApplication::translate("myDialog", "Dialog", 0));
label->setText(QApplication::translate("myDialog", "hello,QT!", 0));
} // retranslateUi
};
//名字空间的结束
namespace Ui {
class myDialog: public Ui_myDialog {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MYDIALOG_H

这段代码就是对Ui::myDialog的具体定义,看以看到,首先定义了一个Ui_myDialog类负责具体的ui细节,然后定义了Ui::myDialog直接继承Ui_myDialog的所有定义。从而完成了对ui的详细设计。

思考: 为什么要用名字空间Ui::myDialog进行,而不直接使用Ui_myDialog进行,而且使用前置定义?

原因(自我思考):

  1. 突出了namespace的作用
  2. 如果ui细节放生了变化,因为是前置声明,所以不需要很大的重新编译,降低了频繁的编译。

mydialog.cpp

自定义类的源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "mydialog.h"
#include "ui_mydialog.h"
myDialog::myDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::myDialog)
{
ui->setupUi(this);
}
myDialog::~myDialog()
{
delete ui;
}

在这里主要是将myDialog的构造和析构

1
2
3
4
5
6
myDialog::myDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::myDialog)
{
ui->setupUi(this);
}

这是myDialog的构造函数,主要负责对publicQDialog(parent)和private ui(new Ui::myDialog)的构造

回归成最简单的定义形式比清楚:

1
2
3
4
5
class a
{ privatechar name;
public: int num;
a(int b,char c):num=b,name=c;
}

剩下的是析构函数,负责销毁

1
2
3
4
5
myDialog::~myDialog()
{
delete ui;
}
`

同时,pro内的内容被更新为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#-------------------------------------------------
#
# Project created by QtCreator 2016-12-02T20:18:03
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = helloworld
TEMPLATE = app
SOURCES += main.cpp \
mydialog.cpp
HEADERS += \
mydialog.h
FORMS += \
mydialog.ui

开始编辑ui文件:

ctrl+s保存之后,看带我们的ui内容被以xml的形式存储:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>myDialog</class>
<widget class="QDialog" name="myDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>130</x>
<y>90</y>
<width>151</width>
<height>131</height>
</rect>
</property>
<property name="text">
<string>hello,QT!</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

调用设计师ui

在设计完ui之后我们需要在主程序里调用:
编写主程序:

1
2
3
4
5
6
7
8
9
#include<QApplication>
#include"mydialog.h"
int main(int argc,char * argv[])
{
QApplication QAPP(argc,argv);
myDialog w; //调用自定义的窗口类
w.show();
return QAPP.exec();
}

总结

几个程序之间的调用关系:

坚持原创技术分享,您的支持将鼓励我继续创作!