【Qt5】入门Qt开发教程,一篇文章就够了(Creator、混合开发、多窗体、资源文件、打包发布、exe图标) 您所在的位置:网站首页 零基础做设计的软件 【Qt5】入门Qt开发教程,一篇文章就够了(Creator、混合开发、多窗体、资源文件、打包发布、exe图标)

【Qt5】入门Qt开发教程,一篇文章就够了(Creator、混合开发、多窗体、资源文件、打包发布、exe图标)

2024-07-08 09:20| 来源: 网络整理| 查看: 265

时间是人类生活的空间,我们在时域上展开生活,构建自己的世界

零|说明 本文面向初学者介绍Qt5开发,不求全面 但求过程完整 每个步骤只说明【一种】操作方式 代码和操作并重 在给出代码的同时介绍开发环境的使用 力图使读者能较容易地【复现】任务 快速熟悉从【开发意图】到【打包发布】的一整套开发流程 一|任务导向

本文向Qt初学者介绍开发一款自定义的Notepad,也就是仿照Windows自带的记事本小应用的流程。 主界面如下: 在这里插入图片描述

界面说明

1:自定义的窗口图标,运行时在任务栏中显示的图标与之一致; 2:自定义窗口标题; 3:自定义工具栏,使用了自选的矢量图标; 4:将多个txt文档嵌入到同一个窗口中。

对初学Qt的朋友而言,首先要做的是熟悉Qt的开发环境,为了让读者把精力集中到开发技术的学习上,本文只介绍Qt Creator这种官方提供的集成开发环境(IDE)进行开发的过程。

二|认识Qt Creator开发环境

初见 不了解Qt Creator的朋友可以自行检索或到Qt官网了解。这里只需要知道,我们将使用这个工具完成接下来的开发就行了。

Qt Creator的下载和安装 1、官方通道下载速度比较着急,最好使用国内镜像源。找不到镜像源的额朋友可以参考我这篇文章:https://blog.csdn.net/qq_33904382/article/details/108632625 通过这篇文章介绍的告诉下载链接,可以很快下载完成,节省不必要的等待时间。

2、安装全程跟随安装引导点点点即可,略感困难的朋友可以参考我这篇文章:https://blog.csdn.net/qq_33904382/article/details/108643419中的图例,对照着完成Qt的安装。

新建工程 在Qt Creator中建立工程文件和在其他开发环境中类似,这里可以参考这篇文章:https://blog.csdn.net/qq_33904382/article/details/108743493建立一个名为Notepad的工程。 在这里插入图片描述

注意我们在Kits这个步骤和链接文章中不同,我们在这里选择的编译工具是MinGW 32bit,这和编译以及打包发布有较大关联。为了避免不必要的麻烦,建议初学的朋友和本文保持一致。

查看工程内容 建立工程后,会自动打开,Qt Creator切换到Edit界面: 在这里插入图片描述 上图显示了工程中自动生成了一些文件,单击左下角的绿色三角形图标,这个工程将进行编译、链接(编译链接的进度将被实时显示在右下角的方条中),然后运行。在屏幕上出现一个空白的窗口:

在这里插入图片描述 我们将对工程中的这些文件进行编辑,从而把窗口内容打磨成我们想要的样子。 所以,首先要认识一下工程中的这些文件:

一个工程文件:Notepad.pro

这个文件和工程为一些配置有关,在本文的开发过程中不会用到。我们将在打包发布的阶段对它进行必要的编辑。

一个主文件:main.cpp

这个文件和进行纯c/c++的代码编写时有所不同。为了削弱朋友们的陌生感,本文将逐行地介绍一下这个文件。但仅供了解,不必深究。

主c文件内容:

#include "notepad.h" #include int main(int argc, char *argv[]) { QApplication EditorApp(argc, argv); Notepad Editor; Editor.show(); return EditorApp.exec(); }

逐行解析:

最开始的两行用于引用notepad.h和QApplication这两个头文件。QApplication是Qt库的一个头文件,所有的Qt类都有对应的头文件。

#include "notepad.h" #include

这行是定义了主函数。和纯c/c++开发一样,使用Qt开发环境编写的整个程序也是从这个函数开始执行。

int main(int argc, char *argv[])

这一行使用主函数的参数,创建了一个EditorApp对象。这是Qt程序的主函数中的固定操作,不必细究。

QApplication EditorApp(argc, argv);

下面这行声明了一个在mainwindow.h和mainwindow.cpp中定义的那个Notepad类的对象Editor,我们编辑的主要对象。

Notepad Editor;

下面这行代码让我们编写的这个窗口显示在屏幕上。

Editor.show();

最后一句代码让程序进入Qt的事件循环,也就是窗口一直运行着,等待我们的各种操作,并根据我们在代码中的设定做出响应。

return EditorApp.exec();

逐行解析结束

一个后缀为ui的文件:mainwindow.ui

除了使用代码编辑,我们还可以通过这个文件对窗口的界面进行设计和改动。 而且借助开发环境中集成的Qt Designer,我们可以使用鼠标进行可视化编辑。双击这个ui文件即可打开Qt Designer界面,具体在第四部分熟悉Qt designer和窗体UI编辑方法中介绍。

三|了解Qt的混合开发模式

有的初学者认为应该使用纯代码编辑窗体,诚然,这是可以的,但确实不推荐。

因为窗体的大小通常可以变化,所以想要保持一定风格的界面,窗体上的按钮等控件的位置也就应该随着窗体的变化。这样就需要许多与界面相关的代码。

所以实际上,我们通常用Qt designer这个工具对窗体的界面进行可视化的编辑,代码部分只用来完成槽函数和对事件的响应。

这也就是所谓的Qt的混合开发模式。

四|熟悉Qt designer和窗体UI编辑方法

在这里插入图片描述 鼠标双击工程目录中的mainwindow.ui文件,Qt Creator会自动转到Qt designer,如下图所示: 在这里插入图片描述 中间白色背景区域就是窗体显示区域,灰色的方框就是窗体mainwindow,因为我们还没有为它添加控件,此时上面时空白的。

比较一|任务导向中的效果图,我们先准备在顶部给它加上一排工具栏。

1、在窗体上单击右键 2、在弹出的选项框中选择add toolbar(添加工具栏),单击左键

在这里插入图片描述 可以看到窗体顶部多了窄窄的一栏,右上角的元素框(上图右边那个红色圈中)中也显示出窗体上有一个名为toolbar的控件。这个名字是可以修改的,我们现在不管这些细节。

当然,这和我们想要的工具栏还是不同,现在我们让它看上去好一点,具体来说有两个步骤:

1、为工具栏添加一些action 2、为action设置图标,让它更好看一些

第二个步骤我们将在六|资源文件和自定义图标中说明,这一部分我们先考虑怎么让工具栏有一些像按键的东西,并且让这些“按键”被按下去后发生一些我们设想的事情。

为工具栏添加action (1)新建action 首先就是新建acition吧,怎么做? 在这里插入图片描述 单击Qt designer底部的新建action按钮(上图中圈中的位置),弹出一个窗口: 在这里插入图片描述 在Text一栏中填写New,然后单击OK按钮,新建一个名为New的action: 在这里插入图片描述

可以看到,action栏中已经显示出这个actionNew的属性。 (2)把action添加到工具栏中 这步很简单,直接用鼠标把action拖到工具栏中即可。 在这里插入图片描述 使用同样的步骤,再为工具栏添加Open、Save、Exit、Paste、Redo、Undo等action。完成后形如下图这样,这个图里的窗口有两个工具栏,你也可以只用一个: 在这里插入图片描述 上图白色框是一个textedit控件,添加方法就是在Qt designer左侧的控件列表中找到textedit,拖入窗体范围即可。

到这里我们就把单个窗体的界面做完了,接下来看mainwindow所谓代码部分: mainwindow.h:

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include namespace Ui { class Notepadx; } class Notepadx : public QMainWindow { Q_OBJECT public: explicit Notepadx(QWidget *parent = nullptr); ~Notepadx(); private slots: void newDocument(); void open(); void save(); void saveAs(); void print(); void exit(); void copy(); void cut(); void paste(); void undo(); void redo(); void selectFont(); void setFontBold(bool bold); void setFontUnderline(bool underline); void setFontItalic(bool italic); void about(); void on_actionNew_triggered(); void on_actionOpen_triggered(); private: Ui::Notepadx *ui; QString currentFile; }; #endif // mainwindow.h

mainwindow.cpp:

#include "notepadx.h" #include "ui_notepadx.h" #include #include #include #include #include Notepadx::Notepadx(QWidget *parent) : QMainWindow(parent), ui(new Ui::Notepadx) { ui->setupUi(this); this->setCentralWidget(ui->textEdit); connect(ui->actionNew, &QAction::triggered, this, &Notepadx::newDocument); connect(ui->actionOpen, &QAction::triggered, this, &Notepadx::open); connect(ui->actionSave, &QAction::triggered, this, &Notepadx::save); connect(ui->actionSave_as, &QAction::triggered, this, &Notepadx::saveAs); connect(ui->actionPrint, &QAction::triggered, this, &Notepadx::print); connect(ui->actionExit, &QAction::triggered, this, &Notepadx::exit); connect(ui->actionCopy, &QAction::triggered, this, &Notepadx::copy); connect(ui->actionCut, &QAction::triggered, this, &Notepadx::cut); connect(ui->actionPaste, &QAction::triggered, this, &Notepadx::paste); connect(ui->actionUndo, &QAction::triggered, this, &Notepadx::undo); connect(ui->actionRedo, &QAction::triggered, this, &Notepadx::redo); connect(ui->actionFont, &QAction::triggered, this, &Notepadx::selectFont); connect(ui->actionBold, &QAction::triggered, this, &Notepadx::setFontBold); connect(ui->actionUnderline, &QAction::triggered, this, &Notepadx::setFontUnderline); connect(ui->actionItalic, &QAction::triggered, this, &Notepadx::setFontItalic); connect(ui->actionAbout, &QAction::triggered, this, &Notepadx::about); // Disable menu actions for unavailable features #if !defined(QT_PRINTSUPPORT_LIB) || !QT_CONFIG(printer) ui->actionPrint->setEnabled(false); #endif #if !QT_CONFIG(clipboard) ui->actionCut->setEnabled(false); ui->actionCopy->setEnabled(false); ui->actionPaste->setEnabled(false); #endif } Notepadx::~Notepadx() { delete ui; } void Notepadx::newDocument() { currentFile.clear(); ui->textEdit->setText(QString()); } void Notepadx::open() { QString fileName = QFileDialog::getOpenFileName(this, "Open the file"); QFile file(fileName); currentFile = fileName; if (!file.open(QIODevice::ReadOnly | QFile::Text)) { QMessageBox::warning(this, "Warning", "Cannot open file: " + file.errorString()); return; } setWindowTitle(fileName); QTextStream in(&file); QString text = in.readAll(); ui->textEdit->setText(text); file.close(); } void Notepadx::save() { QString fileName; // If we don't have a filename from before, get one. if (currentFile.isEmpty()) { fileName = QFileDialog::getSaveFileName(this, "Save"); currentFile = fileName; } else { fileName = currentFile; } QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QFile::Text)) { QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString()); return; } setWindowTitle(fileName); QTextStream out(&file); QString text = ui->textEdit->toPlainText(); out QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString()); return; } currentFile = fileName; setWindowTitle(fileName); QTextStream out(&file); QString text = ui->textEdit->toPlainText(); out QCoreApplication::quit(); } void Notepadx::copy() { #if QT_CONFIG(clipboard) ui->textEdit->copy(); #endif } void Notepadx::cut() { #if QT_CONFIG(clipboard) ui->textEdit->cut(); #endif } void Notepadx::paste() { #if QT_CONFIG(clipboard) ui->textEdit->paste(); #endif } void Notepadx::undo() { ui->textEdit->undo(); } void Notepadx::redo() { ui->textEdit->redo(); } void Notepadx::selectFont() { bool fontSelected; QFont font = QFontDialog::getFont(&fontSelected, this); if (fontSelected) ui->textEdit->setFont(font); } void Notepadx::setFontBold(bool) { } void Notepadx::setFontUnderline(bool) { } void Notepadx::setFontItalic(bool) { } void Notepadx::about() { }

代码说明: 上面的代码说用的是c++风格,并且我们主要关注的是Qt的特性,故而对于那些成员函数(member functions)就不说明了。 这些函数对应着各action,当我们在窗体上单击某个action,对应的函数就会被调用。譬如,我们运行程序,在窗体上的任务栏中New这个action的位置单击鼠标,程序调用Notepadx::newDocument()这个函数。

读到这里,初学的朋友不禁要问,这些action和函数的关系是怎样确立的? 让我们把目光移到mainwindow.cpp中的这一部分:

connect(ui->actionNew, &QAction::triggered, this, &Notepadx::newDocument); connect(ui->actionOpen, &QAction::triggered, this, &Notepadx::open); connect(ui->actionSave, &QAction::triggered, this, &Notepadx::save); connect(ui->actionSave_as, &QAction::triggered, this, &Notepadx::saveAs); connect(ui->actionPrint, &QAction::triggered, this, &Notepadx::print); connect(ui->actionExit, &QAction::triggered, this, &Notepadx::exit); connect(ui->actionCopy, &QAction::triggered, this, &Notepadx::copy); connect(ui->actionCut, &QAction::triggered, this, &Notepadx::cut); connect(ui->actionPaste, &QAction::triggered, this, &Notepadx::paste); connect(ui->actionUndo, &QAction::triggered, this, &Notepadx::undo); connect(ui->actionRedo, &QAction::triggered, this, &Notepadx::redo); connect(ui->actionFont, &QAction::triggered, this, &Notepadx::selectFont); connect(ui->actionBold, &QAction::triggered, this, &Notepadx::setFontBold); connect(ui->actionUnderline, &QAction::triggered, this, &Notepadx::setFontUnderline); connect(ui->actionItalic, &QAction::triggered, this, &Notepadx::setFontItalic); connect(ui->actionAbout, &QAction::triggered, this, &Notepadx::about);

我们能够看到很多connect函数被调用。这就涉及到Qt的一个特质——信号(signal)和槽函数(slot)了,具体可参考我的这篇文章: Qt的信号和槽函数https://blog.csdn.net/qq_33904382/article/details/108785463

这里只需要知道:

connect(ui->actionNew, &QAction::triggered, this, &Notepadx::newDocument);

这个这条语句的意思是:

把actionNew这个action的 triggered("被单击"这个信号) 和 this(这个类(mainwindow))的 函数newDocument() 关联起来) 五|多窗体

初学的朋友先跳过这步,我以后再补充。

六|资源文件和自定义图标

我们在开发过程中可能会用到一些图片,或者程序运行过程中需要一些文件的支持,这些文件都可以放到工程目录下,方便打包的时候一并带上。 通常我们把这些文件叫做资源文件,Qt Creator提供了资源文件的管理工具。 在这里插入图片描述 要添加一个资源文件,在Qt Creator的工程目录中右键单击工程名,选择Add New,然后Qt->Qt Resource File->choose…: 在这里插入图片描述 然后填写Name栏->Next->Finish: 在这里插入图片描述

在这里插入图片描述 可以看到工程目录中已经有了src1这个资源文件: 在这里插入图片描述 单击add Prefix新建一个分支。 然后单击Add Files,把资源文件添加到这个分支下面: 在这里插入图片描述 在这里插入图片描述 然后保存工程中所有文件(每次修改资源文件都要保存一次资源文件(快捷键ctrl+s)。 这样,我们就可以引用这些资源文件为action设置图标了。

自定义图标 双击ui文件打开Qt designer,双击action编辑栏中的action(随便选一个你想编辑的action),本文选择Cut这个action,双击,然后看到这个界面: 在这里插入图片描述

图中标注的2和3是我们接下来要操作的地方:

2:单击下拉箭头,把normal off(从不显示图标)换成normal on(总是显示图标)。

单击3指示的地方,弹出一个列表框: 在这里插入图片描述 找到对应的资源文件夹,选择你想要的图标 补充说明一下:这里的图标用png的图片格式即可。缺少矢量图标资源的可以在这个网站逛一逛:https://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.5&type=1

这里我选择了剪刀这个图片当作为Cut这个action的图标: 在这里插入图片描述 单击OK,确认: 在这里插入图片描述 可以看到工具栏里的actioncut已经显示为图标啦。用同样的方法,可以为其他action也配置上图标。

七|打包工具和自定义exe图标

exe图标

在这里插入图片描述 在这里插入图片描述 exe图标,两种选择,【不管不顾】/【自己选个奈斯的图】 这个其实很简单,只需要把图标文件xxx.ico放到工程文件的目录(和主文件所在的那个文件夹)中: 在这里插入图片描述

然后再打开工程文件Notepad.pro,在最后一行添加语句:RC_ICONS = xxx.ico 比如我这里想把一个名为lb256的图标文件做exe的图标,就像下图这样在pro文件末尾补加一条:RC_ICONS = lb256.ico 在这里插入图片描述 需要注意的是,这里必须使用ico格式的文件做图标,如果你想把某张png/jpg格式的图片作为exe的图标,那就要借助一些转换工具。 幸运的是,Windows的应用商店里就有满足我们需求的应用,比如IconMaker.

打包

1.前提

强调:使用Qt自带的打包工具!选择与编译工具对应的打包工具!

否则在打包时大概率会遇到如下问题:

a.使用cmd进行打包,遇到报错:Warning: Cannot find Visual Studio installation directory, VCINSTALLDIR is not set.需要配置环境变量,但配置后也可能不行哈哈哈哈哈。 b.转用vs的开发者工具打包,遇到报错Warning: Cannot find GCC installation directory. g++.exe must be in the path.这个可能是因为使用了x86工具打包64位exe。 c.好不容易打包完成了,一运行就报错: 丢失libstdc+±6.dll、libgcc_s_dw2-1.dll、libwinpthread-1.dll的系统错误。 或者:应用程序无法正常启动(0xc000007b)

我为啥知道捏,因为我都遇到过哈哈哈哈

总而言之,使用这些方法打包不是遇到资源引用不畅,就是打包包含的dll不全。综上,建议各位读者朋友使用Qt自带的命令工具进行打包。

2.具体操作步骤 (1)准备工作 按release方式编译整个工程,把release目录下的可执行文件拷贝到一个空文件夹里面(这个文件夹用来为这个exe存放配套的动态库,以便exe能在其他机器上运行,也就是我们所说的打包里面的那个“包”)。 在这里插入图片描述

(2)选择打包工具 在这里插入图片描述 直接在全部程序/任务栏搜索框中搜索Qt,可以看到一系列的命令工具。 这里我们根据工程设置的编译工具,选择Qt5.9.9(MinGW 5.3.0 32-bit)这个命令工具。 (3)开始打包 运行Qt5.9.9 MinGW 5.3.0 32-bit.exe,切换到上一步把Notepad.exe放到的那个文件夹,命令形式是

cd 文件夹绝对路径

在这里插入图片描述

然后使用打包命令:

windepoyqt Notepad.exe

这条命令会把Notepad.exe运行时所需要的所有动态库拷贝到这个目录下,也就充实了我们的这个包。

上面两条命令及其效果都显示在下图中,供朋友们参考: 在这里插入图片描述 ok,打包完成了,把这个文件夹看成一个整体,拷贝到不同的机器上,我们的Notepad.exe都能运行,这就达到了打包的目的。

结语

至此,整个介绍就完结啦。 总的说来,初学Qt不必过分关注各种控件的操作方法,界面布局也是大致ok就行。重要的是这个工具库的特性,以及使用这个工具进行开发的并发布软件的流程。

本文以一个自定义Notepad开发为载体,介绍了使用Qt Creator这种IDE进行开发的流程。主要内容包含以下几方面:

1、Qt库几个特殊元素——信号、槽、事件及他们的设计和使用。 2、单窗体和多窗体设计 3、ui界面可视化编辑和窗体类代码编写的混合开发模式。 4、资源文件的添加和使用 6、在工程文件中编辑exe图标 7、使用Qt自带命令工具进行打包发布

祝各位后续的工作和学习顺利进行,对本文有意见和建议都可以在评论区提出。恭候各位的留言。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有