文档测试发送
在上面的例子中, MyClass 有一个名为mySignal 的信号,它带有一个整型参数。
定义槽:槽可以是任何普通的成员函数,但通常在类定义中用slots 关键字标识。槽可以有返回类型,也可以接受参数,但它们的参数类型需要与发出信号的参数类型匹配。例如:
|
在这个例子中,我们定义了一个名为mySlot 的槽,它接收一个整型参数。
连接信号与槽:使用QObject::connect 函数将信号与槽连接起来。当信号被发射时,连接到这个信号的槽将被调用。
|
这行代码连接了myObject 的mySignal 信号到同一个对象的mySlot 槽。
发射信号:使用emit 关键字发射信号。当信号被发射时,所有连接到这个信号的槽都会被调用。
|
这将触发所有连接到mySignal 的槽。
自定义信号和槽是Qt编程中非常强大的特性,它们使得组件之间的通信变得灵活而松耦合。通过信和槽,可以方便地实现各种复杂的事件驱动逻//辑。
|
|
QDebug()
是 Qt 框架中用于输出调试信息的一个类。它提供了一种方便的方式来输出文本到标准输出(通常是控制台),这对于调试 Qt 应用程序非常有用。 QDebug 类可以与 Qt 的信号和槽机制一起使用,使得在响应各种事件时能够输出有用的调试信息。
使用 的一个典型方式是通过作符 来输出各种数据类型。例如:
函数,它返回一个
对象。然后,可以使用流操
当执行这些代码时,它们会在应用程序的控制台输出相应的文本。这对于检查程序的运行状态、变量的值或者跟踪程序的执行流程非常有帮助。
还可以使用 qDebug() 来输出自定义类型,只要为这些类型提供了适当的输出操作符重载。此外,Qt 还
提供了 qInfo() , qWarning() , 和 函数,用于输出不同级别的信息,分别用
于普通信息、警告、关键错误和致命错误。这有助于对日志信息进行级别划分,从而更好地控制输出内容。
-
- 文件操作类 QFile
是 Qt 框架中用于文件处理的一个类。它提供了读取和写入文件的功能,支持文本和二进制文
件。
继承自 QIODevice ,因此它可以像其他IO设备一样使用。
主要功能
-
文件读写: QFile 支持打开文件进行读取或写入操作 - 文件信息:可以检索有关文件的信息,如大小、修改日期等。
- 文件操作:提供了对文件进行重命名、移动、删除等操作的能力。
-
错误处理: 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-8、UTF-16 等不同编码。通过 setCodec() 方法设置特定编码。 |
读写文本 | 用于读写文件、字符串或任何继承自 QIODevice 的对象。 |
格式化 | 提供文本格式化功能,如数字精度、基数(十进制、十六进制等)调整。 |
流操作符 | 支持使用 << 和 >> 操作符,类似于 C++ 中的 iostream。 |
特性类别 | 说明 |
换行处理 | 自动处理不同操作系统间的换行符差异(如 Unix 的 \n 和 Windows 的 \r\n )。 |
错误处理 | 能够检测和报告在读写过程中出现的错误。 |
缓冲机制 | 提供缓冲机制,提高读写效率。 |
字符串操作 | 可以方便地处理和解析字符串数据。 |
是一个功能强大的类,用于处理文本数据,特别是在需要考虑字符编码和文本格式化的情况下。通过这些特性,它提供了一种灵活而强大的方式来读写和操作文本。
使用示例
以下是一个更详细的示例,展示了如何使用 来读写文件:
|
-
- 文件选择对话框 QFileDialog
- QFileDialog开发流程
- 文件选择对话框 QFileDialog
使用 的基本步骤通常如下:
实例化:首先,创建一个 对象的实例。
|
设置模式:根据需要设置对话框的模式,如打开文件、保存文件等。
|
设置过滤器:如果需要,可以设置文件类型过滤器,以限制用户可以选择的文件类型。
|
显示对话框:通过调用 方法显示对话框,并在用户作出选择后执行相应的操作。
|
通过
这是使用
方法获取用户选择的文件路径列表,然后对这些文件进行相应的处理。
的基本模式。Qt 也允许使用静态方法直接创建和显示对话框,例如
QFileDialog::getOpenFileName() ,这些方法更简单,但提供的自定义选项较少。
-
-
- QFileDialog 打开开发案例
-
|
-
-
- QFileDialog 保存开发案例
-
|
-
- 实现文件打开功能
- 开发流程
- 实现文件打开功能
为QPushButton对应Open的控件设置槽函数槽函数代码开发
打开文件
读取文件
把文件数据显示在TextEdit控件上
-
-
- 代码实现
-
|
-
-
- 打开功能优化
-
字符编码相关问题解决
在 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。 |
这些编码覆盖了大部分常用的语言字符集,可以通过中进行设置。
方法在
检测光标位置,并在右下角显示光标位置在程序左上方显示当前打开的文件名称
-
-
- QComboBox
-
是 Qt 框架中用于创建下拉列表的一个控件。
它允许用户从一组选项中选择一个选项,并可以配置为可编辑,使用户能够在其中输入文本。
提供了一系列方法来添加、删除和修改列表中的项,支持通过索引或文本检索项,并可以通过信号和槽机制来响应用户的选择变化。该
控件广泛应用于需要从多个选项中进行选择的用户界面场景,例如表单和设置界面。
功能 | 描述 | API 方法 |
添加选项 | 向下拉列表添加单个或多个选项 | addItem() , addItems() |
获取选项 | 获取当前选中的文本或索引 | currentText() , currentIndex() |
设置选项 | 设置当前选中的项 | setCurrentIndex(int) |
移除选项 | 从下拉列表中移除项 | removeItem(int) |
信号 | 当选项改变时触发的事件 | currentIndexChanged(int) |
可编辑性 | 设置下拉列表是否可编辑 | setEditable(bool) |
自定义数据 | 向下拉列表项关联额外的数据 | setItemData(int, const QVariant&) |
清空列表 | 移除所有选项 | clear() |
示例代码
|
这个示例展示了
需要调整和扩展这个示例。
的基本用法,包括添加选项、设置为可编辑以及连接信号和槽。您可以根据
-
-
- 记事本支持字符编码
-
获取用户在QComboBox上选择的字符编码,用特定编码打开文件,这里注意QComboBox返回QString类型,
setCodec参数要求const char*型
QString先转成C++的String,再转换成const char *
|
支持打开文件后进行字符编码的重新选择和显示加载
|
-
-
- 添加行列显示
-
使用QTextEdit的cursorPositionChanged信号,当光标发生移动时候刷新显示
|
-
-
- 添加文件打开提示
-
|
-
-
- 设置当前行高亮
-
实现策略:
获取当前行的光标位置,使用的信号和获取行列值是一样的通过ExtraSelection来配置相关属性
在当前行设置该属性
实现该功能,需要用到一个API,
|
-
-
-
- QList
-
-
在 Qt 框架中, QList 是一个容器类,它在内部实现上类似于一个数组,但也提供了一些链表的特性。的设计旨在提供一个在多数情况下既高效又方便的通用列表容器。用于存储元素列表。它提供了
丰富的功能,包括添加、移除、访问元素等。
QList 的内部工作原理:
-
-
-
-
-
数组式存储: QList 在大多数情况下使用连续内存存储其元素,类似于数组。这意味着它提供了快速的索引访问(通过下标操作符 [] ),以及相对高效的迭代性能。 -
动态调整大小:与静态数组不同, QList 可以动态增长和缩减,自动管理内存分配。 -
链表特性:虽然 主要基于数组,但它也提供了一些链表的操作,比如在列表的开始或结束
-
-
-
-
处添加和移除元素。这些操作通常比在数组中间插入或删除元素更高效。
-
-
-
-
-
复制时共享内存: QList 使用一种称为“隐式共享”(implicit sharing)或“写时复制”(copy-on-
-
-
-
-
write)的技术。这意味着当你复制一个 时,它不会立即复制所有元素,而是共享相同的数
据,直到你尝试修改其中一个列表,此时才进行实际的复制。这使得复制
使用场景:
变得非常高效。
当你需要快速的随机访问(如通过索引访问元素)时, QList 是一个不错的选择。如果你的主要操作是在列表的两端添加或移除元素, QList 也表现得很好。
基本用法
包含头文件:首先,你需要包含 的头文件。
|
创建 QList 实例:创建一个 对象,并指定存储的元素类型。
|
添加元素:使用 或 方法添加元素。
访问元素:可以使用下标操作符或 方法访问元素。
|
遍历列表:使用迭代器或范围基的 for 循环遍历列表。
|
移除元素:使用 removeAt 、 removeOne 或 方法移除元素。
|
3.8.2 ExtraSelection 简介
是一个在
中用来表示额外的文本选择和高亮的结构。
如何工作
-
ExtraSelection 结构体: QTextEdit::ExtraSelection 是一个结构体,包含了两个主要成员:和 QTextCharFormat 。 QTextCursor 表示在文本中的一个位置或者区间,而
用于定义这个区间的格式,比如背景颜色、字体等。
-
设置 ExtraSelection:你可以创建一个或多个 对象,为它们设置相应的光标位
置和格式,然后通过 的 方法将这些对象应用到文本编辑器中。
这样,你可以对文本的特定部分应用特定的格式,而不影响其他文本。
-
高亮当前行:要高亮显示当前行,你需要在
信号的槽函数中创建一个
对象。使用当前的
对象(通过
方法获取)来确
定当前行的位置,并设置背景颜色为你选择的高亮颜色。
类是 Qt 框架中的一部分,用于描述文本字符的格式。这个类提供了丰富的接口来设置和获取文本字符的各种属性,如字体、颜色、背景色等。 QTextCharFormat 通常用于富文本处理,可
以在像 和
下面列出了
这样的类中使用
的一些常用功能和方法:
- 设置和获取字体样式:
使用
方法设置字体。
通过 方法获取当前字体。
- 设置字体属性:
setFontWeight() : 设置字体的粗细。 setFontItalic() : 设置字体是否倾斜。 setFontUnderline() : 设置是否有下划线。
- 设置文本颜色和背景色:
setForeground() : 设置文本的前景色(即字体颜色)。
setBackground() : 设置文本的背景色。
- 其他文本属性:
setToolTip() : 设置文本的工具提示。 setAnchor() : 设置文本是否为超链接。 setAnchorHref() : 设置超链接的目标 URL。
示例代码
下面是一个简单的示例,展示如何在
中使用
来设置特定文本的格式:
-
- 文件保存功能优化
- 开发流程
- 文件保存功能优化
判断当下是否有已经打开的文件,如果有打开的文件读取TextEdit的内容
写入新文件
|
-
- 关闭优化
在上节课中关闭部分稍微优化了以下,但是还是不够, 我们应该弹出窗口多一个询问!
|
-
-
- 消息对话框 QMessageBox
-
是 Qt 框架中用于显示消息框的一个类,它常用于向用户显示信息、询问问题或者报告错
误。以下是 的一些主要用途:
- 显示信息:向用户显示一些信息性的消息。
- 询问用户决策:询问用户一个问题,并根据其回答做出相应的操作。
- 报告错误:向用户报告程序运行中的错误。代码示例
以下是一个简单的 使用示例,展示了如何创建一个基本的消息框:
|
在这个例子中,我们创建了一个 对象,并设置了窗口标题、主要文本、附加信息文本和
图标。还添加了两个按钮(OK 和 Cancel),并设置了默认按钮。通过
据用户的选择执行不同的操作。
方法显示消息框,并根
由于 是为标准对话框设计的,其定制能力有限,但你可以通过添加自定义按钮来实现一
定程度的定制。例如,如果你想要添加一个自定义的按钮,可以这样做:
|
在这个例子中,通过 方法添加了一个自定义按钮。按钮的角色被设置为
QMessageBox::ActionRole ,这意味着它将被放置在对话框的底部,与其他标准按钮一起。通过检查用户点击的按钮来确定是否点击了自定义按钮。
3.7.3 代码实现
|
-
- 实现快捷键功能
- 快捷键开发基础
- 实现快捷键功能
在 Qt 中实现快捷键功能通常涉及到
Qt 应用程序中为特定功能设置快捷键:
类的使用。下面是一个简单的代码示例,展示了如何在
在这个示例中,当用户按下 Ctrl + N 时,程序将弹出一个消息框。这是通过创建一个 对象,
并将其快捷键序列设置为
来实现的。然后,将
信号连接到一个 Lambda 函数,
该函数在快捷键被激活时执行。这种方法非常适用于为特定操作提供快速访问路径。
-
-
- 上官记事本添加快捷键
-
|
-
- 实现字体放大缩小功能
- 滚动调节字体大小的流程
- 实现字体放大缩小功能
为TextEdit添加事件过滤器重写窗口的eventFilter函数
eventFilter设置滚轮事件和目标对象实现字体放大缩小的功能函数
-
-
- 本节笔记失误
-
啥也没有,嘿嘿嘿
-
-
- 检测Ctrl键被按下
-
(如 Ctrl、Shift、Alt 等)。当与了 Control 键。
是 Qt 中一个静态函数,用于返回当前按下的键盘修饰符结合使用时,这个函数可以用来检测是否按下
例如,以下代码片段检查 Control 键是否被按下:
这里, QGuiApplication::keyboardModifiers() 返回当前按下的修饰符,而
前按下的修饰符中。
是一个枚举值,表示 Control 键。使用位与运算符
检查 Control 键是否在当
-
-
- 记事本添加字体放大缩小
-
|
-
-
- 事件
-
事件处理过程
众所周知Qt是一个基于C++的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高的)。所以在Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会经过: 事件派发 -> 事件过滤->事件分发->事件处理 几个阶段。Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作,比如信号与槽就是一种
事件(event)是由系统或者 Qt 本身在不同的场景下发出的。当用户按下/移动鼠标、敲下键盘,或者是窗口关闭/大小发生变化/隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如鼠标/键盘事件等;另一些事件则是由系统自动发出,如计时器事件。
每一个Qt应用程序都对应一个唯一的 QApplication 应用程序对象,然后调用这个对象的exec() 函数,这样Qt框架内部的事件检测就开始了( 程序将进入事件循环来监听应用程序的事件 )。
|
事件在Qt中产生之后,的分发过程是这样的:
-
当事件产生之后,Qt使用用应用程序对象调用 notify() 函数将事件发送到指定的窗口:
|
- 事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤。
|
- 当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类:
|
- 事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件。。。)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函 数),比如:鼠标事件:
|
重写事件案例
程序关闭之前的询问,鼠标进入,鼠标离开,窗口大小改变
#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)可以让你在事件达到目标对象之前进行拦截和处理。这是一种强大的机制,允许你在不同对象间共享事件处理逻辑或在父对象中集中处理特定事件。下面是加入事件过滤器的步骤:
-
定义事件过滤器: 事件过滤器通常是一个重写了QObject::eventFilter() 方法的对象。这个方法会在事件传递给目标对象之前被调用。 -
安装事件过滤器: 使用QObject::installEventFilter() 方法安装事件过滤器。这个方法告诉Qt在将事件发送给特定对象之前先通过过滤器对象。例如,如果你想在父窗口中过滤子窗口的事件,你需要在父窗口的对象上调用installEventFilter() ,并将子窗口作为参数传递。 -
事件过滤器逻辑: 在eventFilter() 方法内部,你可以编写自定义逻辑来决定如何处理或忽略事件。如果此方法返回true ,则表示事件已被处理,不应该继续传递;如果返回false ,则事件将正常传递给目标对象。 - 事件分发: 当事件发生时,Qt首先将事件发送到安装了事件过滤器的对象。在这一步,
eventFilter() 方法被调用。
-
决定是否传递事件: 根据eventFilter() 方法的返回值,Qt决定是否继续向目标对象传递事件。如果过滤器返回true ,事件处理到此结束;如果返回false ,事件继续传递到原始目标对象。 - 目标对象处理事件: 如果事件过滤器允许事件继续传递,目标对象将像没有事件过滤器存在时那样处理事件。
事件过滤器特别适用于以下情况:
当你想在不修改子类代码的情况下改变事件的行为。当多个对象需要共享相同的事件处理逻辑。
当你需要在更高的层级上监控或修改应用程序的事件流。
通过使用事件过滤器,Qt应用程序可以获得更大的灵活性和更细粒度的事件处理控制。
-
-
- 鼠标滚轮和字体大小
-
|
|
在 C++ 中,强制类型转换(或类型转换)是一种将变量从一种类型转换为另一种类型的方法。C++ 提供了四种强制转换运算符,每种都有其特定的用途和适用场景:
- static_cast
是最常用的类型转换运算符,用于无风险的转换,如整数到浮点数,字符到整
数等。
它在编译时执行,不执行运行时类型检查(RTTI)。
示例: int x = static_cast<int>(y); 其中
- dynamic_cast
可能是 float 类型。
专门用于处理对象的多态性,只能用于指针和引用,且涉及对象类必须有虚函数。
它在运行时检查类型的安全性,如果转换失败,对于指针类型返回 nullptr ,对于引用类型抛出异常。
示例: Derived *dp = dynamic_cast<Derived *>(bp); 其中是派生类。
- const_cast
用于修改类型的 const 或 volatile 属性。
是基类指针, Derived
通常用于去除对象的 const 性质,允许修改原本被声明为 const 的变量。示例: const int a = 10; int* b = const_cast<int*>(&a);
- 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 串口调试助手项目
-
- 项目概述
项目功能描述
见下方界面,所见即所得!
|
-
- 串口通信核心代码开发
代码会放在网盘上
全程高能力输出-代码开发和调试都在视频里
|
P5 网络调试助手
-
- TCP网络调试助手
- 项目概述
- TCP网络调试助手
网络相关的一些基础概念-面试用学习QTcpServer
学习QTcpClient
学习TextEdit特定位置输入文字颜色学习网络通信相关知识点
|
-
-
- 开发流程
-
|
-
-
- QTtcp服务器的关键流程
-
工程建立,需要在.pro加入网络权限
|
创建一个基于
-
-
-
- 创建并初始化
-
-
的服务端涉及以下关键步骤:
实例:
实例化 QTcpServer 。
调用
-
-
-
-
处理新连接:为
-
-
-
方法在特定端口监听传入的连接。
信号连接一个槽函数。
在槽函数中,使用
-
-
-
- 读取和发送数据:
-
-
获取 以与客户端通信。
通过连接使用
-
-
-
- 关闭连接:
-
-
的
方法发送数据回客户端。
信号来读取来自客户端的数据。
在适当的时候关闭 QTcpSocket 。示例代码可能如下:
|
确保在使用 和 时妥善处理网络错误和异常情况。
-
-
- QTtcp客户端的关键流程
-
工程建立,需要在.pro加入网络权限
|
创建一个基于
-
-
-
-
创建
-
-
-
的Qt客户端涉及以下步骤:
实例:
实例化 QTcpSocket 。
-
-
-
- 连接到服务器:
-
-
使用
-
-
-
- 发送数据到服务器:
-
-
方法连接到服务器的IP地址和端口。
使用 方法发送数据。
-
-
-
- 接收来自服务器的数据:
-
-
为
-
-
-
- 关闭连接:
-
-
信号连接一个槽函数来接收数据。
关闭示例代码如下:
连接。
这个客户端尝试连接到指定的服务器地址和端口,然后等待和处理来自服务器的数据。记得根据需要管理和处理网络错误和异常情况。
5.1.2 TCP协议
以下内容自省阅读和消化,主要在面试之前类似八股文问答,实际编程我们不需要关系这么多,
QTcpSocket类底下的API已经做好所有的封装。
TCP(传输控制协议)是一种广泛使用的网络通信协议,设计用于在网络中的计算机之间可靠地传输数据。它是互联网协议套件的核心部分,通常与IP(互联网协议)一起使用,合称为TCP/IP。以下是TCP协议的一些基本特点:
- 面向连接:在数据传输之前,TCP 需要在发送方和接收方之间建立一个连接。这包括三次握手过程,确保两端都准备好进行数据传输。
- 可靠传输:TCP 提供可靠的数据传输服务,这意味着它保证数据包准确无误地到达目的地。如果发生数据丢失或错误,TCP 会重新发送数据包。
- 顺序控制:TCP 保证数据包的传输顺序。即使数据包在网络中的传输顺序被打乱,接收方也能按照正确的顺序重组这些数据。
- 流量控制:TCP 使用窗口机制来控制发送方的数据传输速率,以防止网络过载。这有助于防止接收方被发送方发送的数据所淹没。
- 拥塞控制:TCP 还包括拥塞控制机制,用来检测并防止网络拥塞。当网络拥塞发生时,TCP 会减少其数据传输速率。
- 数据分段:大块的数据在发送前会被分割成更小的段,以便于传输。这些段会被独立发送并在接收端重新组装。
- 确认和重传:接收方对成功接收的数据包发送确认(ACK)信号。如果发送方没有收到确认,它会重传丢失的数据包。
- 终止连接:数据传输完成后,TCP 连接需要被正常关闭,这通常涉及到四次挥手过程。
TCP 适用于需要高可靠性的应用,如网页浏览、文件传输、电子邮件等。然而,由于它的这些特性,TCP在处理速度上可能不如其他协议(如UDP)那么快速。
TCP协议中的三次握手和四次挥手是建立和终止连接的重要过程。下面是它们的简要描述:
三次握手(建立连接)
三次握手的主要目的是在两台设备之间建立一个可靠的连接。它包括以下步骤:
- SYN:客户端向服务器发送一个SYN(同步序列编号)报文来开始一个新的连接。此时,客户端进入SYN-SENT状态。
- SYN-ACK:服务器接收到SYN报文后,回复一个SYN-ACK(同步和确认)报文。此时服务器进入
SYN-RECEIVED状态。
- ACK:客户端接收到SYN-ACK后,发送一个ACK(确认)报文作为回应,并进入ESTABLISHED(已建立)状态。服务器在收到这个ACK报文后,也进入ESTABLISHED状态。这标志着连接已经建立。
|
四次挥手(断开连接)
四次挥手的目的是终止已经建立的连接。这个过程包括以下步骤:
- FIN:当通信的一方完成数据发送任务后,它会发送一个FIN(结束)报文来关闭连接。发送完FIN
报文后,该方进入FIN-WAIT-1状态。
- ACK:另一方接收到FIN报文后,发送一个ACK报文作为回应,并进入CLOSE-WAIT状态。发送FIN
报文的一方在收到ACK后,进入FIN-WAIT-2状态。
- FIN:在等待一段时间并完成所有数据的发送后,CLOSE-WAIT状态的一方也发送一个FIN报文来请求关闭连接。
- 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 是实现网络通信的基础工具之一,它抽象化了网络层的复杂性,为开发者提供了一种相对简单的方式来建立和管理网络连接。
-
- UI设计
UI设计过程,教学视频展示,都是大家熟悉的内容了
-
- 网络通信核心代码
是 Qt 网络模块的一部分,用于构建 TCP 服务器。它提供了一种机制来异步监听来自客户端的连接。一旦接受了一个连接,服务器就可以与客户端进行数据交换。
-
-
- 创建TCP服务端的核心代码
-
主要步骤如下:
-
-
-
-
创建 实例:启动服务器并开始监听指定端口。 -
监听连接请求:调用 方法使服务器监听特定的 IP 地址和端口。 -
接受连接:当客户端尝试连接时, QTcpServer 产生一个信号。你需要实现一个槽(slot)来响应这个信号,并接受连接。
-
-
-
-
-
-
- 处理客户端连接:每个连接的客户端都关联一个示例代码
-
-
对象,用于数据交换。
代码解释
-
创建 - 监听端口:使用
对象:在主函数中,直接创建了一个
方法监听所有接口上的 12345 端口。
对象。
-
处理新连接:通过连接 信号,当有新客户端连接时,会调用相应的槽函数。
- 读取数据:为每个连接的客户端创建
- 发送数据:向客户端发送响应消息。
对象,并连接
信号以接收数据。
- 客户端断开连接时的处理:使用
这个代码示例展示了如何使用
信号确保客户端在断开连接时被适当地清理。
创建一个基本的 TCP 服务器,而无需通过继承来扩展类。这
种方式通常更简单,适用于不需要复杂处理的基本应用场景。
-
-
- 创建TCP客户端的核心代码
-
为了使客户端代码更具模块化和响应性,可以使用 Qt 的信号与槽机制。这种方法允许客户端以事件驱动的方式响应网络事件,如连接建立、数据接收等。下面是一个使用信号与槽的 TCP 客户端示例。
示例代码
|
代码解释
-
-
-
- 创建
-
-
类:这个类继承自 QObject ,允许使用信号与槽机制。
-
-
-
-
连接信号和槽:在构造函数中,将 的 和 信号分别连接到
-
-
-
和
-
-
-
- 连接到服务器:使用
-
-
槽。
方法开始连接过程。
-
-
-
-
处理连接建立:一旦连接建立, onConnected 槽被触发,客户端向服务器发送一条消息。 -
接收数据:当数据可读时, onReadyRead 槽被触发,客户端读取并打印来自服务器的数据。 - 断开连接:在接收数据后,客户端断开与服务器的连接。
-
-
-
这个客户端示例展示了如何使用 Qt 的信号与槽机制来处理 TCP 连接。这种方式使得代码更加清晰,易于维护,并且能更好地处理异步事件。
-
- 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);
}
-
- 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 状态
-
- 项目总结
TCPServer类关于监听,连接,发送,接受的API TCPServer在网络通信中常用的信号
TCPScoket在QT实现Socket常用的API TCPScoket在QT实现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 自定义控件
-
- QPaintEvent绘图事件
是 Qt 框架中一个重要的事件类,专门用于处理绘图事件。当 Qt 视图组件需要重绘自己
的一部分时,就会产生 事件。这通常发生在以下几种情况:
-
窗口第一次显示时:当窗口或控件第一次出现在屏幕上时,系统会生成一个通知窗口进行自身的绘制。
事件,
-
窗口大小改变时:当用户改变窗口的大小时,窗口的内容通常需要重新绘制以适应新的尺寸。 - 窗口部分被遮挡后又重新显示时:如果窗口被其他窗口遮挡,然后又重新露出来,被遮挡的部分通常需要重新绘制。
-
手动请求重绘:通过调用 的 或
在 Qt 应用程序中,通常通过重写 的例如:
方法,可以手动触发重绘事件。方法来处理绘制逻辑。
在 方法中,您可以创建一个 对象并使用它来执行绘制操作。 QPainter 可以绘
制各种基本图形,如线条、矩形、椭圆等,还可以绘制文本和图像。重写
自定义绘制的标准做法。
是在 Qt 中进行
-
- QPainter画家
- 概述
- QPainter画家
是 Qt 库中用于在屏幕上进行绘画的类。它提供了各种绘制功能,比如画线、画图形、画文本
等。
以下是一些基本的用法示例:
1. 初始化 QPainter:首先,您需要一个 QPaintDevice ,比如一个
或 QPixmap ,然后使
用它来初始化 对象。
|
设置画笔和画刷:您可以设置画笔(用于描边)和画刷(用于填充)的颜色、样式等。
|
绘制图形:使用 的方法来绘制线条、矩形、圆形、文本等。
|
结束绘制:完成绘制后, QPainter 对象会在其析构函数中自动结束绘制。
请注意, QPainter 的使用依赖于 Qt 的事件循环,因此通常在 的 或者类似的事
件处理函数中使用它。如果您在 Qt 应用程序中使用 QPainter ,请确保您遵循 Qt 的事件驱动机制。
-
-
- 渐变色
- 线性渐变
- 渐变色
-
是 Qt 框架中用于创建线性渐变的类。线性渐变是一种从一个颜色平滑过渡到另一个颜色的效果,其变化沿着两个点之间的直线进行。这种渐变在图形用户界面设计中非常常见,用于添加深度、立体感或动态效果。
基本用法
要使用 QLinearGradient ,你需要执行以下几个基本步骤:
-
-
-
-
-
创建 对象:指定渐变的起点和终点坐标。 - 设置颜色停靠点:在渐变线上定义颜色和相应的位置。
-
-
-
-
-
-
-
-
-
使用渐变创建 QBrush :用中进行绘制。
-
-
-
-
示例代码
以下是一个创建和使用
对象来创建一个 QBrush ,然后用它在
的示例代码:
在这个例子中, QLinearGradient 创建了一个从红色到蓝色的渐变,其方向是从小部件的左上角 (0, 0)
到右下角 (100, 100)。
注意事项
的颜色变化是沿着两个指定点之间的直线进行的。通过改变这些点的位置,你可以控制渐变的方向和长度。
方法的第一个参数是一个介于 0.0 和 1.0 之间的浮点数,表示颜色在渐变线上的位置。0.0 通常对应于起点,1.0 对应于终点。
你可以设置多个颜色停靠点来创建更复杂的渐变效果。例如,你可以在 0.0 处设置一种颜色,在 0.5
处设置另一种颜色,在 1.0 处再设置一种颜色。
使用 创建的 可以用于填充任何形状,包括矩形、椭圆、多边形等。
为了获取更好的视觉效果,可以启用 的抗锯齿选项( QPainter::Antialiasing )。
请注意,当窗口小部件的大小发生变化时,渐变的效果可能也会随之改变,除非你相应地调整渐变的起点和终点坐标或使用其他方法来适应大小变化。
-
-
-
- 径向渐变
-
-
是 Qt 框架中用于创建径向渐变的类。径向渐变是一种从中心点向外部辐射的颜色渐变,通常在中心点有一种颜色,而向外围渐渐变化为另一种颜色。这种渐变非常适合用于模拟光源、阴影或创建圆形的立体感。
基本用法
要使用 QRadialGradient ,你需要执行以下几个基本步骤:
-
-
-
-
-
创建 对象:指定渐变的中心点、半径以及焦点(可选)。 - 设置颜色停靠点:在径向渐变中定义颜色和对应的位置。
-
使用渐变创建 QBrush :利用 对象创建一个 QBrush ,然后用
-
-
-
-
它在
示例代码
中进行绘制。
以下是一个创建和使用 的示例代码:
|
在这个例子中, QRadialGradient 创建了一个从中心的黄色向外围的黑色渐变。渐变的中心和半径都设置在 (50, 50, 50)。
注意事项
方法的第一个参数是一个介于 0.0 和 1.0 之间的浮点数,表示颜色在径向渐变中的位置。0.0 通常对应于中心点,1.0 对应于边缘。
通过添加多个颜色停靠点,你可以创建更复杂的径向渐变效果。
方法允许你设置焦点位置,这是渐变颜色开始变化的点,可以与中心点不同。
使用 创建的 可以用于
填充任何形状,如矩形、椭圆、多边形等。为了获得更好的视觉效果,可以启用
的抗锯齿选项( QPainter::Antialiasing )。
当绘制较大区域时,可以通过调整渐变的半径和中心点来控制渐变效果的扩展。
非常适用于创建像按钮、指示灯或其他需要有深度感和立体感的界面元素。
-
-
-
- 圆锥形渐变
-
-
是 Qt 框架中用于创建圆锥形渐变的类。圆锥渐变是一种渐变效果,其中颜色沿着圆锥的轮廓变化,类似于旋转颜色轮。这种渐变以其中心点为基点,颜色沿圆周分布,可以创建出富有动感的视觉效果。
基本用法
要使用 QConicalGradient ,你通常需要做以下几个步骤:
-
-
-
-
-
创建 对象:指定渐变的中心点和起始角度。
-
-
-
-
-
-
-
-
- 设置颜色停靠点:为渐变添加不同的颜色和对应的位置(角度)。
-
使用渐变创建 QBrush :使用这个渐变对象来创建一个 QBrush ,然后应用到图。
-
-
-
示例代码
中进行绘
下面是一个如何创建和使用 的简单示例:
|
在这个例子中, QConicalGradient 被用来创建一个从红色到蓝色再回到红色的渐变。渐变的中心设置在点 (100, 100),并且从 0 度开始旋转。
注意事项
的颜色是沿着圆周分布的,其中 和你可以通过添加多个颜色停靠点来创建更复杂的渐变效果。
在圆周上是相同的位置。
在使用时,角度是按照顺时针方向测量的,起始点(0度)通常在三点钟方向。
|
非常适合用于创建旋转或动态效果的图形,例如加载指示器、进度条或任何需要圆周颜色变化的场景。
-
-
坐标转移
-
在 Qt 框架中, painter.translate(rect().center()) 这行代码的作用是移动 QPainter 的坐标系统
原点到当前绘制区域(即由
解释一下各个部分:
返回的矩形)的中心。
-
painter : 这是一个 QPainter 对象实例,用于在 Qt 窗口或者图像上进行绘制。 -
translate() : 这是 QPainter 类中的一个方法,用于改变坐标系统的原点。它接受一个 QPoint 或
QPointF 作为参数,这个点指定了新的原点位置。
-
rect() : 这通常是指一个控件(如 QWidget)的矩形区域,返回一个 QRect 或 QRectF 对象,表示该控件的大小和位置。 -
rect().center() : 这个方法返回当前矩形(即控件的区域)的中心点,是一个 QPoint 或
QPointF 对象。
总之, painter.translate(rect().center()) 这行代码将 QPainter 的绘图原点移动到控件的中心。这在进行中心对称绘制或者需要以控件中心为基准进行绘图时特别有用。
-
- 画雷达案例
|
|
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);
}
-
- 仪表表盘
- 初步完成
- 仪表表盘
|
|
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();//保存当前坐标位置,此时此刻是在原点,x在3点钟方向 painter.rotate(135);
for(int i=0;i<=50;i++){ if(i % 10 == 0){
-
-
- 稍微美化
-
稍微修改后,依然存在数字方向的问题!
|
}
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();//保存当前坐标位置,此时此刻是在原点,x在3点钟方向 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{//画短的刻度线
-
-
- 优化数字显示后代码整理
-
|
|
|
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,保留小数
//保存当前坐标位置,此时此刻是在原点,x在3点钟方向 painter.save(); painter.setPen(QPen(Qt::white,5));
//2. 设置第一个刻度的位置
painter.rotate(startAngle); for(int i=0;i<=60;i++){
if(i % 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;//QT中sin认的是弧度 int delY = qSin(qDegreesToRadians(210-angle*i)) * r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
painter.rotate(-120+angle*i);//angle=4,30*4=120的时候,实参是0,120
//写上文字
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){
|
-
-
- 画一个指针
-
在Qt中,使用 QPainter 来绘制一个类似指南针的指针,你通常会遵循以下步骤:
- 创建一个QWidget或QMainWindow的子类:这是你绘图的画布。
-
重写 paintEvent 方法:这个方法是Qt中绘制自定义图形的关键地方。 -
使用QPainter:在paintEvent 中创建一个QPainter 对象,并用它来绘制你的指针。 - 绘制指针:可以通过绘制一个线条或者一个具有特定形状的多边形来创建指针,比如一个三角形。
-
旋转指针:如果你想让指针能够像指南针那样旋转,你可以使用QPainter 的旋转功能。下面是一个简单的例子,展示如何在Qt中绘制一个静态的指针:
|
这个代码片段创建了一个自定义的QWidget,它在中间绘制了一个三角形作为指针。你可以通过添加更多的逻辑来使指针动态旋转,比如根据数据改变指针的方向。在实际应用中,指针的样式、大小和颜色都可以根据你的需要进行自定义。
-
-
- 内环
-
|
|
-
-
- 完结
-
|
|
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,保留小数
//保存当前坐标位置,此时此刻是在原点,x在3点钟方向 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(i % 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(i % 5 == 0){
//保存坐标系 painter.save();
//算出平移点,弧度=角度*3.1415/180
int delX = qCos( (210-angle*i)*M_PI/180) * r;//QT中sin认的是弧度 int delY = qSin(qDegreesToRadians(210-angle*i)) * r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
painter.rotate(-120+angle*i);//angle=4,30*4=120的时候,实参是0,120
//写上文字
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);
}
-
- 汽车表盘参考样式
|
P7 天气预报项目
-
- 项目概述
stylesheet界面美化 Json数据解析
HTTP通信
自定义控件绘制温度多控件
代码整合调试能力
|
-
- stylesheet样式
设置边框弧度
设置某方向边框弧度
|
设置背景颜色
|
父控件影响
父控件指定某类控件的样式,子控件都要遵守此样式进行显示,除非子控件内部有做相关修改
|
-
- 窗体无状态栏-关闭
设置无状态栏
|
设置左键弹窗关闭功能
|
|
-
- 窗口跟随移动
代码实现
|
实现的逻辑
|
-
- 天气预报数据接口
第一种:
|
数据返回:
{"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":"福州市气象台2024年01月 22日09时44分继续发布降温蓝色预警信号:受寒潮影响,今天到24日我市气温继续下降,日最低气温过程降幅可达9~12℃;今天到24日夜晨气温较低;过程最低气温晋安区山区可达-3~0℃,有结冰;其余地区1~3℃,有霜或霜冻;22日傍晚到23日上午部分乡镇将出现小雪或雨夹雪。请注意防范!(预警信息来源:国家预警信息发布中心)"},{"alarm_type":"降温","alarm_level":"蓝色","alarm_title":"福建省福州市发布降温蓝色预警","alarm_content":"福州市气象台2024年01月22日09时44分继续发布降温蓝色预警信 号:受寒潮影响,今天到24日我市气温继续下降,日最低气温过程降幅可达9~12℃;今天到24日夜晨气温较低;过程最低气温晋安区山区可达-3~0℃,有结冰;其余地区1~3℃,有霜或霜冻;22日傍晚到23日上午部分乡镇将出现小雪或雨夹雪。请注意防范!(预警信息来源:国家预警信息发布中心)"},
{"alarm_type":"降温","alarm_level":"蓝色","alarm_title":"福建省福州市发布降温蓝色预
警","alarm_content":"福州市气象台2024年01月21日09时29分发布降温蓝色预警信号:受寒潮影响,今天到23日我市气温持续下降,日最低气温过程降幅可达9~12℃,22~24日夜晨气温较低,过程日最低气温晋安区北部可达-3~0℃,有霜或霜冻和结冰;其余地区1~3℃,有霜或霜冻,请注意防范!(预警信息来源:国家预警信息发布中心)"},{"alarm_type":"降温","alarm_level":"蓝色","alarm_title":"福建省福州市发布降温蓝色预警","alarm_content":"福州市气象台2024年01月21日09时29分发布降温蓝色预警信号:受寒潮影响,今天到23日我市气温持续下降,日最低气温过程降幅可达9~12℃,22~24日夜晨气温较低,过程日最低气温晋安区北部可达-3~0℃,有霜或霜冻和结冰;其余地区1~3℃,有霜或霜冻,请注意防 范!(预警信息来源:国家预警信息发布中
心)"}],"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":"福州市气象台2024年01月22日09时44分继续发布降温蓝色预警信号:受寒潮影
响,今天到24日我市气温继续下降,日最低气温过程降幅可达9~12℃;今天到24日夜晨气温较低;过程最低气温晋安区山区可达-3~0℃,有结冰;其余地区1~3℃,有霜或霜冻;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大于15、PA+防晒护肤
品。"},{"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大于15、PA+防晒护肤品。"},{"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大于15、PA+防晒护肤
品。"},{"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大于15、PA+防晒护肤品。"},{"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级"},
-
- 软件开发网络通信架构
- BS架构/CS架构
- 软件开发网络通信架构
在计算机网络和软件开发中,CS架构(Client-Server Architecture,客户端-服务器架构)和BS架构
(Browser-Server Architecture,浏览器-服务器架构)是两种主要的应用程序架构。
CS架构(客户端-服务器架构)
CS架构是一种典型的两层结构,包括客户端和服务器两个部分。在这种架构中,客户端和服务器通过网络进行通信,每部分都有明确的职责。
-
-
-
- 客户端:
-
-
用户界面通常在客户端呈现。
可以是桌面应用程序、移动应用或专用软件。
负责向服务器发送请求,接收和处理服务器响应。
-
-
-
- 服务器:
-
-
管理数据和业务逻辑。
处理来自客户端的请求,并发送回响应。
通常承载在远程系统上,如数据库服务器、应用服务器等。
-
-
-
- 特点:
-
-
需要为每种操作系统或平台单独开发客户端。高效的数据处理和响应能力。
在客户端设备上占用资源(如内存和处理能力)。
BS架构(浏览器-服务器架构)
BS架构是一种基于Web的三层或多层架构,主要通过Web浏览器作为客户端访问服务器上的应用程序。
- 浏览器(客户端):
使用标准Web浏览器(如Chrome、Firefox等)作为客户端。
无需安装额外的软件,使用HTML、CSS和JavaScript显示内容。
- 服务器:
和CS架构中的服务器类似,处理业务逻辑和数据存储。通过Web服务(如HTTP服务器)提供页面和数据。
- 特点:
跨平台兼容性强,可以在任何支持Web浏览器的设备上运行。客户端无需安装专用软件,容易维护和更新。
可能依赖网络性能,因为所有操作都在服务器上进行。
对比
部署和维护:BS架构易于部署和维护,而CS架构通常需要在每个客户端单独安装和更新。
性能:CS架构可以更有效地利用客户端的计算资源,适合高性能要求的应用。BS架构依赖于服务器的性能和网络延迟。
安全性:CS架构中,数据经常在客户端和服务器之间传输,可能需要更复杂的安全措施。BS架构中,敏感数据主要存储在服务器端。
用户体验:CS架构通常能提供更丰富的用户界面和交互功能。BS架构的用户体验受限于Web技术的能力。
在实际应用中,选择哪种架构取决于具体的业务需求、目标用户群、性能要求以及开发和维护的成本。
-
-
- HTTP基本概念
-
HTTP(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是万维网
(WWW)的数据通信的基础。了解HTTP的基本概念对于理解现代网络通信至关重要。以下是HTTP的一些核心概念:
- 请求和响应
HTTP是一个基于请求-响应模式的协议。客户端(通常是Web浏览器)向服务器发送一个HTTP请求,然后服务器返回一个HTTP响应。请求包含请求的资源(如网页),而响应包含请求的资源的内容。
- HTTP方法
HTTP定义了一系列的方法来表明对资源的不同操作,最常用的包括:
GET: 用于请求资源。
POST: 用于提交数据给服务器(例如,表单数据)。
PUT: 用于上传文件或内容。
DELETE: 用于请求删除资源。
HEAD: 用于获取资源的元信息,而不是资源本身。
- 状态码
服务器对请求的响应中包含一个状态码,它表示请求的成功或失败,以及失败的原因。常见的状态码包括:
200 OK: 请求成功。
404 Not Found: 请求的资源未找到。
500 Internal Server Error: 服务器内部错误。
301 Moved Permanently: 请求的资源已永久移动到新位置。
- URL(统一资源定位符)
URL是Web上资源的地址。它指定了资源的位置以及用于访问资源的协议(例如,http://)。
- HTTP头
HTTP请求和响应包含头部信息,这些信息包括元数据,如内容类型、内容长度、服务器信息、客户端信息等。例如, Content-Type 头部指示响应中的媒体类型(如text/html,application/json)。
- 无状态协议
HTTP是一个无状态协议,这意味着服务器不会保留任何请求的数据(状态)。然而,通过使用如 Cookies这样的机制,可以在多个请求之间维持状态。
- 安全性(HTTPS)
HTTPS是HTTP的安全版本,它在HTTP和TCP层之间增加了一个加密层(通常是SSL/TLS)。这提供了数据传输的加密和更好的安全性。
- RESTful API
RESTful是一种使用HTTP协议的Web服务设计风格,它利用HTTP的方法来实现API的不同操作。在 RESTful架构中,每个URL代表一个资源,并使用HTTP的方法(如GET, POST)来处理这些资源。
- Session和Cookies
由于HTTP本身是无状态的,Cookies和会话(Session)被用来在多个请求之间存储用户数据,从而为用户提供连贯的体验。
这些概念构成了HTTP的基础,是理解和使用HTTP协议的关键。每个概念都有它的具体细节和使用场景,了解这些有助于更好地在网络应用开发中应用HTTP。
-
- QT的HTTP编程
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响应时被调用。
注意事项
-
异步处理: QNetworkAccessManager 的请求是异步的。这意味着get 方法会立即返回,而HTTP响应将在稍后通过信号处理。 -
错误处理: 应该检查QNetworkReply 对象是否有错误,并相应地处理。 -
内存管理: QNetworkReply 对象需要被正确地管理,以避免内存泄漏。通常情况下,使用
QObject::deleteLater 来安排删除它是一个好方法。
-
- JSON数据
- 概述
- JSON数据
JSON(JavaScript 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处理的类,部分Swift和Objective-C标准库中 |
-
-
- QT生成JSON数据
-
在Qt中生成JSON数据并将其保存到文件的一个基本示例涉及使用 QJsonDocument 、 QJsonObject 和
QJsonArray 类。以下是创建一个简单JSON对象并将其保存到文件的示例代码。
|
说明
-
-
-
-
创建JSON对象:使用QJsonObject 来构建JSON对象,并使用键值对填充数据。 -
创建JSON数组:使用QJsonArray 来创建一个数组,并添加元素。 - 组合JSON结构:将JSON数组添加到JSON对象中。
-
生成JSON文档:通过QJsonDocument 来处理JSON数据,可以选择格式化(缩进)或压缩形式。 -
保存到文件:创建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;
//通过QJsonDocument把JSON数据转换成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;
}
-
-
- QT解析JSON数据
-
在Qt中解析JSON数据通常涉及到使用 QJsonDocument 、 QJsonObject 和QJsonArray 类。这些类提供了处理JSON数据的必要工具,使您能够从JSON字符串中提取信息、遍历JSON对象或数组,并访问具体的数据项。以下是一个基本的示例,展示了如何在Qt中解析JSON字符串。
示例:解析JSON字符串
假设您有一个JSON字符串,例如:
|
以下是如何在Qt中解析这个JSON字符串的步骤:
|
说明
-
-
-
-
字符串转换为 QJsonDocument :使用QJsonDocument::fromJson 方法将JSON字符串转换为
-
-
-
QJsonDocument 对象。
-
-
-
-
提取 QJsonObject :如果QJsonDocument 包含一个JSON对象,使用 object() 方法获取它。 -
访问对象数据:使用键(如"name" 、"age" )访问QJsonObject 中的数据。 -
处理数组:如果对象包含一个数组,使用QJsonArray 来遍历数组中的元素。
-
-
-
这个示例提供了一个基础框架,用于在Qt中解析和处理JSON数据。您可以根据实际需要调整这个过程,以适应不同的JSON结构和数据类型。
在Qt中,如果你想要将JSON数据解析到一个 QMap 中,你可以遍历JSON对象的所有键值对,并将它们添加到QMap 里。这个方法特别适合于当你的JSON对象是一个简单的键值对集合时。以下是一个如何实现这一点的示例。
示例:将JSON数据解析到QMap中
假设你有以下JSON数据:
|
以下是如何将这些数据解析到QMap<QString, QString> 中的步骤:
说明
-
从JSON字符串创建 QJsonDocument :使用QJsonDocument::fromJson 来解析JSON字符串。 -
创建 QMap :定义一个QMap<QString, QString> 来存储键值对。 -
遍历JSON对象:使用keys() 方法获取所有键,然后遍历这些键,将对应的值添加到QMap 中。 -
打印 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){
//QJsonValue的type函数返回数据类型,根据不同的数据类型处理数据
// 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开发环境
-
- 安装Ubutnu22
- 下载和安装Vmware
- 安装Ubutnu22
使用我们提供的安装包或者使用如下地址进行下载
官方下载网址: https://download3.vmware.com/software/WKST-1700-WIN/VMware-workstation-fu ll-17.0.0-20800274.exe
支持正版
如果你的电脑已经安装低版本的VMware,千万不要卸载,直接覆盖安装,更新到17的版本
|
-
-
- 下载和安装Ubuntu22
-
使用我们提供的镜像
|
安装的过程看视频教程,安装之后打开如下图所示
|
-
-
- 常用功能配置
-
先掌握如下命令
查看命令所在目录
查看当前目录下的所有文件和文件夹创建文件夹
复制拷贝文件 复制拷贝文件夹
删除文件 rm 文件名 ,如果删除文件夹 加 -rf选项
特别有用!!善于使用tab键,能自动补全文件名或者命令名,不会造成输入错误
网络配置
正常电脑就一台虚拟机,通过以上安装后,就能正常上网
多虚拟机情况,桥接模式冲突,配置不稳定,选择NAT共享主机网络上网获取IP地址通过命令 ip addr
共享文件配置
windows需要传文件给虚拟机 可以通过共享文件夹的方式可以通过网络的方式
编译环境
默认情况,系统不带编译环境,通过以下命令安装环境
|
安装VMware Tool
和windows系统的文本复制黏贴打通共享文件夹
|
配置支持ubuntu远程登录
|
|
-
- 安装Ubuntu环境下的QT
- 下载安装UbuntuQT
- 安装Ubuntu环境下的QT
下载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 & 这里的“&”符号代表后台运行,不占用控制命令终端
|
-
-
- Ubuntu中文支持
-
配置Ubuntu的中文环境
配置apt下载的服务器源,选择阿里
|
更新源 sudo apt-get update
|
在setting设置那边打开Region&Language设置
选择语言安装,在窗口中选择Chinese(simplified)
|
勾选Chinese,重启
配置Ubuntu支持中文输入
安装拼音输入法
sudo apt-get install fcitx-sunpinyin
设置输入法
点击应用到整个系统,关闭,重启
|
拷贝我分享的so文件到QT相关路径,让QT支持输入中文!非常重要!!!用系统自带的不行。
|
P9 加餐课