赞
踩
利用Qt Creator组件创建一个可视化界面,仅需要几步就可以完成。
新建一个名字为helloworld的Qt的项目,利用Qcreator打开如下所示:
利用树形图直观的展示每个项目文件夹和文件的功能如下:
后缀为“.pro”的文件是项目的管理文件,文件名就是项目的名称,分析其文件源码:
#------------------------------------------------- # # Project created by QtCreator 2023-07-18T14:59:01 // 创作时间 # #------------------------------------------------- QT += core gui // 表示项目中加入core gui模块,core gui是Qt用于GUI设计的类库模块,除此之丸Qt还有很多的模块,例如Qt GUI、Qt SQL等等 //Qt类库以模块的形式组织各种功能的类,根据项目涉及的功能需求,在项目中添加适当的类库模块支持。例如,如果项目中使用到了涉及数据库操作的类就需要用到sql 模块,在pro 文件中需要增加如下一行:Qt += sql greaterThan(QT_MAJOR_VERSION, 4): QT += widgets // 这是个条件执行语句,表示当Qt主版本大于4 时,才加入widgets模块。 因为后面使用的类都包含在widgets模块中 TARGET = helloworld // 表示生成的目标可执行文件的名称,即编译后生成的可执行文件是helloworld.exe。 TEMPLATE = app // 表示项目使用的模板是app,是一般的应用程序。 除了app还有lib建立一个故的makefile等等 DEFINES += QT_DEPRECATED_WARNINGS // 用于定义预处理器宏。预处理器宏是一种编译时进行文本替换的机制,可以在代码中使用宏来定义条件编译、功能开关等。 /* 在C++中,可以使用#ifdef和#ifndef指令来检查宏是否已经定义。 ifdef:如果宏已经定义,则执行后面的代码块。 例如: #ifdef QT_DEPRECATED_WARNINGS // 执行代码块,如果QT_DEPRECATED_WARNINGS已经定义 #else // 执行代码块,如果QT_DEPRECATED_WARNINGS没有定义 #endif ifndef:如果宏没有定义,则执行后面的代码块。 #ifndef QT_DEPRECATED_WARNINGS 例如: // 执行代码块,如果QT_DEPRECATED_WARNINGS没有定义 #else // 执行代码块,如果QT_DEPRECATED_WARNINGS已经定义 #endif */ // 这些文件列表是Qt Creator自动添加到项目管理文件里面的,用户不需手动修改。当添加一个文件到项目,或从项目里删除一个文件时,项目管理文件里的条目会自动修改。 SOURCES += \ // 记录了项目中包含的源程序文件的名称 main.cpp FORMS += \ // 记录了项目中包含的头文件的名称 hellodialog.ui HEADERS += \ // 记录了项目中包含的窗体文件(.ui文件)的名称 hellodialog.h
/******************************************************************************** ** Form generated from reading UI file 'hellodialog.ui' ** ** Created by: Qt User Interface Compiler version 5.9.0 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ // 前面两句和最后一句是要添加UI_HELLODIALOG_H这个头文件之前要检查头文件是否已经存在,防止重复包含 #ifndef UI_HELLODIALOG_H #define UI_HELLODIALOG_H // 包含了及各类的头文件 #include <QtCore/QVariant> #include <QtWidgets/QAction> #include <QtWidgets/QApplication> #include <QtWidgets/QButtonGroup> #include <QtWidgets/QDialog> #include <QtWidgets/QHeaderView> #include <QtWidgets/QLabel> // 与后面的QT_END_NAMESPACE一起是Qt的命名空间开始宏和结束宏 QT_BEGIN_NAMESPACE class Ui_HelloDialog //定义了一个Ui_HelloDialog类,在前面更改的对话框类HelloDialog之前加上一个Ui_(默认的名字) { public: QLabel *label; //定义了一个QLabel类对象的指针,这个就是对话框窗口添加的Label部件 void setupUi(QDialog *HelloDialog) // 用来生成界面,因为选择模板时选择的是对话框,所以函数的参数是QDialog类型 { // 设置对话框的对象名称 if (HelloDialog->objectName().isEmpty()) HelloDialog->setObjectName(QStringLiteral("HelloDialog")); // 设置了窗口的大小 HelloDialog->resize(400, 300); // 在对话框上创建了标签对象 label = new QLabel(HelloDialog); // 设置标签对象的名称(objectname) label->setObjectName(QStringLiteral("label")); // 设置标签对象的位置(默认左上角为(0, 0)) 和 大小(长71 宽31) label->setGeometry(QRect(120, 120, 71, 31)); // 该函数实现对窗口里面的字符串进行编码转换的功能 retranslateUi(HelloDialog); //调用了QMetaObject这个类里面的connectSlotsByName()函数,使得窗口中的部件可以实现按对象名进行信号和槽的关联 QMetaObject::connectSlotsByName(HelloDialog); } // setupUi // 该函数实现对窗口里面的字符串进行编码转换的功能 void retranslateUi(QDialog *HelloDialog) { HelloDialog->setWindowTitle(QApplication::translate("HelloDialog", "Dialog", Q_NULLPTR)); label->setText(QApplication::translate("HelloDialog", "Hello World", Q_NULLPTR)); } // retranslateUi }; // 定义了命名空间Ui namespace Ui { class HelloDialog: public Ui_HelloDialog {}; // Ui里面定义了一个HelloDialog继承自Ui_HelloDialog类 } // namespace Ui QT_END_NAMESPACE #endif // UI_HELLODIALOG_H
// 前面两句和最后一句是要添加HELLODIALOG_H这个头文件之前要检查头文件是否已经存在,防止重复包含, #ifndef HELLODIALOG_H // 这是一个条件编译指令,用于检查是否已经包含了名为"HELLODIALOG_H"的头文件。如果已经包含了该头文件,则下面的代码将被忽略,否则会继续编译下去。 #define HELLODIALOG_H // 这是一个预处理指令,用于定义一个名为"HELLODIALOG_H"的宏。 #include <QDialog> // 基类 Qt的三个大基类之一 另外两个为:QWidget、QMainWindow /* 这是声明了一个名称为Ui 的命名空间(namespace),包含一个类HelloDialog。但是这个类HelloDialog并不是本文件里定义的类HelloDialog,而是ui_hellodialog.h文件里定义的类,用于描述界面组件的。这个声明相当于一个外部类型声明(具体要看完ui_hellodialog.h文件内的解释之后才能搞明白)。 */ namespace Ui { // 前置声明(前置声明只能作为指针或引用,不能定义类的对象,自然也就不能调用对象中的方法了。)加快编译速度 //使用命名空间:避免在一个头文件中随意包含其他文件而产生错误,这里只使用了该类对象的指针,并不需要该类的完整定义 class HelloDialog; // 命名空间的解析Ui::HelloDialog } class HelloDialog : public QDialog // 主体部分是一个继承于QDialog的新定义的类HelloDialog。 { Q_OBJECT // 扩展功能,在HelloDialog类中使用了宏Q_OBJECT,这是提供了Qt 的信号与槽(signal 和slot)机制 public: // 定义了HelloDialog类的构造函数和析构函数,两个函数都是只定义,但没有实现 // 用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 跟它相对应的另一个关键字是implicit隐藏的,类构造函数默认情况下即声明为implicit(隐式). explicit HelloDialog(QWidget *parent = 0); // 默认参数为0 ~HelloDialog(); private: Ui::HelloDialog *ui; // Ui::HelloDialog 表示是属于前面Ui命名空间里面的类HelloDialog的指针,不加的话会被识别成本文件HelloDialog的指针 }; #endif // HELLODIALOG_H
#include "ui_hellodialog.h" // ui_hellodialog.h文件中已经包含了上面的三个类,故上面的三个类可以注释掉
// main函数程序入口
// argc 命令行便令的数量
// argv 命令行变量的数组
int main(int argc, char *argv[])
{
QApplication a(argc, argv); //实例化一个应用程序的对象a,Qt中有且仅有一个应用程序对象
QDialog w; // 实例化QDialog对象
Ui::HelloDialog ui; // 使用命名空间Ui中断HelloDialog类定义一个ui对象
ui.setupUi(&w); // 将对话框类对象作为参数,这样可以将设计好的界面应用到对象w所表示的对话框上了。
w.show(); // 让对话框显示出来
return a.exec(); // a.exec() 进入一个消息循环机制 main函数是在栈上面的,代码一行一行执行完后就停止,但是调用消息循环机制后,窗口不消失,一直在展示 阻塞代码:即执行到此的时候,代码不往下执行了
}
#include "hellodialog.h" // 由于在hellodialog.h中只是前置声明了Ui,而前置声明只能作为指针或引用,不能定义类的对象,自然也就不能调用对象中的方法了。 #include "ui_hellodialog.h" // 故这里需要导入以可以实例化Ui /* 实现HelloDialog的构造函数和析构函数 */ /* c++构造函数后面跟“:”也表示赋值 1)对含有对象成员的对象进行初始化 类line有两个私有对象成员startpoint、endpoint,line的构造函数写成: line(int sx,int sy,int ex,int ey):startpoint(sx,sy),endpoint(ex,ey){……} 2)对于不含对象成员的对象,初始化时也可以套用上面的格式,例如, 类rectangle有两个数据成员length、width,其构造函数写成: rectangle():length(1),width(2){} rectangle(int x,int y):length(x),width(y){} 3)对父类进行初始化,例如, CDlgCalcDlg的父类是MFC类CDialog,其构造函数写为: CDlgCalcDlg(CWnd* pParent ): CDialog(CDlgCalcDlg::IDD, pParent) */ // HelloDialog对其父类QDialog进行初始化,如果parent指定了则传给父类,若没有指定则默认用0 HelloDialog::HelloDialog(QWidget *parent) :QDialog(parent), ui(new Ui::HelloDialog) { // ui(new Ui::HelloDialog)放在上面的作用与 ui= new Ui::HelloDialog 放在这里是一样的 创建Ui::HelloDialog对象 ui->setupUi(this); // this表示为现在这个类所代表的对话框创建界面。 } // 类内定义函数,类外实现函数的形式 HelloDialog::~HelloDialog() // HelloDialog:: 表示~HelloDialog()是属于HelloDialog这个类的函数,不加的话会被识别成普通的函数 { delete ui; }
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>HelloDialog</class> <widget class="QDialog" name="HelloDialog"> <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>120</x> <y>120</y> <width>71</width> <height>31</height> </rect> </property> <property name="text"> <string>Hello World</string> </property> </widget> </widget> <resources/> <connections/> </ui>
在解析上面源码的时候发现有两个本不同的类却被取相同的名字 – HelloDialog,将Ui命名空间内的类名改为HelloDialog_Ui,将涉及到HelloDialog_Ui的地方去替换,再观察代码便于去区分理解:
#ifndef UI_HELLODIALOG_H #define UI_HELLODIALOG_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 class Ui_HelloDialog { public: QLabel *label; void setupUi(QDialog *HelloDialog) { ''' ''' } // setupUi // 该函数实现对窗口里面的字符串进行编码转换的功能 void retranslateUi(QDialog *HelloDialog) { ''' ''' } // retranslateUi }; // 定义了命名空间Ui namespace Ui { class HelloDialog_Ui: public Ui_HelloDialog {}; // Ui里面定义了一个HelloDialog_Ui继承自Ui_HelloDialog类 } // namespace Ui QT_END_NAMESPACE #endif // UI_HELLODIALOG_H
#ifndef HELLODIALOG_H #define HELLODIALOG_H #include <QDialog> namespace Ui { class HelloDialog_Ui; // 命名空间的解析Ui::HelloDialog_Ui } class HelloDialog : public QDialog { Q_OBJECT public: explicit HelloDialog(QWidget *parent = 0); // 默认参数为0 ~HelloDialog(); private: Ui::HelloDialog_Ui *ui; // Ui::HelloDialog_Ui 表示是属于前面Ui命名空间里面的类HelloDialog_Ui的指针 }; #endif // HELLODIALOG_H
#include "hellodialog.h"
#include "ui_hellodialog.h"
HelloDialog::HelloDialog(QWidget *parent) :QDialog(parent), ui(new Ui::HelloDialog_Ui)
{
ui->setupUi(this);
}
// 类内定义函数,类外实现函数的形式
HelloDialog::~HelloDialog() // HelloDialog:: 表示~HelloDialog()是属于HelloDialog这个类的函数,不加的话会被识别成普通的函数
{
delete ui;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。