当前位置: 首页 > news >正文

文档测试发送

在上面的例子中MyClass 有一个名mySignal 的信号,它带有一个整型参数

定义槽:槽可以是任何普通的成员函数,但通常在类定义中用slots 关键字标识。槽可以有返回类型,也可以接受参数,但它们的参数类型需要与发出信号的参数类型匹配。例如:

在这个例子中,我们定义了一个名mySlot 的槽,它接收一个整型参数

连接信号与槽:使用QObject::connect 函数将信号与槽连接起来。当信号被发射时,连接到这个信号的槽将被调用。

这行代码连接myObject mySignal 信号到同一个对象mySlot 

发射信号:使emit 关键字发射信号。当信号被发射时,所有连接到这个信号的槽都会被调用

这将触发所有连接mySignal 的槽

自定义信号和槽是Qt编程中非常强大的特性,它们使得组件之间的通信变得灵活而松耦合。通过信和槽,可以方便地实现各种复杂的事件驱动逻//辑。

QDebug()

Qt 框架中用于输出调试信息的一个类。它提供了一种方便的方式来输出文本到标准输出(通常是控制台),这对于调试 Qt 应用程序非常有用。 QDebug 类可以与 Qt 的信号和槽机制一起使用,使得在响应各种事件时能够输出有用的调试信息。

使用 的一个典型方式是通过作符 来输出各种数据类型。例如

函数,它返回一

对象。然后,可以使用流

当执行这些代码时,它们会在应用程序的控制台输出相应的文本。这对于检查程序的运行状态、变量的值或者跟踪程序的执行流程非常有帮助。

还可以使用  qDebug() 来输出自定义类型,只要为这些类型提供了适当的输出操作符重载。此外,Qt 

提供了 qInfo() , qWarning() , 函数,用于输出不同级别的信息,分别

于普通信息、警告、关键错误和致命错误。这有助于对日志信息进行级别划分,从而更好地控制输出内容。

    1. 文件操作类 QFile

Qt 框架中用于文件处理的一个类。它提供了读取和写入文件的功能,支持文本和二进制

继承自 QIODevice ,因此它可以像其他IO设备一样使用

主要功
  1. 文件读写QFile 支持打开文件进行读取或写入操
  2. 文件信息:可以检索有关文件的信息,如大小、修改日期等
  3. 文件操作:提供了对文件进行重命名、移动、删除等操作的能力
  4. 错误处理QFile 在操作文件时提供了错误处理机制,可以通过相应的函数检查和获取错误信息
常用方

open() :打开一个文件。需要指定模式(如只读、只写、读写等)

close() :关闭文件

 write() :用于读取和写入数据

exists() :检查文件是否存在

remove() :删除文件

copy() :复制文件

示例代

以下是使 的一个简单例子

Widget::Widget(QWidget *parent)

: QWidget(parent)

, ui(new Ui::Widget)

{

ui->setupUi(this);

}

Widget::~Widget()

{

delete ui;

}

void Widget::on_btnRead_clicked()

{

//1. 打开文

//QFile file("D:/QT/test.txt"); QFile file; file.setFileName("D:/QT/test.txt");

if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug() << "file open error";

}

//2. 读取文

char context[100] = {'\0'};

if( file.read(context,100) == -1) return;

//3. 输出文件内容 qDebug() << context; file.close();

}

void Widget::on_btnWrite_clicked()

{

// 1.

QFile file("D:/QT/test2.txt"); file.open(QIODevice::WriteOnly | QIODevice::Text);

// 2. 

file.write("Program 45-QFile001 write something to This File 我是老陈");

// 3. 

file.close();

}

3.3.3 QTextStream

的主要特性成一个表格。请看下表

特性类

字符编

支持 Unicode,可以处理如 UTF-8UTF-16 等不同编码。通过 setCodec() 方法设置特定编码。

读写文

用于读写文件、字符串或任何继承自 QIODevice 的对象

格式

提供文本格式化功能,如数字精度、基数(十进制、十六进制等)调整

流操作

支持使用 <<  >> 操作符,类似于 C++ 中的 iostream

特性类

换行处

自动处理不同操作系统间的换行符差异(如 Unix \n Windows \r\n 

错误处

能够检测和报告在读写过程中出现的错误

缓冲机

提供缓冲机制,提高读写效率

字符串操

可以方便地处理和解析字符串数据

是一个功能强大的类,用于处理文本数据,特别是在需要考虑字符编码和文本格式化的情况下。通过这些特性,它提供了一种灵活而强大的方式来读写和操作文本。

使用示

以下是一个更详细的示例,展示了如何使 来读写文件

    1. 文件选择对话框 QFileDialog
      1. QFileDialog开发流程

使 的基本步骤通常如下

实例化:首先,创建一 对象的实例

设置模式:根据需要设置对话框的模式,如打开文件、保存文件等

设置过滤器:如果需要,可以设置文件类型过滤器,以限制用户可以选择的文件类型

显示对话框:通过调 方法显示对话框,并在用户作出选择后执行相应的操作

这是使

方法获取用户选择的文件路径列表,然后对这些文件进行相应的处理

的基本模式。Qt  也允许使用静态方法直接创建和显示对话框,例

QFileDialog::getOpenFileName() ,这些方法更简单,但提供的自定义选项较少

      1. QFileDialog 打开开发案例

      1. QFileDialog 保存开发案例

    1. 实现文件打开功
      1. 开发流程

QPushButton对应Open的控件设置槽函数槽函数代码开发

打开文

读取文

把文件数据显示在TextEdit控件

      1. 代码实现

      1. 打开功能优化

字符编码相关问题解

Qt QTextStream 常用的字符编码主要包括以下几种

编码名

UTF-8

用于表示 Unicode 文本的变长字符编码,广泛用于网络和多语言文

UTF-16

用于表示 Unicode 文本的定长字符编

ISO 8859-1

也称为 Latin1,用于表示西欧语言字

GBK

用于表示简体中文字符,是 GB2312 的扩

Big5

用于表示繁体中文字符,常用于台湾和香港地

Windows- 1252

用于表示西欧语言字符,是 ISO 8859-1 的超

ANSI

 Qt 中,"ANSI" 编码并不是一个明确指定的编码标准,因为 ANSI 编码可以指代不同的编码标准,这取决于操作系统的语言和区域设置。例如,在中文 Windows系统中,ANSI 编码通常指的是 GBK 编码;而在西欧语言的 Windows 系统中, ANSI 编码可能指的是 ISO 8859-1  Windows-1252

这些编码覆盖了大部分常用的语言字符集,可以通过中进行设置。

方法

检测光标位置,并在右下角显示光标位置在程序左上方显示当前打开的文件名称

      1. QComboBox

Qt 框架中用于创建下拉列表的一个控件

它允许用户从一组选项中选择一个选项,并可以配置为可编辑,使用户能够在其中输入文本

提供了一系列方法来添加、删除和修改列表中的项,支持通过索引或文本检索项,并可以通过信号和槽机制来响应用户的选择变化。该

控件广泛应用于需要从多个选项中进行选择的用户界面场景,例如表单和设置界面

API 

添加选

向下拉列表添加单个或多个选

addItem() , addItems()

获取选

获取当前选中的文本或索

currentText() , currentIndex()

设置选

设置当前选中的

setCurrentIndex(int)

移除选

从下拉列表中移除

removeItem(int)

当选项改变时触发的事

currentIndexChanged(int)

可编辑

设置下拉列表是否可编

setEditable(bool)

自定义数

向下拉列表项关联额外的数

setItemData(int, const QVariant&)

清空列

移除所有选

clear()

示例代

这个示例展示

需要调整和扩展这个示例

的基本用法,包括添加选项、设置为可编辑以及连接信号和槽。您可以根

      1. 记事本支持字符编码

获取用户在QComboBox上选择的字符编码,用特定编码打开文件,这里注意QComboBox返回QString类型,

setCodec参数要求const char*

QString先转成C++String,再转换成const char *

支持打开文件后进行字符编码的重新选择和显示加

      1. 添加行列显示

使用QTextEditcursorPositionChanged信号,当光标发生移动时候刷新显

      1. 添加文件打开提示

      1. 设置当前行高亮

实现策略

获取当前行的光标位置,使用的信号和获取行列值是一样的通过ExtraSelection来配置相关属性

在当前行设置该属

实现该功能,需要用到一个API

        1. QList

Qt 框架中QList 是一个容器类,它在内部实现上类似于一个数组,但也提供了一些链表的特性。的设计旨在提供一个在多数情况下既高效又方便的通用列表容器。用于存储元素列表。它提供

丰富的功能,包括添加、移除、访问元素等

QList 的内部工作原理

          1. 数组式存储QList 在大多数情况下使用连续内存存储其元素,类似于数组。这意味着它提供了快速的索引访问(通过下标操作符 [] ),以及相对高效的迭代性能。
          2. 动态调整大小:与静态数组不同QList 可以动态增长和缩减,自动管理内存分配
          3. 链表特性:虽 主要基于数组,但它也提供了一些链表的操作,比如在列表的开始或结

处添加和移除元素。这些操作通常比在数组中间插入或删除元素更高效

          1. 复制时共享内存QList  使用一种称为隐式共享implicit sharing)或写时复制copy-on-

write)的技术。这意味着当你复制一 时,它不会立即复制所有元素,而是共享相同的

据,直到你尝试修改其中一个列表,此时才进行实际的复制。这使得复

使用场景

变得非常高效

当你需要快速的随机访问(如通过索引访问元素)时, QList 是一个不错的选择。如果你的主要操作是在列表的两端添加或移除元素, QList 也表现得很好。

基本用

包含头文件:首先,你需要包 的头文件

创建 QList 实例:创建一 对象,并指定存储的元素类型

添加元素:使 方法添加元素

访问元素:可以使用下标操作符 方法访问元素

遍历列表:使用迭代器或范围基的 for 循环遍历列表

移除元素:使用 removeAt  removeOne  方法移除元素

3.8.2 ExtraSelection 

是一个

中用来表示额外的文本选择和高亮的结构

如何工
  1. ExtraSelection 结构体QTextEdit::ExtraSelection 是一个结构体,包含了两个主要成员:QTextCharFormat QTextCursor 表示在文本中的一个位置或者区间,而

用于定义这个区间的格式,比如背景颜色、字体等

  1. 设置  ExtraSelection:你可以创建一个或多 对象,为它们设置相应的光标

置和格式,然后通 方法将这些对象应用到文本编辑器中

这样,你可以对文本的特定部分应用特定的格式,而不影响其他文本

  1. 高亮当前行:要高亮显示当前行,你需要

信号的槽函数中创建一

对象。使用当前

对象(通

方法获取)来

定当前行的位置,并设置背景颜色为你选择的高亮颜色

类是 Qt 框架中的一部分,用于描述文本字符的格式。这个类提供了丰富的接口来设置和获取文本字符的各种属性,如字体、颜色、背景色等。 QTextCharFormat 通常用于富文本处理,可

以在

下面列出

这样的类中使

的一些常用功能和方法

  1. 设置和获取字体样式

使

方法设置字体

方法获取当前字体

  1. 设置字体属性

setFontWeight() : 设置字体的粗细。 setFontItalic() : 设置字体是否倾斜。 setFontUnderline() : 设置是否有下划线。

  1. 设置文本颜色和背景色

setForeground() : 设置文本的前景色(即字体颜色)

setBackground() : 设置文本的背景色

  1. 其他文本属性

setToolTip() : 设置文本的工具提示。 setAnchor() : 设置文本是否为超链接。 setAnchorHref() : 设置超链接的目标 URL

示例代

下面是一个简单的示例,展示如何

中使

来设置特定文本的格式

    1. 文件保存功能优
      1. 开发流程

判断当下是否有已经打开的文件,如果有打开的文件读取TextEdit的内容

写入新文

    1. 关闭优

在上节课中关闭部分稍微优化了以下,但是还是不够,  我们应该弹出窗口多一个询问

      1. 消息对话框 QMessageBox

Qt 框架中用于显示消息框的一个类,它常用于向用户显示信息、询问问题或者报告

误。以下 的一些主要用途

  1. 显示信息:向用户显示一些信息性的消息
  2. 询问用户决策:询问用户一个问题,并根据其回答做出相应的操作
  3. 报告错误:向用户报告程序运行中的错误。代码示例

以下是一个简单 使用示例,展示了如何创建一个基本的消息框

在这个例子中,我们创建了一 对象,并设置了窗口标题、主要文本、附加信息文本

图标。还添加了两个按钮(OK Cancel),并设置了默认按钮。通

据用户的选择执行不同的操作

方法显示消息框,并

是为标准对话框设计的,其定制能力有限,但你可以通过添加自定义按钮来实现

定程度的定制。例如,如果你想要添加一个自定义的按钮,可以这样做

在这个例子中,通 方法添加了一个自定义按钮。按钮的角色被设置

QMessageBox::ActionRole ,这意味着它将被放置在对话框的底部,与其他标准按钮一起。通过检查用户点击的按钮来确定是否点击了自定义按钮。

3.7.3 代码实现

    1. 实现快捷键功
      1. 快捷键开发基础

Qt 中实现快捷键功能通常涉及

Qt 应用程序中为特定功能设置快捷键

类的使用。下面是一个简单的代码示例,展示了如何

在这个示例中,当用户按下 Ctrl + N 时,程序将弹出一个消息框。这是通过创建一 对象

并将其快捷键序列设置

来实现的。然后,

信号连接到一个 Lambda 函数

该函数在快捷键被激活时执行。这种方法非常适用于为特定操作提供快速访问路径

      1. 上官记事本添加快捷键

    1. 实现字体放大缩小功
      1. 滚动调节字体大小的流程

TextEdit添加事件过滤器重写窗口的eventFilter函数

eventFilter设置滚轮事件和目标对象实现字体放大缩小的功能函数

      1. 本节笔记失误

啥也没有,嘿嘿

      1. 检测Ctrl键被按下

(如 CtrlShiftAlt 等)。当与了 Control 键。

 Qt 中一个静态函数,用于返回当前按下的键盘修饰符结合使用时,这个函数可以用来检测是否按下

例如,以下代码片段检查 Control 键是否被按下

这里QGuiApplication::keyboardModifiers() 返回当前按下的修饰符,

前按下的修饰符中

是一个枚举值,表示 Control 键。使用位与运算

检查 Control 键是否在

      1. 记事本添加字体放大缩小

      1. 事件
事件处理过

众所周知Qt是一个基于C++的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高的)。所以在Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会经过: 事件派发 -> 事件过滤->事件分发->事件处理 几个阶段。Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作,比如信号与槽就是一种

事件(event)是由系统或者 Qt 本身在不同的场景下发出的。当用户按下/移动鼠标、敲下键盘,或者是窗口关闭/大小发生变化/隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如鼠标/键盘事件等;另一些事件则是由系统自动发出,如计时器事件。

每一个Qt应用程序都对应一个唯一的 QApplication 应用程序对象,然后调用这个对象exec() 数,这样Qt框架内部的事件检测就开始了( 程序将进入事件循环来监听应用程序的事件 )。

事件在Qt中产生之后,的分发过程是这样的

  1. 当事件产生之后,Qt使用用应用程序对象调用 notify() 函数将事件发送到指定的窗口

  1. 事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤

  1. 当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类:

  1. 事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件。。。)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函 数),比如:鼠标事件:

重写事件案

程序关闭之前的询问,鼠标进入,鼠标离开,窗口大小改

#include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QMessageBox> #include <QWheelEvent>

Widget::Widget(QWidget *parent)

: QWidget(parent)

, ui(new Ui::Widget)

{

ui->setupUi(this);

}

Widget::~Widget()

{

delete ui;

}

void Widget::enterEvent(QEvent *event)

{

qDebug() << "mouse enter";

}

void Widget::leaveEvent(QEvent *event)

{

qDebug() << "mouse leave";

}

void Widget::wheelEvent(QWheelEvent *event)

{

qDebug() << event->angleDelta();

}

void Widget::closeEvent(QCloseEvent *event)

{

int ret = QMessageBox::warning(this, tr("My Application"),

tr("close the window\n"

"Do you want to close the window?"), QMessageBox::Ok | QMessageBox::No

);

switch(ret){

case QMessageBox::Ok: event->accept(); break;

case QMessageBox::No: event->ignore(); break;

}

}

void Widget::resizeEvent(QResizeEvent *event)

{

qDebug() << "oldSize:" << event->oldSize()

<< "newSize:" << event->size();

自定义按

mybutton.h

mybutton.cpp

widget.cpp

事件方式实现字体放大缩

自定义控件MyTextEdit头文件

实现文

事件过滤

我们通过继承QTextEdit来重写事件实现Ctrl加滚轮的检测,还有一种处理方式,叫做事件过滤

Qt的事件处理过程中,引入事件过滤器(Event Filter可以让你在事件达到目标对象之前进行拦截和处理。这是一种强大的机制,允许你在不同对象间共享事件处理逻辑或在父对象中集中处理特定事件。下面是加入事件过滤器的步骤:

  1. 定义事件过滤器: 事件过滤器通常是一个重写QObject::eventFilter() 方法的对象。这个方法会在事件传递给目标对象之前被调用。
  2. 安装事件过滤器: 使用QObject::installEventFilter() 方法安装事件过滤器。这个方法告诉Qt在将事件发送给特定对象之前先通过过滤器对象。例如,如果你想在父窗口中过滤子窗口的事件,你需要在父窗口的对象上调用installEventFilter() ,并将子窗口作为参数传递。
  3. 事件过滤器逻辑: eventFilter() 方法内部,你可以编写自定义逻辑来决定如何处理或忽略事件。如果此方法返回true ,则表示事件已被处理,不应该继续传递;如果返回false ,则事件将正常传递给目标对象。
  4. 事件分发:  当事件发生时,Qt首先将事件发送到安装了事件过滤器的对象。在这一步

eventFilter() 方法被调用

  1. 决定是否传递事件: 根据eventFilter() 方法的返回值,Qt决定是否继续向目标对象传递事件。如果过滤器返true ,事件处理到此结束;如果返false ,事件继续传递到原始目标对象。
  2. 目标对象处理事件: 如果事件过滤器允许事件继续传递,目标对象将像没有事件过滤器存在时那样处理事件。

事件过滤器特别适用于以下情况

当你想在不修改子类代码的情况下改变事件的行为。当多个对象需要共享相同的事件处理逻辑。

当你需要在更高的层级上监控或修改应用程序的事件流

通过使用事件过滤器,Qt应用程序可以获得更大的灵活性和更细粒度的事件处理控制

      1. 鼠标滚轮和字体大小

C++ 中,强制类型转换(或类型转换)是一种将变量从一种类型转换为另一种类型的方法。C++ 提供了四种强制转换运算符,每种都有其特定的用途和适用场景:

  1. static_cast

是最常用的类型转换运算符,用于无风险的转换,如整数到浮点数,字符到

数等

它在编译时执行,不执行运行时类型检查(RTTI

示例int x = static_cast<int>(y); 其中

  1. dynamic_cast

可能是 float 类型

专门用于处理对象的多态性,只能用于指针和引用,且涉及对象类必须有虚函数

它在运行时检查类型的安全性,如果转换失败,对于指针类型返回 nullptr ,对于引用类型抛出异常。

示例Derived *dp = dynamic_cast<Derived *>(bp); 其中是派生类。

  1. const_cast

用于修改类型的 const volatile 属性

是基类指针Derived

通常用于去除对象的 const 性质,允许修改原本被声明为 const 的变量。示例const int a = 10; int* b = const_cast<int*>(&a);

  1. reinterpret_cast

用于进行低级别的重新解释转换,几乎无限制,但也是最危险的

它可以将一种完全不相关的类型转换为另一种类型,比如将指针类型转换为整数类型

示例: long p = reinterpret_cast<long>(&object);  是某个类的对象

3.12 记事本项目总结

UI设计师基本控件操

Widget

基础的用户界面单元,用于构建复杂的用户界面。

QPushButton

用于创建按钮

QHBoxLayout

水平布局管理器,用于水平排列控件

QVBoxLayout

垂直布局管理器,用于垂直排列控件

TextEdit

多行文本编辑器控件

Stylesheet

使用样式表来定制控件的外观

文件操作

QFile

用于读取和写入文件

文件选择对话框

QFileDialog

提供了一个对话框,允许用户选择文件或目录

QT的信号与

-

用于对象之间的通信机制

消息对话

QMessageBox

用于显示信息、警告、错误等对话框

快捷键捕获和处

-

用于捕获和处理键盘快捷键

Ctrl按键信号捕获和处

-

专门处理Ctrl按键的信号

鼠标滚轮信号捕获和处

-

用于捕获和处理鼠标滚轮动作

事件处

event

用于处理不同的事件

文本字符编码检

-

用于检测和处理文本的字符编码

字体放大缩

-

用于调整字体大小

QT程序开发流

-

涉及从设计到部署的整个开发流程

P4 串口调试助手项

    1. 项目概
项目功能描

见下方界面,所见即所得

    1. 串口通信核心代码开

代码会放在网盘

全程高能力输出-代码开发和调试都在视频

P5 网络调试助

    1. TCP网络调试助
      1. 项目概述

网络相关的一些基础概念-面试用学习QTcpServer

学习QTcpClient

学习TextEdit特定位置输入文字颜色学习网络通信相关知识点

复习巩固之前 UI 控件 程序运行如下图所

      1. 开发流程

      1. QTtcp服务器的关键流程

工程建立,需要在.pro加入网络权

创建一个基

        1. 创建并初始

的服务端涉及以下关键步骤

实例

实例化 QTcpServer 

        1. 处理新连接

方法在特定端口监听传入的连接

信号连接一个槽函数

在槽函数中,使

        1. 读取和发送数据

以与客户端通信

通过连接使用

        1. 关闭连接

方法发送数据回客户端

信号来读取来自客户端的数据

在适当的时候关闭 QTcpSocket 示例代码可能如下:

确保在使 时妥善处理网络错误和异常情况

      1. QTtcp客户端的关键流程

工程建立,需要在.pro加入网络权

创建一个基

Qt客户端涉及以下步骤

实例

实例化 QTcpSocket 

        1. 连接到服务器

使

        1. 发送数据到服务器

方法连接到服务器的IP地址和端口

使 方法发送数据

        1. 接收来自服务器的数据

        1. 关闭连接

信号连接一个槽函数来接收数据

关闭示例代码如下

连接

这个客户端尝试连接到指定的服务器地址和端口,然后等待和处理来自服务器的数据。记得根据需要管理和处理网络错误和异常情况。

5.1.2 TCP

以下内容自省阅读和消化,主要在面试之前类似八股文问答,实际编程我们不需要关系这么多

QTcpSocket类底下的API已经做好所有的封装

TCP(传输控制协议)是一种广泛使用的网络通信协议,设计用于在网络中的计算机之间可靠地传输数据。它是互联网协议套件的核心部分,通常与IP(互联网协议)一起使用,合称为TCP/IP。以下是TCP议的一些基本特点:

  1. 面向连接:在数据传输之前,TCP 需要在发送方和接收方之间建立一个连接。这包括三次握手过程,确保两端都准备好进行数据传输。
  2. 可靠传输TCP 提供可靠的数据传输服务,这意味着它保证数据包准确无误地到达目的地。如果发生数据丢失或错误,TCP 会重新发送数据包。
  3. 顺序控制TCP 保证数据包的传输顺序。即使数据包在网络中的传输顺序被打乱,接收方也能按照正确的顺序重组这些数据。
  4. 流量控制TCP 使用窗口机制来控制发送方的数据传输速率,以防止网络过载。这有助于防止接收方被发送方发送的数据所淹没。
  5. 拥塞控制TCP 还包括拥塞控制机制,用来检测并防止网络拥塞。当网络拥塞发生时,TCP 会减少其数据传输速率。
  6. 数据分段:大块的数据在发送前会被分割成更小的段,以便于传输。这些段会被独立发送并在接收端重新组装。
  7. 确认和重传:接收方对成功接收的数据包发送确认(ACK信号。如果发送方没有收到确认,它会重传丢失的数据包。
  8. 终止连接:数据传输完成后,TCP 连接需要被正常关闭,这通常涉及到四次挥手过程

TCP 适用于需要高可靠性的应用,如网页浏览、文件传输、电子邮件等。然而,由于它的这些特性,TCP在处理速度上可能不如其他协议(如UDP)那么快速。

TCP协议中的三次握手和四次挥手是建立和终止连接的重要过程。下面是它们的简要描述

三次握手(建立连接

三次握手的主要目的是在两台设备之间建立一个可靠的连接。它包括以下步骤

  1. SYN:客户端向服务器发送一个SYN(同步序列编号)报文来开始一个新的连接。此时,客户端进SYN-SENT状态。
  2. SYN-ACK:服务器接收到SYN报文后,回复一个SYN-ACK(同步和确认)报文。此时服务器进

SYN-RECEIVED状态

  1. ACK:客户端接收到SYN-ACK后,发送一个ACK(确认)报文作为回应,并进入ESTABLISHED建立)状态。服务器在收到这个ACK报文后,也进入ESTABLISHED状态。这标志着连接已经建立。

四次挥手(断开连接

四次挥手的目的是终止已经建立的连接。这个过程包括以下步骤

  1. FIN:当通信的一方完成数据发送任务后,它会发送一个FIN(结束)报文来关闭连接。发送完FIN

报文后,该方进入FIN-WAIT-1状态

  1. ACK:另一方接收到FIN报文后,发送一个ACK报文作为回应,并进入CLOSE-WAIT状态。发送FIN

报文的一方在收到ACK后,进入FIN-WAIT-2状态

  1. FIN:在等待一段时间并完成所有数据的发送后,CLOSE-WAIT状态的一方也发送一个FIN报文来请求关闭连接。
  2. ACK:最初发送FIN报文的一方在收到这个FIN报文后,发送一个ACK报文作为最后的确认,并进

TIME-WAIT状态。经过一段时间后,确保对方接收到了最后的ACK报文,该方最终关闭连接

在这两个过程中,三次握手主要确保双方都准备好进行通信,而四次挥手则确保双方都已经完成通信并同意关闭连接。

5.1.4 Socket

Socket 不是一个协议,而是一种编程接口(API)或机制,用于在网络中实现通信。Socket 通常在应用层和传输层之间提供一个端点,使得应用程序可以通过网络发送和接收数据。它支持多种协议,主要是 TCP UDP

以下是 Socket 的一些基本特点

类型:有两种主要类型的 Sockets —— TCP Socket(面向连接,可靠)和 UDP Socket(无连接,不可靠)。

应用:在各种网络应用中广泛使用,如网页服务器、聊天应用、在线游戏等

编程语言支持:大多数现代编程语言如 Python, Java, C++, 等都提供 Socket 编程的支持

功能:提供了创建网络连接、监听传入的连接、发送和接收数据等功能

QT: QT组件中,QTcpSocket用来管理和实现TCP Socket通信,QUdpSocket用来管理和实现 UDP Socket通信

总之,Socket 是实现网络通信的基础工具之一,它抽象化了网络层的复杂性,为开发者提供了一种相对简单的方式来建立和管理网络连接。

    1. UI

UI设计过程,教学视频展示,都是大家熟悉的内容

    1. 网络通信核心代

Qt 网络模块的一部分,用于构建 TCP 服务器。它提供了一种机制来异步监听来自客户端的连接。一旦接受了一个连接,服务器就可以与客户端进行数据交换。

      1. 创建TCP服务端的核心代

主要步骤如下

        1. 实例:启动服务器并开始监听指定端口
        2. 监听连接请求:调 方法使服务器监听特定的 IP 地址和端口
        3. 接受连接:当客户端尝试连接时QTcpServer 产生一个信号。你需要实现一个槽(slot)来响应这个信号,并接受连接。

        1. 处理客户端连接:每个连接的客户端都关联一个示例代码

对象,用于数据交换

代码解

  1. 监听端口:使

对象:在主函数中,直接创建了一

方法监听所有接口上的 12345 端口

对象

  1. 处理新连接:通过连 信号,当有新客户端连接时,会调用相应的槽函数

  1. 读取数据:为每个连接的客户端创
  2. 发送数据:向客户端发送响应消息

对象,并连

信号以接收数据

  1. 客户端断开连接时的处理:使

这个代码示例展示了如何使

信号确保客户端在断开连接时被适当地清理

创建一个基本的 TCP 服务器,而无需通过继承来扩展类。

种方式通常更简单,适用于不需要复杂处理的基本应用场景

      1. 创建TCP客户端的核心代

为了使客户端代码更具模块化和响应性,可以使用 Qt 的信号与槽机制。这种方法允许客户端以事件驱动的方式响应网络事件,如连接建立、数据接收等。下面是一个使用信号与槽的 TCP 客户端示例。

示例代

代码解

:这个类继承自 QObject ,允许使用信号与槽机制

        1. 连接信号和槽:在构造函数中, 信号分别连接

        1. 连接到服务器:使

方法开始连接过程

        1. 处理连接建立:一旦连接建立onConnected 槽被触发,客户端向服务器发送一条消息
        2. 接收数据:当数据可读时onReadyRead 槽被触发,客户端读取并打印来自服务器的数据
        3. 断开连接:在接收数据后,客户端断开与服务器的连接

这个客户端示例展示了如何使用 Qt 的信号与槽机制来处理 TCP 连接。这种方式使得代码更加清晰,易于维护,并且能更好地处理异步事件。

    1. TCP服务端项目开

核心代

for (const QNetworkInterface &interface : interfaces) {

for (const QNetworkAddressEntry &entry : interface.addressEntries()) { if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {

ui->comboBoxIpAddr->addItem(entry.ip().toString());

}

}

}

}

// 主窗口析构函

MainWindow::~MainWindow()

{

// 释放用户界面资

delete ui;

}

// 开始监听按钮的点击事件处理函

void MainWindow::on_pushButtonListen_clicked()

{

// 侦听指定 IP 地址和端

tcpServer->listen(QHostAddress(ui->comboBoxIpAddr->currentText()), ui->lineEditPort->text().toInt());

// 更新按钮状

ui->pushButtonListen->setEnabled(false); ui->pushButtonListenStop->setEnabled(true);

}

// TCP 连接的处理函

void MainWindow::mnewConnectionHandler()

{

// 获取下一个待处理的连

QTcpSocket *tmpSocket = tcpServer->nextPendingConnection();

// 向文本浏览器中添加客户端信

ui->textBrowserRev->append("服务器: 客户端IP地址是:"+ tmpSocket-

>peerAddress().toString()

+" 客户端端口号是"+QString::number(tmpSocket-

>peerPort())+"\n");

// 连接套接字的状态变化和数据接收信号到相应槽函

connect(tmpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(mstateChanged(QAbstractSocket::SocketState)));

connect(tmpSocket, SIGNAL(readyRead()), this, SLOT(mreadData()));

}

// 套接字状态改变时的槽函

void MainWindow::mstateChanged(QAbstractSocket::SocketState state)

{

// 获取发送信号的套接字对

QTcpSocket *tmp = (QTcpSocket *)sender();

// 根据套接字的不同状态进行不同处

switch(state){

case QAbstractSocket::UnconnectedState:

// 客户端断开连

ui->textBrowserRev->append("服务器:有客户端断开连接!"); tmp->deleteLater();

break;

case QAbstractSocket::ConnectedState:

// 客户端连

ui->textBrowserRev->append("服务器:有新客户端接入!"); break;

default:

break;

}

}

// 停止监听按钮的点击事件处理函

void MainWindow::on_pushButtonListenStop_clicked()

{

// 更新按钮状

ui->pushButtonListen->setEnabled(true);

ui->pushButtonListenStop->setEnabled(true);

// 停止监听端

tcpServer->close();

}

// 接收到数据时的槽函

void MainWindow::mreadData()

{

// 获取发送信号的套接字对

QTcpSocket *tmp = (QTcpSocket *)sender(); setTextColor(0,0,0); // 设置文本颜色为红色 cursor.insertText("客户端:"+ tmp->readAll()+"\n");

}

// “发送按钮的点击事件处理函

void MainWindow::on_pushButtonSend_clicked()

{

// 查找所有的子 QTcpSocket 

QList<QTcpSocket*> socketList = tcpServer->findChildren<QTcpSocket*>();

// 向每个连接的客户端发送数

foreach(QTcpSocket *tmp, socketList){

tmp->write(ui->textEditSnd->toPlainText().toUtf8()); setTextColor(255,0,0); // 设置文本颜色为红色 cursor.insertText("服务端:"+ui->textEditSnd-

>toPlainText().toUtf8()+"\n");

};

}

// 设置文本颜色的函

void MainWindow::setTextColor(int r, int g, int b)

{

QTextCharFormat textFormat;

textFormat.setForeground(QBrush(QColor(r, g, b))); // 根据提供的 RGB 值设置颜

// 应用格式到光

cursor.setCharFormat(textFormat);

}

    1. TCP客户端项目开

核心代

#include "mainwindow.h" #include "ui_mainwindow.h"

// 主窗口的构造函

MainWindow::MainWindow(QWidget *parent)

: QMainWindow(parent)

, ui(new Ui::MainWindow)

{

ui->setupUi(this); // 设置 UI

ui->centralwidget->setLayout(ui->verticalLayoutGlobal); // 设置中央小部件的布

this->setWindowTitle("网络调试助手客户端-上官QT案例"); // 设置窗口标题 ui->pushButtonDiscon->setEnabled(false); // 初始时禁用断开连接按钮 cursor = ui->textBrowser->textCursor(); // 获取文本浏览器的文本光标 tcpSocket = new QTcpSocket(this); // 创建一个新的 QTcpSocket

connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(mreadDataFromServer()));

// 连接信号与

}

// 析构函

MainWindow::~MainWindow()

{

delete ui; // 删除 UI

}

// 当点击发送按钮时调

void MainWindow::on_pushButtonSend_clicked()

{

tcpSocket->write(ui->textEditSend->toPlainText().toUtf8()); // 将文本编辑器中的文本发送到服务器

setTextColor(255,0,0); // 设置文本颜色为红

cursor.insertText("客户端:  "+ui->textEditSend->toPlainText().toUtf8()+"\n");

// 在文本浏览器中插入红色文

}

// 从服务器读取数

void MainWindow::mreadDataFromServer()

{

setTextColor(0,0,0); // 设置文本颜色为黑

cursor.insertText("服务端"+tcpSocket->readAll()+"\n"); // 在文本浏览器中插入黑色文本

}

// 当点击断开连接按钮时调

void MainWindow::on_pushButtonDiscon_clicked()

{

tcpSocket->close(); // 关闭套接字连

// 更新 UI 

    1. 项目总

TCPServer类关于监听,连接,发送,接受的API TCPServer在网络通信中常用的信号

TCPScoketQT实现Socket常用的API TCPScoketQT实现Socket常用的信

EditText的内容读取方法,内容写入方法,在特定行写入特点颜色的方

TCPServer  TCPScoket  的信息整合到一个表格中

API/

TCPServer

bool listen(const QHostAddress &address, quint16 port)

在指定的 IP 地址和端口上开始监听传入的连接。

void close()

停止服务器监听传入的连接。

API/

QTcpSocket

*nextPendingConnection()

返回下一个待处理连接

QTcpSocket 指针

TCPServer

newConnection()

当有新连接时发出

TCPScoket

void connectToHost(const QString &host, quint16 port)

连接到指定的主机和端口

qint64 write(const QByteArray &data)

向连接的套接字写入数据

QByteArray readAll()

读取可用的所有数据

void disconnectFromHost()

断开与主机的连接

TCPScoket

connected()

成功连接到主机时发出

disconnected()

从主机断开连接时发出

readyRead()

当有可读数据时发出

bytesWritten(qint64 bytes)

成功写入数据时发出

EditText

读取内容

String getText()

获取 EditText 的内容

写入内容

void setText(String text)

设置 EditText 的内容

使用光标改变文本颜色

void changeTextColor(int start, int end, int color)

使用光标( cursor )改变 EditText 中从 start 位置end 位置的文本颜色为 color 

P6 自定义控

    1. QPaintEvent绘图事

Qt 框架中一个重要的事件类,专门用于处理绘图事件。当 Qt 视图组件需要重绘自

的一部分时,就会产 事件。这通常发生在以下几种情况

  1. 窗口第一次显示时:当窗口或控件第一次出现在屏幕上时,系统会生成一个通知窗口进行自身的绘制。

事件

  1. 窗口大小改变时:当用户改变窗口的大小时,窗口的内容通常需要重新绘制以适应新的尺寸
  2. 窗口部分被遮挡后又重新显示时:如果窗口被其他窗口遮挡,然后又重新露出来,被遮挡的部分通常需要重新绘制。

  1. 手动请求重绘:通过调

Qt 应用程序中,通常通过重写 例如:

方法,可以手动触发重绘事件。方法来处理绘制逻辑。

方法中,您可以创建一 对象并使用它来执行绘制操作。 QPainter 可以

制各种基本图形,如线条、矩形、椭圆等,还可以绘制文本和图像。重

自定义绘制的标准做法

是在 Qt 中进

    1. QPainter
      1. 概述

Qt 库中用于在屏幕上进行绘画的类。它提供了各种绘制功能,比如画线、画图形、画文

以下是一些基本的用法示例

1. 初始化 QPainter:首先,您需要一个  QPaintDevice ,比如一

QPixmap ,然后使

用它来初始 对象

设置画笔和画刷:您可以设置画笔(用于描边)和画刷(用于填充)的颜色、样式等

绘制图形:使 的方法来绘制线条、矩形、圆形、文本等

结束绘制:完成绘制后QPainter 对象会在其析构函数中自动结束绘制

请注意, QPainter 的使用依赖于 Qt 的事件循环,因此通常 或者类似的

件处理函数中使用它。如果您在 Qt 应用程序中使用 QPainter ,请确保您遵循 Qt 的事件驱动机制

      1. 渐变色
        1. 线性渐

 Qt 框架中用于创建线性渐变的类。线性渐变是一种从一个颜色平滑过渡到另一个颜色的效果,其变化沿着两个点之间的直线进行。这种渐变在图形用户界面设计中非常常见,用于添加深度、立体感或动态效果。

基本用

要使用  QLinearGradient ,你需要执行以下几个基本步骤

          1. 对象:指定渐变的起点和终点坐标
          2. 设置颜色停靠点:在渐变线上定义颜色和相应的位置

          1. 使用渐变创建 QBrush :用中进行绘制。
示例代

以下是一个创建和使

对象来创建一个 QBrush ,然后用它

的示例代码

在这个例子中QLinearGradient 创建了一个从红色到蓝色的渐变,其方向是从小部件的左上角 (0, 0)

到右下角 (100, 100)

注意事

的颜色变化是沿着两个指定点之间的直线进行的。通过改变这些点的位置,你可以控制渐变的方向和长度。

方法的第一个参数是一个介于 0.0 1.0 之间的浮点数,表示颜色在渐变线上的位置。0.0 通常对应于起点,1.0 对应于终点。

你可以设置多个颜色停靠点来创建更复杂的渐变效果。例如,你可以在 0.0 处设置一种颜色,在 0.5

处设置另一种颜色,在 1.0 处再设置一种颜色

使 创建 可以用于填充任何形状,包括矩形、椭圆、多边形等

为了获取更好的视觉效果,可以启 的抗锯齿选项( QPainter::Antialiasing 

请注意,当窗口小部件的大小发生变化时,渐变的效果可能也会随之改变,除非你相应地调整渐变的起点和终点坐标或使用其他方法来适应大小变化。

        1. 径向渐

 Qt 框架中用于创建径向渐变的类。径向渐变是一种从中心点向外部辐射的颜色渐变,通常在中心点有一种颜色,而向外围渐渐变化为另一种颜色。这种渐变非常适合用于模拟光源、阴影或创建圆形的立体感。

基本用

要使用  QRadialGradient ,你需要执行以下几个基本步骤

          1. 对象:指定渐变的中心点、半径以及焦点(可选)
          2. 设置颜色停靠点:在径向渐变中定义颜色和对应的位置
          3. 使用渐变创建 QBrush :利 对象创建一个 QBrush ,然后

示例代

中进行绘制

以下是一个创建和使 的示例代码

在这个例子中QRadialGradient 创建了一个从中心的黄色向外围的黑色渐变。渐变的中心和半径都设置在 (50, 50, 50)

注意事

方法的第一个参数是一个介于 0.0 1.0 之间的浮点数,表示颜色在径向渐变中的位置。0.0 通常对应于中心点,1.0 对应于边缘。

通过添加多个颜色停靠点,你可以创建更复杂的径向渐变效果

方法允许你设置焦点位置,这是渐变颜色开始变化的点,可以与中心点不同

使 创建 可以用

填充任何形状,如矩形、椭圆、多边形等。为了获得更好的视觉效果,可以启用

的抗锯齿选项( QPainter::Antialiasing 

当绘制较大区域时,可以通过调整渐变的半径和中心点来控制渐变效果的扩展

非常适用于创建像按钮、指示灯或其他需要有深度感和立体感的界面元素

        1. 圆锥形渐

 Qt 框架中用于创建圆锥形渐变的类。圆锥渐变是一种渐变效果,其中颜色沿着圆锥的轮廓变化,类似于旋转颜色轮。这种渐变以其中心点为基点,颜色沿圆周分布,可以创建出富有动感的视觉效果。

基本用

要使用  QConicalGradient ,你通常需要做以下几个步骤

          1. 对象:指定渐变的中心点和起始角度

          1. 设置颜色停靠点:为渐变添加不同的颜色和对应的位置(角度)
          2. 使用渐变创建 QBrush :使用这个渐变对象来创建一个 QBrush ,然后应用到图。
示例代

中进行

下面是一个如何创建和使 的简单示例

在这个例子中QConicalGradient 被用来创建一个从红色到蓝色再回到红色的渐变。渐变的中心设置在点 (100, 100),并且从 0 度开始旋转。

注意事

的颜色是沿着圆周分布的,其中 你可以通过添加多个颜色停靠点来创建更复杂的渐变效果。

在圆周上是相同的位置

 

在使用时,角度是按照顺时针方向测量的,起始点(0度)通常在三点钟方向

为了达到最佳的渲染效果,可以启 的抗锯齿渲染提

非常适合用于创建旋转或动态效果的图形,例如加载指示器、进度条或任何需要圆周颜色变化的场景。

    1. 坐标转

Qt 框架中painter.translate(rect().center()) 这行代码的作用是移动 QPainter 的坐标系

原点到当前绘制区域(即

解释一下各个部分

返回的矩形)的中心

  1. painter : 这是一个 QPainter 对象实例,用于在 Qt 窗口或者图像上进行绘制
  2. translate() : 这是 QPainter 类中的一个方法,用于改变坐标系统的原点。它接受一个 QPoint 

QPointF 作为参数,这个点指定了新的原点位置

  1. rect() : 这通常是指一个控件(如 QWidget)的矩形区域,返回一个 QRect QRectF 对象,表示该控件的大小和位置。
  2. rect().center() : 这个方法返回当前矩形(即控件的区域)的中心点,是一个 QPoint 

QPointF 对象

总之painter.translate(rect().center()) 这行代码将 QPainter 的绘图原点移动到控件的中心。这在进行中心对称绘制或者需要以控件中心为基准进行绘图时特别有用。

    1. 画雷达案

delete ui;

}

void Widget::paintEvent(QPaintEvent *event)

{

QPainter painter(this);

// 抗锯齿

painter.setRenderHint(QPainter::Antialiasing,true);

// 把背景色刷成黑

QBrush brush(Qt::black); painter.setBrush(brush); painter.drawRect(rect());

// 平移坐标轴到窗口正中

painter.translate(rect().center());

// 最小圆的半

int rEve = height()/2/7; //800 600 600/7

int dataTmp = rEve * 7; //height()/2 导致突出,上面那行代码除不

// 设置画笔,绿色,像素4 QPen pen(Qt::green,4); painter.setPen(pen);

painter.setBrush(Qt::NoBrush); //不要画刷,否则只能看到最外面的圈 for(int i=1; i <= 7; i++){

painter.drawEllipse(QPoint(0,0),rEve*i,rEve*i);  //依次画出7个圆

}

painter.drawLine(-rEve*7,0,rEve*7,0); painter.drawLine(0,-rEve*7,0,rEve*7);

//设置锥形渐

QConicalGradient conGradient(0,0,-startAngle); conGradient.setColorAt(0,QColor(0,255,0,200)); conGradient.setColorAt(0.1,QColor(0,255,0,100)); conGradient.setColorAt(0.2,QColor(0,255,0,0)); conGradient.setColorAt(1,QColor(0,255,0,0));

//直接用渐变色指定画

painter.setBrush(conGradient); painter.setPen(Qt::NoPen); //去除扇形区域边框

//画出扇形,启动角度是startAngle,由定时器来修

painter.drawPie(QRect(-dataTmp,-dataTmp,dataTmp*2,dataTmp*2),

-startAngle*16,70*16);

}

    1. 仪表表
      1. 初步完成

mark = 0;

}

}

update();

});

timer->start(50);

}

Widget::~Widget()

{

delete ui;

}

void Widget::paintEvent(QPaintEvent *event)

{

QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing,true);

//底色弄成黑色 painter.setBrush(Qt::black);

painter.drawRect(rect());

//坐标系 平移到中

painter.translate(rect().center());

QRadialGradient radialGradient(0, 0, height()/2); // 中心和半径 (50, 50, 50)

// 设置颜色停靠

radialGradient.setColorAt(0.0, QColor(255,0,0,50)); // 中心颜

radialGradient.setColorAt(1.0, QColor(255,0,0,250)); // 外围颜

// 使用这个渐变创建 QBrush QBrush brush(radialGradient);

painter.setBrush(brush);

// 画大

painter.drawEllipse(QPoint(0,0),height()/2,height()/2); painter.setBrush(Qt::NoBrush);

// 画小

painter.setPen(QPen(Qt::white,3)); painter.drawEllipse(QPoint(0,0),60,60);

//当前

painter.setFont(QFont("华文宋体",25));

// painter.drawText(0,0,QString::number(currentValue));

painter.drawText(QRect(-60,-60,120,120),Qt::AlignCenter,QString::number(currentV  alue));

//画刻

//1. 算出一个刻度需要旋转的角

double angle = 270*1.0 / 50;//270*1.0的作用是扩大变量类型,把int型阔成double,保留

//2. 设置第一个刻度的位

painter.setFont(QFont("华文宋体",15));

painter.save();//保存当前坐标位置,此时此刻是在原点,x3点钟方向 painter.rotate(135);

for(int i=0;i<=50;i++){ if(i % 10 == 0){

      1. 稍微美化

稍微修改后,依然存在数字方向的问题

}

Widget::~Widget()

{

delete ui;

}

void Widget::paintEvent(QPaintEvent *event)

{

QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing,true);

//底色弄成黑色 painter.setBrush(Qt::black);

painter.drawRect(rect());

//坐标系 平移到中

painter.translate(rect().center());

// 画大

painter.drawEllipse(QPoint(0,0),height()/2,height()/2); painter.setBrush(Qt::NoBrush);

// 画小

painter.setPen(QPen(Qt::white,3)); painter.drawEllipse(QPoint(0,0),60,60);

//当前

painter.setFont(QFont("华文宋体",25));

// painter.drawText(0,0,QString::number(currentValue));

painter.drawText(QRect(-60,-60,120,120),Qt::AlignCenter,QString::number(currentV  alue));

//画刻

//1. 算出一个刻度需要旋转的角

double angle = 240*1.0 / 60;//270*1.0的作用是扩大变量类型,把int型阔成double,保留

//2. 设置第一个刻度的位

painter.setFont(QFont("华文宋体",15));

painter.save();//保存当前坐标位置,此时此刻是在原点,x3点钟方向 painter.rotate(150);

for(int i=0;i<=60;i++){ if(i % 5 == 0){

//

if(150 + angle * i < 270){ painter.rotate(180);

painter.drawText(-(height()/2 - 20 - 10),

8,QString::number(i*4));

painter.rotate(-180);

}else{

painter.drawText(height()/2 - 20 - 45, 8,QString::number(i*4));

}

//画长的刻度线

painter.drawLine(height()/2 - 20, 0, height()/2 - 3 ,0);

}else{//画短的刻度线

      1. 优化数字显示后代码整理

void Widget::initCanvas(QPainter& painter)

{

painter.setRenderHint(QPainter::Antialiasing,true);

//底色弄成黑色 painter.setBrush(Qt::black); painter.drawRect(rect());

//坐标系 平移到中

QPoint cent(rect().width()/2, rect().height()*0.6); painter.translate(cent);

}

void Widget::drawMiddleCircle(QPainter &painter, int radius)

{

// 画小

painter.setPen(QPen(Qt::white,3)); painter.drawEllipse(QPoint(0,0),radius,radius);

}

void Widget::drawCurrentSpeed(QPainter &painter)

{

//当前

painter.setFont(QFont("华文宋体",20));

// painter.drawText(0,0,QString::number(currentValue));

painter.drawText(QRect(-60,-60,120,120),Qt::AlignCenter,QString::number(currentV  alue));

}

void Widget::drawScale(QPainter &painter, int radius)

{

//画刻

//1. 算出一个刻度需要旋转的角

angle = 240*1.0 / 60;//270*1.0的作用是扩大变量类型,把int型阔成double,保留小

//保存当前坐标位置,此时此刻是在原点,x3点钟方向 painter.save(); painter.setPen(QPen(Qt::white,5));

//2. 设置第一个刻度的位

painter.rotate(startAngle); for(int i=0;i<=60;i++){

if(% 5 == 0){

//画长的刻度线

painter.drawLine(radius - 20, 0, radius - 3 ,0);

}else{//画短的刻度线

painter.drawLine(radius - 8, 0, radius - 3 ,0);

}

//画完后旋转 painter.rotate(angle);

}

painter.restore();

}

void Widget::drawScaleText(QPainter &painter, int radius)

{

//写刻度文

painter.setFont(QFont("华文宋体",18)); int r = radius - 46;

for(int i=0; i<=60; i++){ if(i % 5 == 0){

//保存坐标

painter.save();

//算出平移点,弧度=角度*3.1415/180

int delX = qCos( (210-angle*i)*M_PI/180) * r;//QTsin认的是弧度 int delY = qSin(qDegreesToRadians(210-angle*i)) * r;

//平移坐标

painter.translate(QPoint(delX,-delY));

//旋转坐标

painter.rotate(-120+angle*i);//angle=4,30*4=120的时候,实参是0120

//写上文

painter.drawText(-25,-25,50,30,Qt::AlignCenter,QString::number(i*4));

//恢复坐标系 painter.restore();

}

}

}

void Widget::drawPointLine(QPainter &painter,int lenth)

{

//画指针,线

//坐标轴先回到原点 painter.restore();

painter.save();

painter.rotate(startAngle + angle * currentValue); painter.drawLine(60,0,lenth,0);

}

void Widget::drawSpeedPie(QPainter &painter, int radius)

{

painter.restore();

QRect rentangle(-radius,-radius,radius*2,radius*2); painter.setPen(Qt::NoPen); painter.setBrush(QColor(235,152,50,150));

painter.drawPie(rentangle,(360-startAngle)*16,-angle*currentValue*16);//angle

前面取 负数,为了让它顺时针方向

}

void Widget::startSpeed()

{

timer = new QTimer(this);

currentValue = 0;

connect(timer, &QTimer::timeout,[=](){ if(mark == 0){

currentValue++;

if(currentValue >= 60){

mark = 1;

}

}

if(mark == 1){

      1. 画一个指针

Qt中,使用 QPainter 来绘制一个类似指南针的指针,你通常会遵循以下步骤

  1. 创建一个QWidgetQMainWindow的子类:这是你绘图的画布
  2. 重写 paintEvent 方法:这个方法是Qt中绘制自定义图形的关键地方
  3. 使用QPainter:在paintEvent 中创建一QPainter 对象,并用它来绘制你的指针
  4. 绘制指针:可以通过绘制一个线条或者一个具有特定形状的多边形来创建指针,比如一个三角形
  5. 旋转指针:如果你想让指针能够像指南针那样旋转,你可以使用QPainter 的旋转功能。下面是一个简单的例子,展示如何在Qt中绘制一个静态的指针:

这个代码片段创建了一个自定义的QWidget,它在中间绘制了一个三角形作为指针。你可以通过添加更多的逻辑来使指针动态旋转,比如根据数据改变指针的方向。在实际应用中,指针的样式、大小和颜色都可以根据你的需要进行自定义。

      1. 内环

      1. 完结

painter.drawRect(rect());

//坐标系 平移到中

QPoint cent(rect().width()/2, rect().height()*0.6); painter.translate(cent);

}

void Widget::drawMiddleCircle(QPainter &painter, int radius)

{

// 画小

painter.setPen(QPen(Qt::white,3)); painter.drawEllipse(QPoint(0,0),radius,radius);

}

void Widget::drawCurrentSpeed(QPainter &painter)

{

//当前值 painter.setPen(Qt::white);

QFont font("Arial",30); font.setBold(true); painter.setFont(font);

// painter.drawText(0,0,QString::number(currentValue));

painter.drawText(QRect(-60,-60,120,70),Qt::AlignCenter,QString::number(currentVa  lue*4));

QFont font2("Arial",13); font.setBold(true); painter.setFont(font2);

painter.drawText(QRect(-60,-60,120,160),Qt::AlignCenter,"Km/h");

}

void Widget::drawScale(QPainter &painter, int radius)

{

//画刻

//1. 算出一个刻度需要旋转的角

angle = 240*1.0 / 60;//270*1.0的作用是扩大变量类型,把int型阔成double,保留小

//保存当前坐标位置,此时此刻是在原点,x3点钟方向 painter.save();

painter.setPen(QPen(Qt::white,5));

//2. 设置第一个刻度的位

painter.rotate(startAngle); for(int i=0;i<=60;i++){

if( i >= 40){

painter.setPen(QPen(Qt::red,5));

}

if(% 5 == 0){

//画长的刻度线

painter.drawLine(radius - 20, 0, radius - 3 ,0);

}else{//画短的刻度线

painter.drawLine(radius - 8, 0, radius - 3 ,0);

}

//画完后旋转 painter.rotate(angle);

}

painter.restore();

painter.setPen(QPen(Qt::white,5));

}

void Widget::drawScaleText(QPainter &painter, int radius)

{

//写刻度文

QFont font("Arial",15); font.setBold(true); painter.setFont(font); int r = radius - 49; for(int i=0; i<=60; i++){

if(% 5 == 0){

//保存坐标系 painter.save();

//算出平移点,弧度=角度*3.1415/180

int delX = qCos( (210-angle*i)*M_PI/180) * r;//QTsin认的是弧度 int delY = qSin(qDegreesToRadians(210-angle*i)) * r;

//平移坐标

painter.translate(QPoint(delX,-delY));

//旋转坐标

painter.rotate(-120+angle*i);//angle=4,30*4=120的时候,实参是0120

//写上文

painter.drawText(-25,-25,50,30,Qt::AlignCenter,QString::number(i*4));

//恢复坐标系 painter.restore();

}

}

}

void Widget::drawPointLine(QPainter &painter,int lenth)

{

//画指针,线 painter.save();

painter.setBrush(Qt::white); painter.setPen(Qt::NoPen);

static const QPointF points[4] = {

QPointF(0,0.0),

QPointF(200.0,-1.1),

QPointF(200.0,1.1),

QPointF(0,15.0),

};

painter.rotate(startAngle + angle * currentValue); painter.drawPolygon(points, 4);

// painter.drawLine(60,0,lenth,0);

//坐标轴先回到原点 painter.restore();

}

void Widget::drawSpeedPie(QPainter &painter, int radius)

{

QRect rentangle(-radius,-radius,radius*2,radius*2); painter.setPen(Qt::NoPen); painter.setBrush(QColor(255,0,0,80));

painter.drawPie(rentangle,(360-startAngle)*16,-angle*currentValue*16);//angle

前面取 负数,为了让它顺时针方向

}

void Widget::startSpeed()

{

timer = new QTimer(this);

currentValue = 0;

connect(timer, &QTimer::timeout,[=](){ if(mark == 0){

currentValue++; if(currentValue >= 61){

mark = 1;

}

}

if(mark == 1){ currentValue--; if(currentValue == 0){

mark = 0;

}

}

update();

});

timer->start(50);

}

void Widget::drawEllipseInnerBlack(QPainter &painter, int radius)

{

painter.setBrush(Qt::black); painter.drawEllipse(QPoint(0,0),radius,radius);

}

void Widget::drawEllipseInnerShine(QPainter &painter, int radius)

{

QRadialGradient radialGradient(0,0,radius); radialGradient.setColorAt(0.0, QColor(255,0,0,200)); // 中心颜色 radialGradient.setColorAt(1.0, QColor(0,0,0,100)); // 外围颜色

painter.setBrush(radialGradient); painter.drawEllipse(QPoint(0,0),radius,radius);

}

void Widget::drawEllipseOutterShine(QPainter &painter, int radius)

{

QRect rentangle(-radius,-radius,radius*2,radius*2); painter.setPen(Qt::NoPen);

QRadialGradient radiaGradient(0,0,radius); radiaGradient.setColorAt(1,QColor(255,0,0,200));

radiaGradient.setColorAt(0.97,QColor(255,0,0,120)); radiaGradient.setColorAt(0.9,QColor(0,0,0,0)); radiaGradient.setColorAt(0,QColor(0,0,0,0)); painter.setBrush(radiaGradient);

painter.drawPie(rentangle,(360-150)*16,-angle*61*16);//angle前面取 负数,为了让它顺时针方向画

}

void Widget::drawLogo(QPainter &painter, int radius)

{

QRect rectangle(-65,radius*0.38,130,50); painter.drawPixmap(rectangle,QPixmap(":/icon.png"));

}

void Widget::paintEvent(QPaintEvent *event)

{

QPainter painter(this); int rad = height()/2;

//初始化画

initCanvas(painter);

//画小圆 drawMiddleCircle(painter,60);

//画刻度 drawScale(painter, rad);

//画刻度文字 drawScaleText(painter, rad);

//

drawPointLine(painter, rad-58);

//画扇

drawSpeedPie(painter, rad+25);

//画渐变内圈圆 drawEllipseInnerShine(painter,110);

//画黑色内圈 drawEllipseInnerBlack(painter, 80);

//画当前速度 drawCurrentSpeed(painter);

//画外环发光圈 drawEllipseOutterShine(painter,rad+25);

//画一个汽车logo drawLogo(painter, rad);

}

    1. 汽车表盘参考样

P7 天气预报项

    1. 项目概

stylesheet界面美化 Json数据解析

HTTP

自定义控件绘制温度多控件

代码整合调试能

    1. stylesheet

设置边框弧

设置某方向边框弧

设置背景颜

父控件影

父控件指定某类控件的样式,子控件都要遵守此样式进行显示,除非子控件内部有做相关修

    1. 窗体无状态栏-

设置无状态

设置左键弹窗关闭功

    1. 窗口跟随移

代码实

实现的逻

    1. 天气预报数据接

第一种

数据返回

{"message":"success感谢又拍云(upyun.com)提供CDN

","status":200,"date":"20240122","time":"2024-01-22  11:20:56","cityInfo":

{"city":"北京市","citykey":"101010100","parent":"

","updateTime":"07:16"},"data":

{"shidu":"30%","pm25":4.0,"pm10":14.0,"quality":"","wendu":"-16","ganmao":"

人群可自由活动","forecast":[{"date":"22","high":"高温  -3","low":"

-11","ymd":"2024-01-22","week":"

","sunrise":"07:30","sunset":"17:20","aqi":24,"fx":"西北风","fl":"3

","type":"","notice":"愿你拥有比阳光明媚的心情"},{"date":"23","high":"

1","low":"低温  -9","ymd":"2024-01-23","week":"

","sunrise":"07:29","sunset":"17:22","aqi":37,"fx":"西北风","fl":"3

","type":"","notice":"愿你拥有比阳光明媚的心情"},{"date":"24","high":"

4","low":"低温  -7","ymd":"2024-01-24","week":"

","sunrise":"07:29","sunset":"17:23","aqi":74,"fx":"北风","fl":"2

","type":"","notice":"愿你拥有比阳光明媚的心情"},{"date":"25","high":"

5","low":"低温  -8","ymd":"2024-01-25","week":"

","sunrise":"07:28","sunset":"17:24","aqi":86,"fx":"西北风","fl":"2","type":"

","notice":"阴晴之间,谨防紫外线侵扰"},{"date":"26","high":"高温  5","low":"

-7","ymd":"2024-01-26","week":"

","sunrise":"07:27","sunset":"17:25","aqi":79,"fx":"北风","fl":"2

","type":"","notice":"愿你拥有比阳光明媚的心情"},{"date":"27","high":"

6","low":"低温  -4","ymd":"2024-01-27","week":"

","sunrise":"07:26","sunset":"17:26","aqi":53,"fx":"西北风","fl":"2

","type":"","notice":"愿你拥有比阳光明媚的心情"},{"date":"28","high":"

4","low":"低温  -5","ymd":"2024-01-28","week":"

","sunrise":"07:26","sunset":"17:28","aqi":52,"fx":"北风","fl":"1","type":"

","notice":"阴晴之间,谨防紫外线侵扰"},{"date":"29","high":"高温  1","low":"

-6","ymd":"2024-01-29","week":"

","sunrise":"07:25","sunset":"17:29","aqi":22,"fx":"东北风","fl":"1

","type":"","notice":"愿你拥有比阳光明媚的心情"},{"date":"30","high":"

3","low":"低温  -6","ymd":"2024-01-30","week":"

","sunrise":"07:24","sunset":"17:30","aqi":34,"fx":"东风","fl":"2

","type":"","notice":"不要被阴云遮挡住好心情"},{"date":"31","high":"

4","low":"低温  -4","ymd":"2024-01-31","week":"

","sunrise":"07:23","sunset":"17:31","aqi":48,"fx":"东南风","fl":"2

","type":"","notice":"不要被阴云遮挡住好心情"},{"date":"01","high":"

8","low":"低温  -3","ymd":"2024-02-01","week":"

","sunrise":"07:22","sunset":"17:32","aqi":42,"fx":"西风","fl":"1

","type":"","notice":"不要被阴云遮挡住好心情"},{"date":"02","high":"

7","low":"低温  -3","ymd":"2024-02-02","week":"

","sunrise":"07:21","sunset":"17:34","aqi":59,"fx":"东南风","fl":"1

","type":"","notice":"不要被阴云遮挡住好心情"},{"date":"03","high":"

2","low":"低温  -4","ymd":"2024-02-03","week":"

","sunrise":"07:20","sunset":"17:35","aqi":41,"fx":"南风","fl":"2","type":"

","notice":"小雪虽美,赏雪别着凉"},{"date":"04","high":"高温  2","low":"

-5","ymd":"2024-02-04","week":"

","sunrise":"07:19","sunset":"17:36","aqi":45,"fx":"西北风","fl":"1","type":"

","notice":"阴晴之间,谨防紫外线侵扰"},{"date":"05","high":"高温  3","low":"

-5","ymd":"2024-02-05","week":"

","sunrise":"07:18","sunset":"17:37","aqi":48,"fx":"北风","fl":"1","type":"","notice":"阴晴之间,谨防紫外线侵扰"}],"yesterday":{"date":"21","high":"高温

-5","low":"低温  -10","ymd":"2024-01-21","week":"

","sunrise":"07:31","sunset":"17:19","aqi":26,"fx":"西北风","fl":"4","type":"","notice":"愿你拥有比阳光明媚的心情"}}}

第二种

数据返

{"cityid":"101230101","date":"2024-01-22","week":"

","update_time":"11:29","city":"福州","cityEn":"fuzhou","country":"

","countryEn":"China","wea":"","wea_img":"yin","tem":"8.7","tem1":"7","tem2":"

-1","win":"东北风","win_speed":"2

","win_meter":"4km\/h","humidity":"78%","visibility":"10km","pressure":"1019"," air":"21","air_pm25":"21","air_level":"","air_tips":"各类人群可多参加户外活动,多呼吸一下清新的空气。","alarm":[{"alarm_type":"降温","alarm_level":"

","alarm_title":"福建省福州市发布降温蓝色预警","alarm_content":"福州市气象台202401220944分继续发布降温蓝色预警信号:受寒潮影响,今天到24日我市气温继续下降,日最低气温过程降幅可达912℃;今天到24日夜晨气温较低;过程最低气温晋安区山区可达-30℃,有结冰;其余地区13℃,有霜或霜冻;22日傍晚到23日上午部分乡镇将出现小雪或雨夹雪。请注意防范!(预警信息来源:国家预警信息发布中心)"},{"alarm_type":"降温","alarm_level":"蓝色","alarm_title":"福建省福州市发布降温蓝色预警","alarm_content":"福州市气象台202401220944分继续发布降温蓝色预警信 号:受寒潮影响,今天到24日我市气温继续下降,日最低气温过程降幅可达912℃;今天到24日夜晨气温较低;过程最低气温晋安区山区可达-30℃,有结冰;其余地区13℃,有霜或霜冻;22日傍晚到23日上午部分乡镇将出现小雪或雨夹雪。请注意防范!(预警信息来源:国家预警信息发布中心)"},

{"alarm_type":"降温","alarm_level":"蓝色","alarm_title":"福建省福州市发布降温蓝色

","alarm_content":"福州市气象台202401210929分发布降温蓝色预警信号:受寒潮影响,今天到23日我市气温持续下降,日最低气温过程降幅可达912℃,2224日夜晨气温较低,过程日最低气温晋安区北部可达-30℃,有霜或霜冻和结冰;其余地区13℃,有霜或霜冻,请注意防范!(预警信息来源:国家预警信息发布中心)"},{"alarm_type":"降温","alarm_level":"蓝色","alarm_title":"福建省福州市发布降温蓝色预警","alarm_content":"福州市气象台202401210929分发布降温蓝色预警信号:受寒潮影响,今天到23日我市气温持续下降,日最低气温过程降幅可达912℃,2224日夜晨气温较低,过程日最低气温晋安区北部可达-30℃,有霜或霜冻和结冰;其余地区13℃,有霜或霜冻,请注意防 范!(预警信息来源:国家预警信息发布中

心)"}],"rain_pcpn":"2.8","uvIndex":"2","uvDescription":"","wea_day":"","wea_day_img":"yu","wea_night":"

","wea_night_img":"yu","sunrise":"06:50","sunset":"17:36","hours":

[{"hours":"10:00","wea":"小雨","wea_img":"yu","tem":"9","win":"

","win_speed":"2","vis":"13","aqinum":"21","aqi":""},

{"hours":"11:00","wea":"小雨","wea_img":"yu","tem":"7","win":"

","win_speed":"2","vis":"12.92","aqinum":"22","aqi":""},

{"hours":"12:00","wea":"小雨","wea_img":"yu","tem":"7","win":"

","win_speed":"2","vis":"13.02","aqinum":"21","aqi":""},

{"hours":"13:00","wea":"","wea_img":"wu","tem":"7","win":"东北风","win_speed":"2

","vis":"13.02","aqinum":"20","aqi":""},

{"hours":"14:00","wea":"","wea_img":"wu","tem":"5","win":"东北风","win_speed":"2

","vis":"12.92","aqinum":"21","aqi":""},{"hours":"15:00","wea":"

","wea_img":"yu","tem":"4","win":"东北风","win_speed":"2

","vis":"12.78","aqinum":"24","aqi":""},{"hours":"16:00","wea":"

","wea_img":"yu","tem":"3","win":"东北风","win_speed":"2

","vis":"12.21","aqinum":"24","aqi":""},{"hours":"17:00","wea":"

","wea_img":"yu","tem":"2","win":"东北风","win_speed":"2

","vis":"11.77","aqinum":"27","aqi":""},{"hours":"18:00","wea":"

","wea_img":"yu","tem":"1","win":"东北风","win_speed":"2

","vis":"11.42","aqinum":"26","aqi":""},{"hours":"19:00","wea":"

","wea_img":"yu","tem":"1","win":"东北风","win_speed":"2

","vis":"10.77","aqinum":"24","aqi":""},{"hours":"20:00","wea":"

","wea_img":"yu","tem":"1","win":"东北风","win_speed":"2

","vis":"10.13","aqinum":"23","aqi":""},{"hours":"21:00","wea":"

","wea_img":"yu","tem":"1","win":"东北风","win_speed":"2

","vis":"9.3","aqinum":"23","aqi":""},{"hours":"22:00","wea":"

","wea_img":"yu","tem":"1","win":"东北风","win_speed":"2

","vis":"9.11","aqinum":"24","aqi":""},{"hours":"23:00","wea":"

","wea_img":"yu","tem":"1","win":"东北风","win_speed":"1

","vis":"9.11","aqinum":"27","aqi":""},

{"hours":"00:00","wea":"","wea_img":"wu","tem":"2","win":"东北风","win_speed":"1

","vis":"8.91","aqinum":"27","aqi":""},{"hours":"01:00","wea":"

","wea_img":"yu","tem":"2","win":"东北风","win_speed":"1

","vis":"8.91","aqinum":"28","aqi":""},{"hours":"02:00","wea":"

","wea_img":"yu","tem":"2","win":"东北风","win_speed":"1

","vis":"8.91","aqinum":"30","aqi":""},{"hours":"03:00","wea":"

","wea_img":"yu","tem":"2","win":"东北风","win_speed":"1

","vis":"8.91","aqinum":"28","aqi":""},{"hours":"04:00","wea":"

","wea_img":"yu","tem":"2","win":"北东北风","win_speed":"1

","vis":"9.28","aqinum":"28","aqi":""},

{"hours":"05:00","wea":"","wea_img":"yin","tem":"2","win":"

","win_speed":"1","vis":"9.83","aqinum":"28","aqi":""},

{"hours":"06:00","wea":"多云","wea_img":"yun","tem":"3","win":"

","win_speed":"1","vis":"10.7","aqinum":"28","aqi":""},

{"hours":"07:00","wea":"","wea_img":"qing","tem":"4","win":"

","win_speed":"1","vis":"11","aqinum":"28","aqi":""},

{"hours":"08:00","wea":"","wea_img":"qing","tem":"5","win":"

","win_speed":"1","vis":"11.59","aqinum":"28","aqi":""},

{"hours":"09:00","wea":"","wea_img":"qing","tem":"6","win":"

","win_speed":"1","vis":"12.41","aqinum":"27","aqi":""},

{"hours":"10:00","wea":"","wea_img":"qing","tem":"7","win":"

","win_speed":"1","vis":"13.43","aqinum":"27","aqi":""},

{"hours":"11:00","wea":"","wea_img":"qing","tem":"8","win":"

","win_speed":"1","vis":"14.42","aqinum":"27","aqi":""},

{"hours":"12:00","wea":"","wea_img":"qing","tem":"8","win":"

","win_speed":"1","vis":"15.58","aqinum":"25","aqi":""},

{"hours":"13:00","wea":"","wea_img":"qing","tem":"9","win":"

","win_speed":"1","vis":"16.85","aqinum":"24","aqi":""}],"aqi":

{"update_time":"10:47","air":"21","air_level":"","air_tips":"各类人群可多参加户外活动,多呼吸一下清新的空

气。","pm25":"14","pm25_desc":"","pm10":"21","pm10_desc":"","o3":"42","o3_desc

":"","no2":"17","no2_desc":"","so2":"5","so2_desc":"","co":"0.8","co_desc":"","ko  uzhao":"不用佩戴口罩","yundong":"适宜运动","waichu":"适宜外出","kaichuang":"适宜开

","jinghuaqi":"不需要打开"}}

未来7

数据返

{"cityid":"101230101","city":"福州","cityEn":"fuzhou","country":"

","countryEn":"China","update_time":"2024-01-22  11:47:00","data":[{"day":"22

(星期一)","date":"2024-01-22","week":"

","wea":"","wea_img":"yin","wea_day":"小雨","wea_day_img":"yu","wea_night":"

","wea_night_img":"yu","tem":"8.7","tem1":"7","tem2":"-1","humidity":"79%","vis

ibility":"11km","pressure":"1019","win":["无持续风向","无持续风向"],"win_speed":"<3

","win_meter":"2km\/h","sunrise":"06:50","sunset":"17:36","air":"21","air_level  ":"","air_tips":"各类人群可多参加户外活动,多呼吸一下清新的空气。","alarm":

{"alarm_type":"降温","alarm_level":"蓝色","alarm_title":"福建省福州市发布降温蓝色预 ","alarm_content":"福州市气象台202401220944分继续发布降温蓝色预警信号:受寒潮影

响,今天到24日我市气温继续下降,日最低气温过程降幅可达912℃;今天到24日夜晨气温较低;过程最低气温晋安区山区可达-30℃,有结冰;其余地区13℃,有霜或霜冻;22日傍晚到23日上午部分乡镇将出现小雪或雨夹雪。请注意防范!(预警信息来源:国家预警信息发布中心)"},"hours":[{"hours":"08

","wea":"","wea_img":"yin","tem":"7","win":"无持续风向","win_speed":"<3"},

{"hours":"09","wea":"小雨","wea_img":"yu","tem":"6","win":"东北风","win_speed":"

<3"},{"hours":"10","wea":"小雨","wea_img":"yu","tem":"6","win":"东北","win_speed":"<3"},{"hours":"11","wea":"

","wea_img":"yu","tem":"6","win":"东北风","win_speed":"<3"},{"hours":"12

","wea":"小雨","wea_img":"yu","tem":"6","win":"东北风","win_speed":"<3"},

{"hours":"13","wea":"小雨","wea_img":"yu","tem":"6","win":"东北风","win_speed":"

<3"},{"hours":"14","wea":"小雨","wea_img":"yu","tem":"6","win":"东北","win_speed":"<3"},{"hours":"15","wea":"

","wea_img":"yu","tem":"5","win":"东北风","win_speed":"<3"},{"hours":"16

","wea":"小雨","wea_img":"yu","tem":"5","win":"东北风","win_speed":"<3"},

{"hours":"17","wea":"小雨","wea_img":"yu","tem":"4","win":"东北风","win_speed":"

<3"},{"hours":"18","wea":"小雨","wea_img":"yu","tem":"4","win":"东北","win_speed":"<3"},{"hours":"19","wea":"

","wea_img":"yu","tem":"4","win":"东北风","win_speed":"<3"},{"hours":"20

","wea":"小雨","wea_img":"yu","tem":"4","win":"东北风","win_speed":"<3"},

{"hours":"21","wea":"小雨","wea_img":"yu","tem":"3","win":"东北风","win_speed":"

<3"},{"hours":"22","wea":"小雨","wea_img":"yu","tem":"3","win":"东北","win_speed":"<3"},{"hours":"23","wea":"

","wea_img":"yu","tem":"3","win":"东北风","win_speed":"<3"},{"hours":"00

","wea":"雨夹雪","wea_img":"yu","tem":"1","win":"东北风","win_speed":"<3"},

{"hours":"01","wea":"雨夹雪","wea_img":"yu","tem":"0","win":"东北","win_speed":"<3"},{"hours":"02","wea":"雨夹

","wea_img":"yu","tem":"0","win":"东北风","win_speed":"<3"},{"hours":"03

","wea":"雨夹雪","wea_img":"yu","tem":"0","win":"东北风","win_speed":"<3"},

{"hours":"04","wea":"雨夹雪","wea_img":"yu","tem":"0","win":"东北","win_speed":"<3"},{"hours":"05","wea":"雨夹

","wea_img":"yu","tem":"1","win":"东北风","win_speed":"<3"},{"hours":"06

","wea":"小雨","wea_img":"yu","tem":"2","win":"东北风","win_speed":"<3"},

{"hours":"07","wea":"小雨","wea_img":"yu","tem":"2","win":"东北风","win_speed":"

<3"}],"index":[{"title":"紫外线指数","level":"最弱","desc":"辐射弱,涂擦SPF8-12防晒

肤品。"},{"title":"减肥指数","level":"较不宜","desc":"有降水,推荐您在室内进行休闲

动。"},{"title":"血糖指数","level":"极不易发","desc":"无需担心过敏,可放心外出,享受

活。"},{"title":"穿衣指数","level":"","desc":"建议着棉衣加羊毛衫等冬季服装。"},

{"title":"洗车指数","level":"不宜","desc":"有雨,雨水和泥水会弄脏爱车。"},{"title":"空气污染扩散指数","level":"","desc":"气象条件有利于空气污染物扩

散。"}],"uvIndex":"2","uvDescription":""},{"day":"23日(星期二)","date":"2024-01-

23","week":"星期二","wea":"多云转晴","wea_img":"yun","wea_day":"

","wea_day_img":"yun","wea_night":"","wea_night_img":"qing","tem":"10","tem1":

"10","tem2":"2","humidity":"63","visibility":"","pressure":"","win":["无持续风","无持续风向"],"win_speed":"<3

","win_meter":"","sunrise":"06:50","sunset":"17:37","air":"31","air_level":"",  "air_tips":"","alarm":

{"alarm_type":"","alarm_level":"","alarm_content":""},"hours":[{"hours":"08

","wea":"小雨","wea_img":"yu","tem":"3","win":"东北风","win_speed":"<3"},

{"hours":"09","wea":"多云","wea_img":"yun","tem":"4","win":"东北风","win_speed":"

<3"},{"hours":"10","wea":"多云","wea_img":"yun","tem":"5","win":"东北","win_speed":"<3"},{"hours":"11","wea":"

","wea_img":"yun","tem":"7","win":"北风","win_speed":"<3"},{"hours":"12

","wea":"多云","wea_img":"yun","tem":"8","win":"东北风","win_speed":"<3"},

{"hours":"13","wea":"多云","wea_img":"yun","tem":"8","win":"东北风","win_speed":"

<3"},{"hours":"14","wea":"","wea_img":"qing","tem":"9","win":"","win_speed":"<3"},{"hours":"15

","wea":"","wea_img":"qing","tem":"9","win":"东风","win_speed":"<3"},

{"hours":"16","wea":"","wea_img":"qing","tem":"8","win":"东风","win_speed":"<3

"},{"hours":"17","wea":"","wea_img":"qing","tem":"7","win":"","win_speed":"<3"},{"hours":"18

","wea":"","wea_img":"qing","tem":"6","win":"东风","win_speed":"<3"},

{"hours":"19","wea":"","wea_img":"qing","tem":"6","win":"东北风","win_speed":"

<3"},{"hours":"20","wea":"","wea_img":"qing","tem":"5","win":"东北","win_speed":"<3"},{"hours":"21

","wea":"","wea_img":"qing","tem":"4","win":"东北风","win_speed":"<3"},

{"hours":"22","wea":"","wea_img":"qing","tem":"4","win":"东北风","win_speed":"

<3"},{"hours":"23","wea":"","wea_img":"qing","tem":"4","win":"东北","win_speed":"<3"},{"hours":"00

","wea":"","wea_img":"qing","tem":"4","win":"东北风","win_speed":"<3"},

{"hours":"01","wea":"","wea_img":"qing","tem":"3","win":"东北风","win_speed":"

<3"},{"hours":"02","wea":"","wea_img":"qing","tem":"3","win":"东北","win_speed":"<3"},{"hours":"03

","wea":"","wea_img":"qing","tem":"2","win":"东南风","win_speed":"<3"},

{"hours":"04","wea":"","wea_img":"qing","tem":"2","win":"西南风","win_speed":"

<3"},{"hours":"05","wea":"","wea_img":"qing","tem":"2","win":"","win_speed":"<3"},{"hours":"06

","wea":"","wea_img":"qing","tem":"2","win":"北风","win_speed":"<3"},

{"hours":"07","wea":"","wea_img":"qing","tem":"3","win":"北风","win_speed":"<3

"}],"index":[{"title":"紫外线指数","level":"中等","desc":"涂擦SPF大于15PA+防晒护

品。"},{"title":"减肥指数","level":"较适宜","desc":"气温较低,在户外运动请注意增减

物。"},{"title":"血糖指数","level":"极不易发","desc":"无需担心过敏,可放心外出,享受

活。"},{"title":"穿衣指数","level":"较冷","desc":"建议着厚外套加毛衣等服装。"},

{"title":"洗车指数","level":"较不宜","desc":"路面有积水,车子易被溅上泥水。"},

{"title":"空气污染扩散指数","level":"","desc":"易感人群应适当减少室外

动。"}],"uvIndex":"5","uvDescription":"中等"},{"day":"24日(星期三)","date":"2024-  01-24","week":"星期

","wea":"","wea_img":"qing","wea_day":"","wea_day_img":"qing","wea_night":"

","wea_night_img":"qing","tem":"11","tem1":"11","tem2":"4","humidity":"46","vis

ibility":"","pressure":"","win":["无持续风向","无持续风向"],"win_speed":"<3

","win_meter":"","sunrise":"06:50","sunset":"17:38","air":"34","air_level":"",  "air_tips":"","alarm":

{"alarm_type":"","alarm_level":"","alarm_content":""},"hours":[{"hours":"08

","wea":"","wea_img":"qing","tem":"3","win":"西北风","win_speed":"<3"},

{"hours":"09","wea":"","wea_img":"qing","tem":"5","win":"西风","win_speed":"<3

"},{"hours":"10","wea":"","wea_img":"qing","tem":"7","win":"","win_speed":"<3"},{"hours":"11

","wea":"","wea_img":"qing","tem":"9","win":"东风","win_speed":"<3"},

{"hours":"12","wea":"","wea_img":"qing","tem":"9","win":"东风","win_speed":"<3

"},{"hours":"13","wea":"","wea_img":"qing","tem":"10","win":"","win_speed":"<3"},{"hours":"14

","wea":"","wea_img":"qing","tem":"10","win":"东风","win_speed":"<3"},

{"hours":"15","wea":"","wea_img":"qing","tem":"10","win":"东风","win_speed":"

<3"},{"hours":"16","wea":"","wea_img":"qing","tem":"9","win":"","win_speed":"<3"},{"hours":"17

","wea":"","wea_img":"qing","tem":"9","win":"东风","win_speed":"<3"},

{"hours":"18","wea":"","wea_img":"qing","tem":"8","win":"东风","win_speed":"<3

"},{"hours":"19","wea":"","wea_img":"qing","tem":"8","win":"","win_speed":"<3"},{"hours":"20

","wea":"","wea_img":"qing","tem":"8","win":"东北风","win_speed":"<3"},

{"hours":"21","wea":"","wea_img":"qing","tem":"7","win":"东北风","win_speed":"

<3"},{"hours":"22","wea":"","wea_img":"qing","tem":"5","win":"东北","win_speed":"<3"},{"hours":"23

","wea":"","wea_img":"qing","tem":"4","win":"北风","win_speed":"<3"},

{"hours":"00","wea":"","wea_img":"qing","tem":"4","win":"东南风","win_speed":"

<3"},{"hours":"01","wea":"","wea_img":"qing","tem":"4","win":"西南","win_speed":"<3"},{"hours":"02

","wea":"","wea_img":"qing","tem":"4","win":"北风","win_speed":"<3"},

{"hours":"03","wea":"","wea_img":"qing","tem":"5","win":"北风","win_speed":"<3

"},{"hours":"04","wea":"","wea_img":"qing","tem":"5","win":"西北","win_speed":"<3"},{"hours":"05

","wea":"","wea_img":"qing","tem":"5","win":"西北风","win_speed":"<3"},

{"hours":"06","wea":"","wea_img":"qing","tem":"5","win":"西北风","win_speed":"

<3"},{"hours":"07","wea":"","wea_img":"qing","tem":"5","win":"西

","win_speed":"<3"}],"index":[{"title":"紫外线指数","level":"","desc":"涂擦SPF大于15PA+防晒护肤品。"},{"title":"减肥指数","level":"较适宜","desc":"气温较低,在户外运

动请注意增减衣物。"},{"title":"血糖指数","level":"极不易发","desc":"无需担心过敏,可放心

出,享受生活。"},{"title":"穿衣指数","level":"较冷","desc":"建议着厚外套加毛衣等服装。"},

{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"空气污染扩散指数","level":"","desc":"易感人群应适当减少室外活

动。"}],"uvIndex":"6","uvDescription":""},{"day":"25日(星期四)","date":"2024-01-

25","week":"星期四","wea":"晴转

","wea_img":"yun","wea_day":"","wea_day_img":"qing","wea_night":"

","wea_night_img":"yun","tem":"13","tem1":"13","tem2":"5","humidity":"51","visi

bility":"","pressure":"","win":["无持续风向","无持续风向"],"win_speed":"<3

","win_meter":"","sunrise":"06:50","sunset":"17:39","air":"31","air_level":"",  "air_tips":"","alarm":

{"alarm_type":"","alarm_level":"","alarm_content":""},"hours":[{"hours":"08

","wea":"","wea_img":"qing","tem":"6","win":"西北风","win_speed":"<3"},

{"hours":"11","wea":"","wea_img":"qing","tem":"11","win":"东南风","win_speed":"

<3"},{"hours":"14","wea":"","wea_img":"qing","tem":"12","win":"","win_speed":"<3"},{"hours":"17

","wea":"","wea_img":"qing","tem":"13","win":"东北风","win_speed":"<3"},

{"hours":"20","wea":"","wea_img":"qing","tem":"8","win":"东北风","win_speed":"

<3"},{"hours":"23","wea":"","wea_img":"qing","tem":"7","win":"西","win_speed":"<3"},{"hours":"02","wea":"

","wea_img":"yun","tem":"5","win":"北风","win_speed":"<3"},{"hours":"05

","wea":"多云","wea_img":"yun","tem":"5","win":"北风","win_speed":"<3

"}],"index":[{"title":"紫外线指数","level":"","desc":"涂擦SPF大于15PA+防晒护

品。"},{"title":"减肥指数","level":"较适宜","desc":"气温较低,在户外运动请注意增减

物。"},{"title":"血糖指数","level":"极不易发","desc":"无需担心过敏,可放心外出,享受

活。"},{"title":"穿衣指数","level":"较冷","desc":"建议着厚外套加毛衣等服装。"},

{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"空气污染扩散指数","level":"","desc":"易感人群应适当减少室外活

动。"}],"uvIndex":"6","uvDescription":""},{"day":"26日(星期五)","date":"2024-01-  26","week":"星期

","wea":"","wea_img":"qing","wea_day":"","wea_day_img":"qing","wea_night":"

","wea_night_img":"qing","tem":"15","tem1":"15","tem2":"6","humidity":"53","vis

ibility":"","pressure":"","win":["无持续风向","无持续风向"],"win_speed":"<3

","win_meter":"","sunrise":"06:49","sunset":"17:39","air":"30","air_level":"",  "air_tips":"","alarm":

{"alarm_type":"","alarm_level":"","alarm_content":""},"hours":[{"hours":"08

","wea":"多云","wea_img":"yun","tem":"6","win":"西北风","win_speed":"<3"},

{"hours":"11","wea":"多云","wea_img":"yun","tem":"10","win":"东南","win_speed":"<3"},{"hours":"14

","wea":"","wea_img":"qing","tem":"14","win":"东风","win_speed":"<3"},

{"hours":"17","wea":"","wea_img":"qing","tem":"12","win":"东北风","win_speed":"

<3"},{"hours":"20","wea":"","wea_img":"qing","tem":"10","win":"","win_speed":"<3"},{"hours":"23

","wea":"","wea_img":"qing","tem":"8","win":"东风","win_speed":"<3"},

{"hours":"02","wea":"","wea_img":"qing","tem":"6","win":"西北风","win_speed":"

<3"},{"hours":"05","wea":"","wea_img":"qing","tem":"7","win":"

","win_speed":"<3"}],"index":[{"title":"紫外线指数","level":"","desc":"涂擦SPF大于15PA+防晒护肤品。"},{"title":"减肥指数","level":"较适宜","desc":"天气凉,在户外运动

请注意增减衣物。"},{"title":"血糖指数","level":"极不易发","desc":"无需担心过敏,可放心

出,享受生活。"},{"title":"穿衣指数","level":"较冷","desc":"建议着厚外套加毛衣等服装。"},

{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"空气污染扩散指数","level":"","desc":"易感人群应适当减少室外活

动。"}],"uvIndex":"6","uvDescription":""},{"day":"27日(星期六)","date":"2024-01-

27","week":"星期六","wea":"多云","wea_img":"yun","wea_day":"","wea_day_img":"yun","wea_night":"

","wea_night_img":"yun","tem":"16","tem1":"16","tem2":"8","humidity":"53","visi

bility":"","pressure":"","win":["无持续风向","无持续风向"],"win_speed":"<3

","win_meter":"","sunrise":"06:49","sunset":"17:40","air":"36","air_level":"",  "air_tips":"","alarm":

{"alarm_type":"","alarm_level":"","alarm_content":""},"hours":[{"hours":"08

","wea":"","wea_img":"qing","tem":"8","win":"西北风","win_speed":"<3"},

{"hours":"11","wea":"多云","wea_img":"yun","tem":"12","win":"东南","win_speed":"<3"},{"hours":"14","wea":"

","wea_img":"yun","tem":"15","win":"东北风","win_speed":"<3"},{"hours":"17

","wea":"多云","wea_img":"yun","tem":"14","win":"东风","win_speed":"<3"},

{"hours":"20","wea":"多云","wea_img":"yun","tem":"13","win":"东风","win_speed":"

<3"},{"hours":"23","wea":"多云","wea_img":"yun","tem":"12","win":"东南","win_speed":"<3"},{"hours":"02","wea":"

","wea_img":"yun","tem":"8","win":"西北风","win_speed":"<3"},{"hours":"05

","wea":"多云","wea_img":"yun","tem":"8","win":"南风","win_speed":"<3

"}],"index":[{"title":"紫外线指数","level":"","desc":"辐射较弱,涂擦SPF12-15

PA+护肤品。"},{"title":"减肥指数","level":"较适宜","desc":"天气凉,在户外运动请注意增减

物。"},{"title":"血糖指数","level":"极不易发","desc":"无需担心过敏,可放心外出,享受

活。"},{"title":"穿衣指数","level":"较冷","desc":"建议着厚外套加毛衣等服装。"},

{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"空气污染扩散指数","level":"","desc":"易感人群应适当减少室外活

动。"}],"uvIndex":"5","uvDescription":"中等"},{"day":"28日(星期日","date":"2024-

01-28","week":"星期日","wea":"多云","wea_img":"yun","wea_day":"","wea_day_img":"yun","wea_night":"

","wea_night_img":"yun","tem":"17","tem1":"17","tem2":"10","humidity":"62","vis

ibility":"","pressure":"","win":["无持续风向","无持续风向"],"win_speed":"<3

","win_meter":"","sunrise":"06:49","sunset":"17:41","air":"33","air_level":"",  "air_tips":"","alarm":

{"alarm_type":"","alarm_level":"","alarm_content":""},"hours":[{"hours":"08

","wea":"多云","wea_img":"yun","tem":"10","win":"西北风","win_speed":"<3"},

{"hours":"11","wea":"多云","wea_img":"yun","tem":"13","win":"东南","win_speed":"<3"},{"hours":"14","wea":"

","wea_img":"yun","tem":"16","win":"东风","win_speed":"<3"},{"hours":"17

","wea":"多云","wea_img":"yun","tem":"15","win":"东风","win_speed":"<3"},

    1. 软件开发网络通信架
      1. BS架构/CS

在计算机网络和软件开发中,CS架构(Client-Server  Architecture,客户端-服务器架构)和BS

Browser-Server  Architecture,浏览器-服务器架构)是两种主要的应用程序架构

CS架构(客户端-服务器架构

CS架构是一种典型的两层结构,包括客户端和服务器两个部分。在这种架构中,客户端和服务器通过网络进行通信,每部分都有明确的职责。

        1. 客户端

用户界面通常在客户端呈现

可以是桌面应用程序、移动应用或专用软件

负责向服务器发送请求,接收和处理服务器响应

        1. 服务器

管理数据和业务逻辑

处理来自客户端的请求,并发送回响应

通常承载在远程系统上,如数据库服务器、应用服务器等

        1. 特点

需要为每种操作系统或平台单独开发客户端。高效的数据处理和响应能力。

在客户端设备上占用资源(如内存和处理能力)

BS架构(浏览器-服务器架构

BS架构是一种基于Web的三层或多层架构,主要通过Web浏览器作为客户端访问服务器上的应用程序

  1. 浏览器(客户端

使用标准Web浏览器(如ChromeFirefox等)作为客户端

无需安装额外的软件,使用HTMLCSSJavaScript显示内容

  1. 服务器

CS架构中的服务器类似,处理业务逻辑和数据存储。通过Web服务(如HTTP服务器)提供页面和数据。

  1. 特点

跨平台兼容性强,可以在任何支持Web浏览器的设备上运行。客户端无需安装专用软件,容易维护和更新。

可能依赖网络性能,因为所有操作都在服务器上进行

部署和维护BS架构易于部署和维护,而CS架构通常需要在每个客户端单独安装和更新

性能CS架构可以更有效地利用客户端的计算资源,适合高性能要求的应用。BS架构依赖于服务器的性能和网络延迟。

安全性CS架构中,数据经常在客户端和服务器之间传输,可能需要更复杂的安全措施。BS架构中,敏感数据主要存储在服务器端。

用户体验CS架构通常能提供更丰富的用户界面和交互功能。BS架构的用户体验受限于Web技术的能力。

在实际应用中,选择哪种架构取决于具体的业务需求、目标用户群、性能要求以及开发和维护的成本

      1. HTTP基本概

HTTP(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是万维

WWW)的数据通信的基础。了解HTTP的基本概念对于理解现代网络通信至关重要。以下是HTTP的一些核心概念:

  1. 请求和响

HTTP是一个基于请求-响应模式的协议。客户端(通常是Web浏览器)向服务器发送一个HTTP请求,然后服务器返回一个HTTP响应。请求包含请求的资源(如网页),而响应包含请求的资源的内容。

  1. HTTP

HTTP定义了一系列的方法来表明对资源的不同操作,最常用的包括

GET: 用于请求资源

POST: 用于提交数据给服务器(例如,表单数据)

PUT: 用于上传文件或内容

DELETE: 用于请求删除资源

HEAD: 用于获取资源的元信息,而不是资源本身

  1. 状态

服务器对请求的响应中包含一个状态码,它表示请求的成功或失败,以及失败的原因。常见的状态码包括:

200 OK: 请求成功

404 Not Found: 请求的资源未找到

500 Internal Server Error: 服务器内部错误

301 Moved Permanently: 请求的资源已永久移动到新位置

  1. URL(统一资源定位符

URLWeb上资源的地址。它指定了资源的位置以及用于访问资源的协议(例如,http://

  1. HTTP

HTTP请求和响应包含头部信息,这些信息包括元数据,如内容类型、内容长度、服务器信息、客户端信息等。例如, Content-Type 头部指示响应中的媒体类型(如text/htmlapplication/json)。

  1. 无状态协

HTTP是一个无状态协议,这意味着服务器不会保留任何请求的数据(状态)。然而,通过使用如 Cookies这样的机制,可以在多个请求之间维持状态。

  1. 安全性HTTPS

HTTPSHTTP的安全版本,它在HTTPTCP层之间增加了一个加密层(通常是SSL/TLS)。这提供了数据传输的加密和更好的安全性。

  1. RESTful API

RESTful是一种使用HTTP协议的Web服务设计风格,它利用HTTP的方法来实现API的不同操作。在 RESTful架构中,每个URL代表一个资源,并使用HTTP的方法(如GET, POST)来处理这些资源。

  1. SessionCookies

由于HTTP本身是无状态的,Cookies和会话(Session被用来在多个请求之间存储用户数据,从而为用户提供连贯的体验。

这些概念构成了HTTP的基础,是理解和使用HTTP协议的关键。每个概念都有它的具体细节和使用场景,了解这些有助于更好地在网络应用开发中应用HTTP

    1. QTHTTP

Qt中的HTTP编程主要涉及使用Qt的网络模块来进行HTTP请求和处理HTTP响应。Qt提供了一系列类来处理网络通信,其中最常用的类是QNetworkAccessManager  QNetworkRequest  QNetworkReply 以及相关的支持类。

以下是一个基本的HTTP编程示例,展示了如何使用Qt发送一个简单的HTTP GET请求并处理响应

步骤 1: 包含必要的头文

步骤 2: 发送HTTP

创建一QNetworkAccessManager 对象,并使用它发送HTTP请求。 QNetworkAccessManager 对象会异步地处理请求,并返回一QNetworkReply 对象。

在这个例子中,我们使用QNetworkAccessManager 的get 方法发送了一个HTTP GET请求到"http://exa mple.com"。然后,我们连接了QNetworkReply 对象的finished 信号到一个lambda函数,该函数在收HTTP响应时被调用。

注意事
  1. 异步处理: QNetworkAccessManager 的请求是异步的。这意味get 方法会立即返回,而HTTP应将在稍后通过信号处理。
  2. 错误处理: 应该检QNetworkReply 对象是否有错误,并相应地处理
  3. 内存管理:  QNetworkReply 对象需要被正确地管理,以避免内存泄漏。通常情况下,使

QObject::deleteLater 来安排删除它是一个好方法

    1. JSON
      1. 概述

JSONJavaScript Object Notation)是一种轻量级的数据交换格式。它易于人阅读和编写,同时也易于机器解析和生成。JSON是基于JavaScript的一个子集,尽管它是独立于语言的,且有多种语言支持。 JSON常用于网络应用程序中的数据传输,尤其是在Web应用程序中与后端服务器通信。

使用JSON的原因总结如下

易于阅读和编

JSON的结构简单、清晰,对人类来说易于阅读和编写

轻量级数据格

相较于XML等标记语言,JSON更轻量,使用更少的符号,数据体积更小

易于解析和生

大多数编程语言都提供了解析和生成JSON的内置支持或库

跨语言支

JSON是独立于语言的,被广泛支持和使用在多种编程语言中

网络友

JSON格式适合Web环境,易于通过网络传输,是Web API的常用格式

数据互操作

作为一种标准化格式,JSON提高了不同系统间的数据互操作性

BS/CS开发过程中,会使用不同的编程语言,JSON作为数据传输的标准化格式,方便程序员协议约定和数据处理,以下是不同编程语言处理JSON的方案

语言/

JSON处理库/

特点/

C

Jansson

提供JSON的编码、解码和处理功

C++

nlohmann/json

现代C++(从C++11开始)的JSON库,易于使

Java

Jackson

强大的JSON处理库,支持JSON的序列化和反序列

Gson

Google提供的JSON序列化/反序列化

Python

json

Python标准库中的JSON处理模

Qt

QJsonDocument

Qt框架中用于JSON处理的

QJsonObject

用于表示JSON对象的Qt

QJsonArray

用于表示JSON数组的Qt

Android

org.json

Android SDK自带的JSON处理类,提供基础JSON操作功

iOS

JSONSerialization

Apple提供的用于JSON处理的类,部分SwiftObjective-C准库中

      1. QT生成JSON

Qt中生成JSON数据并将其保存到文件的一个基本示例涉及使用 QJsonDocument QJsonObject 

QJsonArray 类。以下是创建一个简单JSON对象并将其保存到文件的示例代码

        1. 创建JSON对象:使QJsonObject 来构建JSON对象,并使用键值对填充数据
        2. 创建JSON数组:使QJsonArray 来创建一个数组,并添加元素
        3. 组合JSON结构:将JSON数组添加到JSON对象中
        4. 生成JSON文档:通QJsonDocument 来处理JSON数据,可以选择格式化(缩进)或压缩形式
        5. 保存到文件:创QFile 对象,打开文件,写入JSON数据,并关闭文件

这个例子展示了Qt中处理JSON的基础流程,包括创建、填充数据、转换为字符串,以及写入文件。您可以根据需要调整这个流程来适应更复杂的JSON结构或数据。

JSON中,数组可以包含多种类型的元素,包括对象。当您在Qt中处理JSON数组,其中的元素是对象时,您可以使用QJsonArray QJsonObject 来创建和处理这些数据结构。以下是一个示例,展示了如何创建一个包含多个对象的JSON数组,并将该数组添加到一个JSON对象中。

示例代

rootObj["tmp"] = 3;

//Json

QJsonArray jsonArray; jsonArray.append("data1"); jsonArray.append("data2"); jsonArray.append("data3"); jsonArray.append(100);

rootObj["testArry"] = jsonArray;

QJsonObject alarmObj; alarmObj["alamType"] = "雪灾"; alarmObj["alamLeve"] = "黄色";

alarmObj["alamTitle"] = "福州市警告老陈多穿点衣服";

rootObj["alam"] = alarmObj;

QJsonObject day0; day0["day"] = "星期一";

day0["wea"] = "";

day0["tem"] = 5.7;

QJsonObject day1; day1["day"] = "星期二";

day1["wea"] = "";

day1["tem"] = 7;

QJsonObject day2; day2["day"] = "星期三";

day2["wea"] = "多云";

day2["tem"] = 17;

QJsonArray dayArray; dayArray.append(day0); dayArray.append(day1); dayArray.append(day2);

rootObj["days"] = dayArray;

//通过QJsonDocumentJSON数据转换成QByteArray QJsonDocument jsonDoc(rootObj);

QByteArray jsonArry = jsonDoc.toJson();

QFile file("D:/QT/test.json"); file.open(QIODevice::WriteOnly); file.write(jsonArry); file.close();

}

Widget::~Widget()

{

delete ui;

}

      1. QT解析JSON

Qt中解析JSON数据通常涉及到使用 QJsonDocument  QJsonObject QJsonArray 类。这些类提供了处理JSON数据的必要工具,使您能够从JSON字符串中提取信息、遍历JSON对象或数组,并访问具体的数据项。以下是一个基本的示例,展示了如何在Qt中解析JSON字符串。

示例:解析JSON字符

假设您有一个JSON字符串,例如

以下是如何在Qt中解析这个JSON字符串的步骤

        1. 字符串转换为 QJsonDocument :使QJsonDocument::fromJson 方法将JSON字符串转换

QJsonDocument 对象

        1. 提取 QJsonObject :如QJsonDocument 包含一个JSON对象,使用 object() 方法获取它
        2. 访问对象数据:使用键("name" "age" )访QJsonObject 中的数据
        3. 处理数组:如果对象包含一个数组,使QJsonArray 来遍历数组中的元素

这个示例提供了一个基础框架,用于在Qt中解析和处理JSON数据。您可以根据实际需要调整这个过程,以适应不同的JSON结构和数据类型。

Qt中,如果你想要将JSON数据解析到一个 QMap 中,你可以遍历JSON对象的所有键值对,并将它们添加到QMap 里。这个方法特别适合于当你的JSON对象是一个简单的键值对集合时。以下是一个如何实现这一点的示例。

示例:将JSON数据解析到QMap

假设你有以下JSON数据

以下是如何将这些数据解析QMap<QString, QString> 中的步骤

  1. JSON字符串创建 QJsonDocument :使QJsonDocument::fromJson 来解析JSON字符串
  2. 创建 QMap :定义一QMap<QString, QString> 来存储键值对
  3. 遍历JSON对象:使keys() 方法获取所有键,然后遍历这些键,将对应的值添加QMap
  4. 打印 QMap 内容:遍QMap 并打印键值对

这个示例展示了如何将JSON对象的键值对解析到 QMap 中。这种方法适用于键值对类型的简单JSON象。对于更复杂的JSON结构,可能需要更详细的解析逻辑。

解析如下JSON

int tempretrue = jsonRoot["tmp"].toInt();

qDebug() << strW; qDebug() << strCityId;

qDebug() << QString::number(tempretrue);

//第五步:判读是否是一个数

if(jsonRoot.contains("testArry") && jsonRoot["testArry"].isArray()){ qDebug() << "array";

//如果是数组,转换成JSON

QJsonArray testArray = jsonRoot["testArry"].toArray();

//遍历数组,访问每一项 for(QJsonValue val : testArray){

//QJsonValuetype函数返回数据类型,根据不同的数据类型处理数

// QJsonValue::Type t = val.type(); switch (val.type()) {

case QJsonValue::Double:

qDebug() << QString::number(val.toDouble()); break;

case QJsonValue::String: qDebug() << val.toString(); break;

case QJsonValue::Object: break;

}

}

}

//第六步:判断某个键对应的值,是否是一个json对象 if(jsonRoot.contains("alam") && jsonRoot["alam"].isObject()){

//转成Json对象后处

QJsonObject alamObj = jsonRoot["alam"].toObject(); qDebug() << alamObj["alamLeve"].toString(); qDebug() << alamObj["alamTitle"].toString(); qDebug() << alamObj["alamType"].toString();

}

if(jsonRoot.contains("days") && jsonRoot["days"].isArray()){ QJsonArray dayArray = jsonRoot["days"].toArray(); for(QJsonValue val : dayArray){

//if(val.type() ==QJsonValue::Object ){ if(val.isObject()){

QJsonObject obj = val.toObject();

qDebug() << obj["day"].toString();

qDebug() << QString::number(obj["tem"].toDouble()); qDebug() << obj["wea"].toString();

}

}

}

}

}

Widget::~Widget()

{

delete ui;

}

天气类型和图

//根据keys,设置icon的路

mTypeMap.insert("暴雪",":/res/type/BaoXue.png"); mTypeMap.insert("暴雨",":/res/type/BaoYu. png"); mTypeMap.insert("暴雨到大暴雨",":/res/type/BaoYuDaoDaBaoYu.png"); mTypeMap.insert("大暴雨",":/res/type/DaBaoYu.png");

mTypeMap.insert("大暴雨到特大暴雨",":/res/type/DaBaoYuDaoTeDaBaoYu.png"); mTypeMap.insert("大到暴雪",":/res/type/DaDaoBaoXue.png"); mTypeMap.insert("大雪",":/res/type/DaXue.png");

mTypeMap.insert("大雨",":/res/type/DaYu.png"); mTypeMap.insert("冻雨",":/res/type/DongYu.png"); mTypeMap.insert("多云",":/res/type/DuoYun.png"); mTypeMap.insert("浮沉",":/res/type/FuChen.png"); mTypeMap.insert("雷阵雨",":/res/type/LeiZhenYu.png");

mTypeMap.insert("雷阵雨伴有冰雹",":/res/type/LeiZhenYuBanYouBingBao.png"); mTypeMap.insert("",":/res/type/Mai.png");

mTypeMap.insert("强沙尘暴",":/res/type/QiangShaChenBao.png"); mTypeMap.insert("",":/res/type/Qing.png"); mTypeMap.insert("沙尘暴",":/res/type/ShaChenBao.png"); mTypeMap.insert("特大暴雨",":/res/type/TeDaBaoYu.png");

mTypeMap.insert("undefined",":/res/type/undefined.png");

mTypeMap.insert("",":/res/type/Wu.png");  mTypeMap.insert("小到中雪",":/res/type/XiaoDaoZhongXue.png"); mTypeMap.insert("小到中雨",":/res/type/XiaoDaoZhongYu.png"); mTypeMap.insert("小雪",":/res/type/XiaoXue.png"); mTypeMap.insert("小雨",":/res/type/XiaoYu.png"); mTypeMap.insert("",":/res/type/Xue.png"); mTypeMap.insert("扬沙",":/res/type/YangSha.png"); mTypeMap.insert("",":/res/type/Yin.png"); mTypeMap.insert("",":/res/type/Yu.png"); mTypeMap.insert("雨夹雪",":/res/type/YuJiaXue.png"); mTypeMap.insert("阵雪",":/res/type/ZhenXue.png"); mTypeMap.insert("阵雨",":/res/type/ZhenYu.png"); mTypeMap.insert("中到大雪",":/res/type/ZhongDaoDaXue.png"); mTypeMap.insert("中到大雨",":/res/type/ZhongDaoDaYu.png"); mTypeMap.insert("中雪",":/res/type/ZhongXue.png"); mTypeMap.insert("中雨",":/res/type/ZhongYu.png");

P8 Ubuntu搭建QT开发环

    1. 安装Ubutnu22
      1. 下载和安装Vmware

使用我们提供的安装包或者使用如下地址进行下

官方下载网址: https://download3.vmware.com/software/WKST-1700-WIN/VMware-workstation-fu ll-17.0.0-20800274.exe

支持正

如果你的电脑已经安装低版本的VMware,千万不要卸载,直接覆盖安装,更新到17的版

      1. 下载和安装Ubuntu22

使用我们提供的镜

安装的过程看视频教程,安装之后打开如下图所

      1. 常用功能配置
先掌握如下命

查看命令所在目

查看当前目录下的所有文件和文件夹创建文件夹

复制拷贝文件 复制拷贝文件夹

删除文件 rm 文件名 ,如果删除文件夹 加 -rf

特别有用!!善于使用tab键,能自动补全文件名或者命令名,不会造成输入错

网络配

正常电脑就一台虚拟机,通过以上安装后,就能正常上

多虚拟机情况,桥接模式冲突,配置不稳定,选择NAT共享主机网络上网获取IP地址通过命令 ip addr

共享文件配

windows需要传文件给虚拟机 可以通过共享文件夹的方式可以通过网络的方式

编译环

默认情况,系统不带编译环境,通过以下命令安装环

安装VMware Tool

windows系统的文本复制黏贴打通共享文件夹

配置支持ubuntu远程登

    1. 安装Ubuntu环境下的QT
      1. 下载安装UbuntuQT

下载QT通过如下命

wget   https://download.qt.io/archive/qt/5.12/5.12.9/qt-opensource-linux-x64-5.12.9.run

但是速度非常

直接去官网下载或者提供我们使用的安装包,把它通过共享文件夹拉倒Ubuntu中使

安装QT

通过如下命令启动QT的安装程序,在此之前和Windows一样,先让Ubuntu断网配置选择需要安装的项目如下,和Windows差不多

运行QT

通过如下命令: /opt/Qt5.12.9/Tools/QtCreator/bin/qtcreator.sh & 这里的“&”符号代表后台运行,不占用控制命令终端

      1. Ubuntu中文支持
配置Ubuntu的中文环

配置apt下载的服务器源,选择阿

更新源 sudo apt-get update

setting设置那边打开Region&Language

选择语言安装,在窗口中选择Chinese(simplified)

勾选Chinese,重

配置Ubuntu支持中文输

安装拼音输入

sudo apt-get install fcitx-sunpinyin

设置输入

点击应用到整个系统,关闭,重

拷贝我分享的so文件到QT相关路径,让QT支持输入中文!非常重要!!!用系统自带的不行

P9 加餐

http://www.xdnf.cn/news/1006741.html

相关文章:

  • 聚集索引与非聚集索引
  • Chapter07-信息披漏
  • Python原生爬虫教程:微店商品详情API接口攻略指南
  • 安徽省考计算机专业课笔记
  • XSS攻击概念通俗解释
  • STM32H7 SD卡使用以及其DMA读写
  • 【AI】理解神经网络原理
  • Java学习笔记之:Vue中路由的基本使用
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(34):ようですそうですばかりのに
  • 由于现在ui设计软件百花齐放,用传统的photoshop设计页面的方式正被摒弃
  • YOLOv2 技术详解:目标检测的又一次飞跃
  • 力扣100- 环形链表
  • vue-property-decorator实践(一)
  • 在 pgvector 中指定相似度搜索方法
  • 能提升30%!Infortrend普安存储自动分层增强版赋能文件共享与医疗影像
  • 华为OD机考-英文输入法-逻辑分析(JAVA 2025B卷)
  • 从 CAN FD 到 SD NAND(SLC)存储:S32K146 T-Box 如何驱动车载数据架构革新?
  • LeetCode 1143. 最长公共子序列 | 动态规划详解
  • 无人机遥控器低延迟高刷新技术解析
  • C# .NET Core Source Generator(C# .NET Core 源生成器)
  • md文件转word文档
  • 单元测试基本步骤
  • Spring MVC 常用请求处理注解总结
  • llm agent
  • OpenCV CUDA模块图像变形------对图像进行任意形式的重映射(Remapping)操作函数remap()
  • Spring Boot3批式访问Dify聊天助手接口
  • Vue 中 this.$emit(‘mount‘) 的妙用
  • 如何在 Discourse AI 中设置 Gemini API
  • 多串口卡使用
  • 软件测试BUG