Qt创建项目及相关问题

news2024/9/20 1:03:46

文章目录

    • 1. Qt项目创建
    • 2. 认识项目代码
      • main.cpp
      • widget.h
      • widget.cpp
      • widget.ui
      • .pro
      • 构建过程生成的中间文件
    • 3. Hello World程序
      • 图形化方式创建
      • 代码方式创建
      • 内存泄漏问题
      • 编辑框方式创建
      • 按钮方式创建
    • 4. 对象树
      • 引入对象树原因
      • 对象树自动释放对象实验演示
    • 5. 乱码问题

1. Qt项目创建

模板介绍:

image-20240831133004387

选择路径:

路径不要带中文!!!

中文会影响项目构建

image-20240831203313317

构建系统:

通过Qt写的程序,设计一系列源编程技术,通过代码来生成代码

image-20240831133713415

qmake是Qt老牌的构建工具

CMake并非Qt专属,很多开源项目会采用CMake

Qbs是新一代的Qt构建工具,但实际用的人非常少,Qt官方没怎么维护了

Details

Qt Creator创建项目的时候,会自动生成代码,生成的代码,就包含一个类,此处选择自动生产的类的父类

image-20240831134657003

Widget就是自动生成的类名,QWidget是生成类继承的父类

Qt中内置的类,都是以Q为前缀开头的

这里生成的文件名和类名是关联的,虽然不是强制要求,但还是建议弄成一样的

image-20240831134832336

Qt中创建图形化界面程序的方式有2种:

  1. 直接通过C++代码创建
  2. 通过form file以图形化的方式生成界面

勾选生成form file文件,就可以用Qt Designer 或者Qt Creator来编辑这个ui文件了,从而以图形化的方式快速生成图形界面

选择翻译文件:

此时不关注,这个是和国际化相关的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

选择编译器的Qt SDK构建代码:

下载时只勾选了MinGW,就只有一个选项

image-20240831135948242

功能管理工具:

这里可选择是否加入到版本控制器里面,想加就加上即可

image-20240831140056575

2. 认识项目代码

main.cpp

C++的程序需要有main函数作为入口函数,此处的main函数是自动生成的。

image-20240831141609089

widget.h

这个文件里面就是Widget类的声明

image-20240831142717218

widget.cpp

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

widget.ui

双击这个ui文件,此时Qt Creator就会调用Qt Designer,打开ui文件,图形化界面编辑器

image-20240831143731220

再点击左侧的“编辑”按钮,此时显式的内容,就是ui文件本体了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个文件格式叫xml格式

xml格式这里的标签,有哪些标签,表示什么含义,是由程序员自己定义的

这里的标签具体含义,我们不需要太关注,只需知道ui文件本质上是xml即可

Qt中使用xml文件就是描述程序界面是什么样的,进一步的qmake会调用相关工具,依据这个xml文件生成一些C++代码,从而把界面完整构造出来

.pro

.pro文件是Qt项目的工程文件,也是qmake构建的重要依据

image-20240831144903798

qmake搭配.pro起到的作用和Linux当中的makefile作用类似,Qt Creator把这个过程都封装好了,不需要过多关注,只需点击安装按钮即可

构建过程生成的中间文件

运行程序一次之后,在项目目录并列的地方,会多出来一个目录,这个目录里面就是该项目运行过程中生成的一些临时文件

image-20240831150107767

image-20240831151020909

3. Hello World程序

有2种方式实现显式hello world

  1. 图形化的方式,在页面创建控件
  2. 纯代码方式创建

图形化方式创建

按照上面流程,重新创建一个名为HelloWorld的项目

image-20240831160714829

双击widget.ui,进入Designer

这里拖拽Label控件到显示页面,然后可以修改里面的内容

image-20240831161300217

点左下角运行之后,就显示出了一个hello world的页面

image-20240831161409843

这里main.cppwidget.h这些文件并不会发生变化,发生变化的是widget.ui

image-20240831161550582

查看中间文件里的ui_widget.h文件:

void setupUi(QWidget *Widget)
{
    if (Widget->objectName().isEmpty())
        Widget->setObjectName(QString::fromUtf8("Widget"));
    Widget->resize(800, 600);
    label = new QLabel(Widget);
    label->setObjectName(QString::fromUtf8("label"));
    label->setGeometry(QRect(340, 330, 161, 91));

    retranslateUi(Widget);

    QMetaObject::connectSlotsByName(Widget);
} // setupUi

这里就会多了一段创建label对象的代码

代码方式创建

再次创建一个工程,名为HelloWorld_2

通过代码创建界面的时候,一般会把构造函数界面代码放到Widget的构造函数当中

QLabel* label = new QLabel();

image-20240831162348746

这里报错,找不到QLabel的定义,这是因为没有包含这个类的头文件

Qt当中每个类都有一个对于的同名的头文件

Label是界面上显示内容的字符串控件

在创建对象的时候,可以通过new的方式在堆上创建,也可以直接在栈上,一般推荐在堆上创建的方式

这里建议在创建的时候,给构造添一个this参数,这表明给当前创建的对象,指定一个父对象

QLabel* label = new QLabel(this);

image-20240831163054718

然后再调用setText()方法往里面插入内容即可

void setText(const QString &);

这里参数类型是QString,这是因为Qt出的比C++早,早年间C++还没有自己的标准,Qt自己造了一套轮子,来支持Qt开发,里面包括但不限于:

Qstring
QVector
QList
QMap

之后C++标准出了,这些引入的Qt容器类,也没删,和现有的STL容器共存

可以显式写为:

label->setText(QString("hello world");

也可以直接写:

label->setText("hello world");

QString中提供了C风格字符串参数作为构造函数

不显式构造QString,C风格字符串也会隐式构造QString对象

image-20240831164302260

内存泄漏问题

这里new之后,并没有delete,在C++当中,内存泄漏是需要特别关注的事情

但是上面的代码,在Qt中不会引起内存泄漏,这是因为我们将其挂在了对象树上

编辑框方式创建

编辑框分为2种:

  1. 单行编辑框:QLineEdit
  2. 多行编辑框:QTextEdit

这里采用QLineEdit作为演示:

image-20240902201227172

运行之后,这个输入框也可以进行编辑:
image-20240902201308771

也可以采用代码的方式:

#include "widget.h"
#include "ui_widget.h"
#include<QLineEdit>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QLineEdit* edit = new QLineEdit(this);
    edit->text("hello world");
}

Widget::~Widget()
{
    delete ui;
}

按钮方式创建

这个按钮是可以点击的,这涉及Qt的信号槽机制

本质就是给按钮的点击操作,关联上一个处理函数,用户点击的时候,就会执行这个处理函数

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
 Q_OBJECT

public:
 Widget(QWidget *parent = nullptr);
 ~Widget();

 void handleClick();

private:
 Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QLineEdit>
Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
 ui->setupUi(this);

 //QLineEdit* edit = new QLineEdit(this);
 //edit->text("hello world");
 // 访问到form file(ui文件)创建的控件
 connect(ui->pushButton, &QPushButton::clicked, this, &Widget::handleClick);
}

Widget::~Widget()
{
 delete ui;
}

void Widget::handleClick()
{
 //点击之后,切换文本
 if(ui->pushButton->text() == QString("Hello World"))
 {
     ui->pushButton->setText("Hello Qt");
 }
 else
 {
     ui->pushButton->setText("Hello World");
 }

}

这个connectQObject这个类提供的静态函数,这个函数的作用就是连接信号和槽

  • ui->pushButton:访问form file(ui文件)中创建的控件

    image-20240902202628740

    这个值会自动生成,也可以手动修改,但是要求在界面中是唯一的

    qmake在处理ui文件的时候,就会根据这里的objectName生成对应的C++代码

  • &QPushButton::clicked:点击按钮pushButton的时候,就会触发信号

  • this:谁来处理这个信号

  • &Widget::handleClick:具体信号怎么处理

    GIF 2024-9-2 21-22-10

这里ui能够找到objectName这个属性,是因为qmake编译的时候会自动生成,objectName设置成什么值,变量名就叫什么:

image-20240902212643880

通过代码创建:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QPushButton>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void handleClick();

private:
    Ui::Widget *ui;
    QPushButton* myButton;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    myButton = new QPushButton(this);
    myButton->setText("hello world");

    connect(myButton, &QPushButton::clicked, this, &Widget::handleClick);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::handleClick()
{
    if(myButton->text() == QString("hello world"))
    {
        myButton->setText("hello qt");
    }
    else
    {
        myButton->setText("hello world");
    }
}

对于纯代码版本,按钮对象是自己new的,而且为了保证其他函数能够访问到这个变量,就需要把这个按钮对象设定为widget类的成员变量;

对于图形化,不需要自己newnew对象的操作被Qt自动生成了,而且这个按钮对象,已经作为ui对象里的成员变量了

4. 对象树

引入对象树原因

Qt中有一个对象树(N叉树),将界面的各种元素组织起来

image-20240831165141802

通过这个树形结构,就将这些控件对象组织起来了,最主要的目的就是为了能够在合适的时间,将这些对象统一释放

如何理解“合适的时间”?

当窗口关闭/销毁的时候,这写对象就会被统一消耗,如果某个对象提前销毁,就会导致控件在界面上不存在

这就是为什么要通过new的方式创建对象,将对象的生命周期交给Qt的对象树进行统一管理

image-20240831165734863

这里将对象在栈上创建,运行程序,hello world并没有显示,这是因为label对象随着构造函数的结束就销毁了

对象树自动释放对象实验演示

上面的QLabel是内置的一个对象,并不会显示输出析构信息。

我们可以自定义一个label类,然后显式输出析构信息

image-20240831200921782

mylabel.h

#ifndef MYLABEL_H
#define MYLABEL_H
#include<QLabel>

class MyLabel : public QLabel
{
public:
    MyLabel(QWidget* parent);	//引入父元素
    ~MyLabel();
};

#endif // MYLABEL_H

mylabel.cpp

#include "mylabel.h"
#include<iostream>
#include<qDebug>
MyLabel::MyLabel(QWidget* parent) : QLabel(parent)
{

}

MyLabel::~MyLabel()
{
    std::cout << "MyLabel 销毁" << std::endl;
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include"mylabel.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    MyLabel* label = new MyLabel(this);
    label->setText("hello world");
}

Widget::~Widget()
{
    delete ui;
}

运行之后发现,虽然没有手动delete,但是由于将MyLabel挂到了对象树当中,销毁窗口的时候,就会自动销毁对象树中的所以对象

这里有一点,虽然输出了析构信息,但是中文部分是乱码的

在这里插入图片描述

5. 乱码问题

乱码问题的原因,有且只有一个:编码方式不匹配

计算机中,一个汉族占几个字节?

回答这个问题,先得知道当前中文编码采用的字符集。

英文采用ASCII码表,而汉族的字符集,有很多种,最主流的是两种:

  1. GBK(中国大陆较多),使用2个字节表示一个汉字

    Windows简体中文版采用的就是默认GBK

  2. UTF-8/utf8,是一种边长编码,表示一个符合使用的字节数有变化,中文一般是3字节

查看编码网站:查看字符编码(UTF-8) (mytju.com)

我们查看当前文件的编码方式为utf8

image-20240831202513741

Qt Creator出现乱码,就表明终端并不是utf8方式编码,但是也不好修改文件和终端的编码方式

要解决这个乱码问题,可以使用Qt内置的qDebug工具,这可以很好的处理字符编码问题

image-20240831202735145

后续想在Qt中通过打印日志的方式输出调试信息,优先使用qDebug

qDebug可以通过编译开关,来实现一键式打开/关闭

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2108832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Databend 产品月报(2024年8月)

很高兴为您带来 Databend 2024 年 8 月的最新更新、新功能和改进&#xff01;我们希望这些增强功能对您有所帮助&#xff0c;并期待您的反馈。 Kafka Connect Sink Connector 插件 我们推出了一种将 Kafka 连接到 Databend 的新方式&#xff1a;databend-kafka-connect&#…

2023Idea版本无法下载通义灵码插件以及无法登录问题

进入下载插件处 在插件主页安装时&#xff0c;通常会根据当前自己访问的IDEA版本推荐合适的插件版本&#xff0c;所以最终会安装成功 idea中通义灵码插件无法登录问题

书客、松下、飞利浦护眼台灯怎么样?测评寻找护眼台灯天花板!

大家好&#xff0c;我是专注在护眼领域的一名评测师&#xff0c;长期以来&#xff0c;我致力于探索并体验各类能保护视力健康的护眼产品。今天&#xff0c;我来和大家分享我对护眼台灯的深入评测。护眼台灯作为日常学习生活的一部分&#xff0c;视觉体验的好坏往往取决于所选用…

Pygame中获取鼠标按键状态的方法

在《Pygame中获取鼠标位置的方法》中提到&#xff0c;可以通过鼠标事件和mouse模块中的函数获取鼠标位置&#xff0c;这两种方法同样适用于获取鼠标按键状态。 1 通过鼠标点击事件获取鼠标按键状态 通过鼠标点击事件获取鼠标按键状态的代码如图1所示。 图1 鼠标点击事件获取鼠…

HRGraph: 利用大型语言模型(LLMs)构建基于信息传播的HR数据知识图谱与职位推荐

知识图谱&#xff08;KGs&#xff09;作为语义网络&#xff0c;在管理不同领域复杂互联数据方面表现出极高的有效性&#xff0c;通过提供统一、上下文化和结构化的表示&#xff0c;具有灵活性&#xff0c;能够轻松适应不断发展的知识。在处理复杂的人力资源&#xff08;HR&…

RP2040 C SDK RTC功能使用

RP2040 C SDK RTC功能使用 &#x1f4cd;《RP2040 C SDK串口功能使用》&#x1f955;RP2040 RTC API官方文档说明&#xff1a;https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_rtc&#x1f955;官方例程参考&#xff1a;https://github.com/…

su root 提示 Permission denied

今天在某机器上新建了一个test账号&#xff0c;然后使用su root时&#xff0c;居然提示我没有权限&#xff0c;具体如下所示&#xff1a; [testlocalhost ~]$ su root Password: su: Permission denied [testlocalhost ~]$我确定密码是对的&#xff0c;试了好几次&#xff0c;…

彻底解决 node/npm, Electron下载失败相关问题, 从底层源码详解node electron 加速配置

最近玩了一下electron项目, 总是会遇到electron的下载失败问题, 于是看了一下node源码, 做一个记录. node/npm 加速配置 这个配置通过设置node配置里面的registry 这个配置项来完成加速. 配置方法 npm config set registry https://registry.npmmirror.com上面的命令就是将当…

day42-测试平台搭建之前端vue学习-基础1

一、Vue是什么 1.1.一套用于构建用户界面的渐进式JavaScript框架 1.2.渐进式 Vue可以自底向上逐层的应用 1).简单应用&#xff1a;只需一个轻量小巧的核心库 2).复杂应用&#xff1a;可以引ll入各式各样的Vue插件 二、Vue特点 2.1.采用组件化模式&#xff0c;提高代码复用率、…

翻译论文的关键部分 | Parallel Tiled QR Factorization for Multicore Architectures

SSRFB DTSQT2 DLARFB DGEQT2 1, 对角子矩阵分解 DGEQT2 这个例程被开发出来&#xff0c;用于针对对角Tile子矩阵&#xff1a; &#xff0c;执行不分块的QR分解。 这个运算产生&#xff1a; 一个上三角矩阵 一个酉下三角矩阵&#xff0c;这个矩阵包含 b 个 Householder 反光面…

跨平台打印模板转化pdf源码--SAAS本地化及未来之窗行业应用跨平台架构

一、跨平台打印转pdf渲染 pdf渲染模式可以支持国产化系统&#xff0c;和手机系统&#xff0c;安卓&#xff0c;苹果系统&#xff0c;qq浏览器&#xff0c;火狐&#xff0c;谷歌刘安祺 二、代码 /* ///cyberwin_offline_database_printtemp.js未来之窗打印模板解析技术 2024-…

maven的作用

一.什么是maven&#xff1f; maven是apache旗下的一个开源项目,是一款用于管理和构建java项目的工具。 关于Apache软件基金会,是目前世界最大的最受欢迎。 二.Maven的作用&#xff1f; 1.依赖管理 方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题。 配置文件(pom.x…

Android UID 和 userID 以及 appID

我们知道Android 操作系统是基于Linux内核的&#xff0c;所以Android 的UID 是基于 Linux UID的。 Linux UID Linux 本身就是一个多用户操作系统&#xff0c;每一个用户都会有一个UID&#xff0c;不同UID 之间的资源访问是受限的。 其中&#xff0c;Linux的DAC权限模型&#…

mysql笔记2(安装配置与连接)

文章目录 1. 社区版两种安装包2. mysql是一个典型的C/S架构的软件3. 编写mysql代码的三个位置① cmd② mysql软件客户端③ 第三方软件Hyper 4. 常见的关系型数据库① myql② sql server③ oracle 5. 连接mysql① 为什么要连&#xff1f;② cmd里怎么连&#xff1f; 6. 清屏与退…

直线上最多的点数

优质博文&#xff1a;IT-BLOG-CN 题目 给你一个数组points&#xff0c;其中points[i] [xi, yi]表示X-Y平面上的一个点。求最多有多少个点在同一条直线上。 示例 1&#xff1a; 输入&#xff1a;points [[1,1],[2,2],[3,3]] 输出&#xff1a;3 示例 2&#xff1a; 输入&am…

中间件解析漏洞(附环境搭建教程)

⼀&#xff1a;IIS解析漏洞 环境资源&#xff1a; https://download.csdn.net/download/Nai_zui_jiang/89717504 环境安装 windows2003iis6 1.创建新的虚拟机 2.在下⼀步中选择我们的iso⽂件镜像 vm已主动识别到windows2003 3.产品密钥⽹上搜⼀个 密码自己设置一个简单的&…

Depop被封如何恢复?如何申诉?可以解封吗?

Depop 是一个受欢迎的在线市场&#xff0c;帮助用户在全球范围内买卖服装、时尚物品和其他配饰。然而&#xff0c;与其他在线平台一样&#xff0c;Depop 有每个用户必须遵守的准则和规则&#xff0c;以确保市场安全公平。其中一条规则是&#xff0c;您不得拥有多个帐户&#xf…

Docker核心原理解读:深度剖析Docker Daemon,掌控容器背后的引擎

容器技术已经成为现代应用程序开发和部署中的核心工具&#xff0c;而在Docker生态系统中&#xff0c;Docker Daemon 扮演着至关重要的角色。它不仅是Docker架构的核心&#xff0c;还负责容器的管理、镜像的操作、资源的分配等复杂任务。本文将深入解读Docker Daemon的工作原理&…

【2024高教社杯全国大学生数学建模竞赛】ABCDEF题 问题分析、模型建立、参考文献及实现代码

【2024高教社杯全国大学生数学建模竞赛】ABCDEF题 问题分析、模型建立、参考文献及实现代码 1 比赛时间 北京时间&#xff1a;2024年9月5日 18:00-2024年9月8日20:00 2 思路内容 2.1 往届比赛资料 【2022高教社杯数学建模】C题&#xff1a;古代玻璃制品的成分分析与鉴别方案…

导入word模板的数据到DB,偏自学,可自改套用

GetMapping("/importTestPeople")public void importTestPeople(RequestParam("file") MultipartFile multipartFile) throws IOException {InputStream inputStream null;File file null;try {// 创建临时文件file File.createTempFile("temp&quo…