5.5 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 状态类别
功能
API/方法
描述
TCPServer
监听
bool listen(const QHostAddress
&address, quint16 port)
在指定的 IP 地址和端口上开
始监听传入的连接。
连接
void close()
停止服务器监听传入的连
接。
5.6 项目总结
TCPServer类关于监听,连接,发送,接受的API
TCPServer在网络通信中常用的信号
TCPScoket在QT实现Socket常用的API
TCPScoket在QT实现Socket常用的信号
EditText的内容读取方法,内容写入方法,在特定行写入特点颜色的方法
TCPServer 、 TCPScoket 和 EditText 的信息整合到一个表格中:
ui->pushButtonCon->setEnabled(true);
ui->pushButtonDiscon->setEnabled(false);
ui->lineEditAddr->setEnabled(true);
ui->lineEditPort->setEnabled(true);
}
// 当点击连接按钮时调用
void MainWindow::on_pushButtonCon_clicked()
{
tcpSocket->connectToHost(ui->lineEditAddr->text().toUtf8(),
ui->lineEditPort->text().toInt()); // 连接到指定的主机
和端口
if(tcpSocket->state() == QTcpSocket::ConnectedState){
ui->textBrowser->append("客户端:连接服务端成功!");
}
// 更新 UI 状态
ui->pushButtonCon->setEnabled(false);
ui->pushButtonDiscon->setEnabled(true);
ui->lineEditAddr->setEnabled(false);
ui->lineEditPort->setEnabled(false);
}
// 设置文本颜色的函数
void MainWindow::setTextColor(int r, int g, int b)
{
QTextCharFormat textFormat;
textFormat.setForeground(QBrush(QColor(r, g, b))); // 根据提供的 RGB 值设置颜色
// 应用格式到光标
cursor.setCharFormat(textFormat);
}类别
功能
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 自定义控件
6.1 QPaintEvent绘图事件
QPaintEvent 是 Qt 框架中一个重要的事件类,专门用于处理绘图事件。当 Qt 视图组件需要重绘自己
的一部分时,就会产生 QPaintEvent 事件。这通常发生在以下几种情况:
1. 窗口第一次显示时:当窗口或控件第一次出现在屏幕上时,系统会生成一个 QPaintEvent 事件,
通知窗口进行自身的绘制。
2. 窗口大小改变时:当用户改变窗口的大小时,窗口的内容通常需要重新绘制以适应新的尺寸。
3. 窗口部分被遮挡后又重新显示时:如果窗口被其他窗口遮挡,然后又重新露出来,被遮挡的部分通
常需要重新绘制。4. 手动请求重绘:通过调用 QWidget 的 update() 或 repaint() 方法,可以手动触发重绘事件。
在 Qt 应用程序中,通常通过重写 QWidget 的 paintEvent(QPaintEvent *) 方法来处理绘制逻辑。
例如:
在 paintEvent 方法中,您可以创建一个 QPainter 对象并使用它来执行绘制操作。 QPainter 可以绘
制各种基本图形,如线条、矩形、椭圆等,还可以绘制文本和图像。重写 paintEvent 是在 Qt 中进行
自定义绘制的标准做法。
6.2 QPainter画家
6.2.1 概述
QPainter 是 Qt 库中用于在屏幕上进行绘画的类。它提供了各种绘制功能,比如画线、画图形、画文本
等。
以下是一些基本的用法示例:
1. 初始化 QPainter:首先,您需要一个 QPaintDevice ,比如一个 QWidget 或 QPixmap ,然后使
用它来初始化 QPainter 对象。
设置画笔和画刷:您可以设置画笔(用于描边)和画刷(用于填充)的颜色、样式等。
绘制图形:使用 QPainter 的方法来绘制线条、矩形、圆形、文本等。
结束绘制:完成绘制后, QPainter 对象会在其析构函数中自动结束绘制。
请注意, QPainter 的使用依赖于 Qt 的事件循环,因此通常在 QWidget 的 paintEvent 或者类似的事
件处理函数中使用它。如果您在 Qt 应用程序中使用 QPainter ,请确保您遵循 Qt 的事件驱动机制。
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
// 绘制逻辑
}
};
QPainter painter(this); // 假设在 QWidget 的子类中
painter.setPen(Qt::blue); // 设置画笔颜色为蓝色
painter.setBrush(Qt::yellow); // 设置画刷颜色为黄色
painter.drawLine(10, 10, 100, 100); // 画线
painter.drawRect(10, 10, 100, 100); // 画矩形
painter.drawText(10, 10, "Hello, Qt!"); // 画文本6.2.2 渐变色
6.2.2.1 线性渐变
QLinearGradient 是 Qt 框架中用于创建线性渐变的类。线性渐变是一种从一个颜色平滑过渡到另一个
颜色的效果,其变化沿着两个点之间的直线进行。这种渐变在图形用户界面设计中非常常见,用于添加
深度、立体感或动态效果。
基本用法
要使用 QLinearGradient ,你需要执行以下几个基本步骤:
1. 创建 QLinearGradient 对象:指定渐变的起点和终点坐标。
2. 设置颜色停靠点:在渐变线上定义颜色和相应的位置。
3. 使用渐变创建 QBrush :用 QLinearGradient 对象来创建一个 QBrush ,然后用它在 QPainter
中进行绘制。
示例代码
以下是一个创建和使用 QLinearGradient 的示例代码:
在这个例子中, QLinearGradient 创建了一个从红色到蓝色的渐变,其方向是从小部件的左上角 (0, 0)
到右下角 (100, 100)。
注意事项
QLinearGradient 的颜色变化是沿着两个指定点之间的直线进行的。通过改变这些点的位置,你
可以控制渐变的方向和长度。
setColorAt() 方法的第一个参数是一个介于 0.0 和 1.0 之间的浮点数,表示颜色在渐变线上的位
置。0.0 通常对应于起点,1.0 对应于终点。
你可以设置多个颜色停靠点来创建更复杂的渐变效果。例如,你可以在 0.0 处设置一种颜色,在 0.5
处设置另一种颜色,在 1.0 处再设置一种颜色。
使用 QLinearGradient 创建的 QBrush 可以用于填充任何形状,包括矩形、椭圆、多边形等。
#include <QPainter>
#include <QLinearGradient>
void MyWidget::paintEvent(QPaintEvent *) {
// 创建一个 QLinearGradient 对象
QLinearGradient linearGradient(0, 0, 100, 100); // 起点(0, 0) 终点(100, 100)
// 设置颜色停靠点
linearGradient.setColorAt(0.0, Qt::red); // 起点颜色
linearGradient.setColorAt(1.0, Qt::blue); // 终点颜色
// 使用这个渐变创建 QBrush
QBrush brush(linearGradient);
// 使用 QBrush 进行绘图
QPainter painter(this);
painter.setBrush(brush);
painter.setPen(Qt::NoPen); // 无边框
painter.drawRect(this->rect()); // 绘制矩形覆盖整个小部件
}为了获取更好的视觉效果,可以启用 QPainter 的抗锯齿选项( QPainter::Antialiasing )。
请注意,当窗口小部件的大小发生变化时,渐变的效果可能也会随之改变,除非你相应地调整渐变
的起点和终点坐标或使用其他方法来适应大小变化。
6.2.2.2 径向渐变
QRadialGradient 是 Qt 框架中用于创建径向渐变的类。径向渐变是一种从中心点向外部辐射的颜色渐
变,通常在中心点有一种颜色,而向外围渐渐变化为另一种颜色。这种渐变非常适合用于模拟光源、阴
影或创建圆形的立体感。
基本用法
要使用 QRadialGradient ,你需要执行以下几个基本步骤:
1. 创建 QRadialGradient 对象:指定渐变的中心点、半径以及焦点(可选)。
2. 设置颜色停靠点:在径向渐变中定义颜色和对应的位置。
3. 使用渐变创建 QBrush :利用 QRadialGradient 对象创建一个 QBrush ,然后用
它在 QPainter 中进行绘制。
示例代码
以下是一个创建和使用 QRadialGradient 的示例代码:
在这个例子中, QRadialGradient 创建了一个从中心的黄色向外围的黑色渐变。渐变的中心和半径都设
置在 (50, 50, 50)。
注意事项
setColorAt() 方法的第一个参数是一个介于 0.0 和 1.0 之间的浮点数,表示颜色在径向渐变中的
位置。0.0 通常对应于中心点,1.0 对应于边缘。
通过添加多个颜色停靠点,你可以创建更复杂的径向渐变效果。
#include <QPainter>
#include <QRadialGradient>
void MyWidget::paintEvent(QPaintEvent *) {
// 创建一个 QRadialGradient 对象
QRadialGradient radialGradient(50, 50, 50); // 中心和半径 (50, 50, 50)
// 可选:设置焦点
// radialGradient.setFocalPoint(30, 30);
// 设置颜色停靠点
radialGradient.setColorAt(0.0, Qt::yellow); // 中心颜色
radialGradient.setColorAt(1.0, Qt::black); // 外围颜色
// 使用这个渐变创建 QBrush
QBrush brush(radialGradient);
// 使用 QBrush 进行绘图
QPainter painter(this);
painter.setBrush(brush);
painter.setPen(Qt::NoPen); // 无边框
painter.drawRect(this->rect()); // 绘制矩形覆盖整个小部件
}setFocalPoint() 方法允许你设置焦点位置,这是渐变颜色开始变化的点,可以与中心点不同。
使用 QRadialGradient 创建的 QBrush 可以用于
填充任何形状,如矩形、椭圆、多边形等。
为了获得更好的视觉效果,可以启用 QPainter 的抗锯齿选项( QPainter::Antialiasing )。
当绘制较大区域时,可以通过调整渐变的半径和中心点来控制渐变效果的扩展。
QRadialGradient 非常适用于创建像按钮、指示灯或其他需要有深度感和立体感的界面元素。
6.2.2.3 圆锥形渐变
QConicalGradient 是 Qt 框架中用于创建圆锥形渐变的类。圆锥渐变是一种渐变效果,其中颜色沿着
圆锥的轮廓变化,类似于旋转颜色轮。这种渐变以其中心点为基点,颜色沿圆周分布,可以创建出富有
动感的视觉效果。
基本用法
要使用 QConicalGradient ,你通常需要做以下几个步骤:
1. 创建 QConicalGradient 对象:指定渐变的中心点和起始角度。
2. 设置颜色停靠点:为渐变添加不同的颜色和对应的位置(角度)。
3. 使用渐变创建 QBrush :使用这个渐变对象来创建一个 QBrush ,然后应用到 QPainter 中进行绘
图。
示例代码
下面是一个如何创建和使用 QConicalGradient 的简单示例:
在这个例子中, QConicalGradient 被用来创建一个从红色到蓝色再回到红色的渐变。渐变的中心设置
在点 (100, 100),并且从 0 度开始旋转。
注意事项
#include <QPainter>
#include <QConicalGradient>
void MyWidget::paintEvent(QPaintEvent *) {
// 创建一个 QConicalGradient 对象
QConicalGradient conicalGradient(100, 100, 0); // 中心点 (100, 100),起始角度 0
// 添加颜色停靠点
conicalGradient.setColorAt(0.0, Qt::red);
conicalGradient.setColorAt(0.5, Qt::blue);
conicalGradient.setColorAt(1.0, Qt::red);
// 使用这个渐变创建 QBrush
QBrush brush(conicalGradient);
// 使用 QBrush 进行绘图
QPainter painter(this);
painter.setBrush(brush);
painter.setPen(Qt::NoPen); // 无边框
painter.drawRect(this->rect()); // 绘制矩形覆盖整个小部件
}QConicalGradient 的颜色是沿着圆周分布的,其中 0.0 和 1.0 在圆周上是相同的位置。
你可以通过添加多个颜色停靠点来创建更复杂的渐变效果。
QConicalGradient
在使用时,角度是按照顺时针方向测量的,起始点(0度)通常在三点钟方向。
为了达到最佳的渲染效果,可以启用 QPainter 的抗锯齿渲染提示
( QPainter::Antialiasing )。
QConicalGradient 非常适合用于创建旋转或动态效果的图形,例如加载指示器、进度条或任何需
要圆周颜色变化的场景。
6.3 坐标转移
在 Qt 框架中, painter.translate(rect().center()) 这行代码的作用是移动 QPainter 的坐标系统
原点到当前绘制区域(即由 rect() 返回的矩形)的中心。
解释一下各个部分:
1. painter : 这是一个 QPainter 对象实例,用于在 Qt 窗口或者图像上进行绘制。
2. translate() : 这是 QPainter 类中的一个方法,用于改变坐标系统的原点。它接受一个 QPoint 或
QPointF 作为参数,这个点指定了新的原点位置。
3. rect() : 这通常是指一个控件(如 QWidget)的矩形区域,返回一个 QRect 或 QRectF 对象,表
示该控件的大小和位置。
4. rect().center() : 这个方法返回当前矩形(即控件的区域)的中心点,是一个 QPoint 或
QPointF 对象。
总之, painter.translate(rect().center()) 这行代码将 QPainter 的绘图原点移动到控件的中心。
这在进行中心对称绘制或者需要以控件中心为基准进行绘图时特别有用。6.4 画雷达案例
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
connect(timer, &QTimer::timeout,[=](){
//不断变化扇形的启动位置
startAngle += 30;
if(startAngle >= 360){
startAngle = 0;
}
update();
});
timer->setInterval(100);
timer->start();
}
Widget::~Widget()
{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);
}6.5仪表表盘
6.5.1 初步完成
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QDebug>
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
currentValue = 0;
connect(timer, &QTimer::timeout,[=](){
if(mark == 0){
currentValue++;
if(currentValue >= 51){
mark = 1;
}
}
if(mark == 1){
currentValue--;
if(currentValue == 0){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){6.5.2 稍微美化
稍微修改后,依然存在数字方向的问题!
//画字
if(135 + angle * i < 270){
painter.rotate(180);
painter.drawText(-(height()/2 - 20 - 10), 8,QString::number(i));
painter.rotate(-180);
}else{
painter.drawText(height()/2 - 20 - 30, 8,QString::number(i));
}
//画长的刻度线
painter.drawLine(height()/2 - 20, 0, height()/2 - 3 ,0);
}else{//画短的刻度线
painter.drawLine(height()/2 - 8, 0, height()/2 - 3 ,0);
}
//画完后旋转
painter.rotate(angle);
}
//画指针,线
//坐标轴先回到原点
painter.restore();
painter.save();
painter.rotate(135 + angle * currentValue);
painter.drawLine(60,0,height()/2 - 20- 10 - 28,0);
//画扇形
painter.restore();
QRect rentangle(-height()/2+58,-height()/2+58,height()-116,height()-116);
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(235,152,50,150));
painter.drawPie(rentangle,(360-135)*16,-angle*currentValue*16);//angle前面取
负数,为了让它顺时针方向画
}#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QDebug>
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
currentValue = 0;
connect(timer, &QTimer::timeout,[=](){
if(mark == 0){
currentValue++;
if(currentValue >= 60){
mark = 1;
}
}
if(mark == 1){
currentValue--;
if(currentValue == 0){
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());
// 画大圆
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{//画短的刻度线6.5.3 优化数字显示后代码整理
painter.drawLine(height()/2 - 8, 0, height()/2 - 3 ,0);
}
//画完后旋转
painter.rotate(angle);
}
//画指针,线
//坐标轴先回到原点
painter.restore();
painter.save();
painter.rotate(150 + angle * currentValue);
painter.drawLine(60,0,height()/2 - 20- 10 - 28,0);
//画扇形
painter.restore();
QRect rentangle(-height()/2,-height()/2,height(),height());
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(235,152,50,150));
painter.drawPie(rentangle,(360-150)*16,-angle*currentValue*16);//angle前面取
负数,为了让它顺时针方向画
}
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
void paintEvent(QPaintEvent *event) override;
private:
Ui::Widget *ui;
QTimer *timer;
int currentValue;
int mark = 0;
int startAngle;
double angle;
void initCanvas(QPainter& painter);
void drawMiddleCircle(QPainter& painter,int radius);
void drawCurrentSpeed(QPainter& painter);
void drawScale(QPainter& painter,int radius);
void drawScaleText(QPainter& painter,int radius);
void drawPointLine(QPainter &painter,int lenth);
void drawSpeedPie(QPainter& painter,int radius);
void startSpeed();
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QDebug>
#include <QTimer>
#include <QtMath>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
startAngle = 150;
startSpeed();
}
Widget::~Widget()
{
delete ui;
}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){currentValue--;
if(currentValue == 0){
mark = 0;
}
}
update();
});
timer->start(50);
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//初始化画布
initCanvas(painter);
//画小圆
drawMiddleCircle(painter,60);
//画当前速度
drawCurrentSpeed(painter);
//画刻度
drawScale(painter, height()/2);
//画刻度文字
drawScaleText(painter, height()/2);
//指针
drawPointLine(painter, height()/2-58);
//画扇形
drawSpeedPie(painter, height()/2);
}6.5.4 画一个指针
在Qt中,使用 QPainter 来绘制一个类似指南针的指针,你通常会遵循以下步骤:
1. 创建一个QWidget或QMainWindow的子类:这是你绘图的画布。
2. 重写 paintEvent 方法:这个方法是Qt中绘制自定义图形的关键地方。
3. 使用QPainter:在 paintEvent 中创建一个 QPainter 对象,并用它来绘制你的指针。
4. 绘制指针:可以通过绘制一个线条或者一个具有特定形状的多边形来创建指针,比如一个三角形。
5. 旋转指针:如果你想让指针能够像指南针那样旋转,你可以使用 QPainter 的旋转功能。
下面是一个简单的例子,展示如何在Qt中绘制一个静态的指针:
这个代码片段创建了一个自定义的QWidget,它在中间绘制了一个三角形作为指针。你可以通过添加更
多的逻辑来使指针动态旋转,比如根据数据改变指针的方向。在实际应用中,指针的样式、大小和颜色
都可以根据你的需要进行自定义。
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setBrush(Qt::red);
painter.translate(rect().center());
static const QPointF points[3] = {
QPointF(-10.0, 0),
QPointF(0, -200.0),
QPointF(10.0, 0),
};
painter.drawPolygon(points, 4);
}6.5.5 内环
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::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//初始化画布
initCanvas(painter);
//画小圆
drawMiddleCircle(painter,60);
//画刻度
drawScale(painter, height()/2);
//画刻度文字
drawScaleText(painter, height()/2);
//指针
drawPointLine(painter, height()/2-58);
//画扇形6.5.6 完结
drawSpeedPie(painter, height()/2);
//画渐变内圈圆
drawEllipseInnerShine(painter,110);
//画黑色内圈
drawEllipseInnerBlack(painter, 80);
//画当前速度
drawCurrentSpeed(painter);
}
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
void paintEvent(QPaintEvent *event) override;private:
Ui::Widget *ui;
QTimer *timer;
int currentValue;
int mark = 0;
int startAngle;
double angle;
void initCanvas(QPainter& painter);
void drawMiddleCircle(QPainter& painter,int radius);
void drawCurrentSpeed(QPainter& painter);
void drawScale(QPainter& painter,int radius);
void drawScaleText(QPainter& painter,int radius);
void drawPointLine(QPainter &painter,int lenth);
void drawSpeedPie(QPainter& painter,int radius);
void startSpeed();
void drawEllipseInnerBlack(QPainter& painter,int radius);
void drawEllipseInnerShine(QPainter& painter,int radius);
void drawEllipseOutterShine(QPainter& painter,int radius);
void drawLogo(QPainter& painter,int radius);
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QDebug>
#include <QTimer>
#include <QtMath>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setFixedSize(800,600);
startAngle = 150;
startSpeed();
}
Widget::~Widget()
{
delete ui;
}
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.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);
}6.6 汽车表盘参考样式P7 天气预报项目
7.1项目概述
stylesheet界面美化
Json数据解析
HTTP通信
自定义控件绘制温度
多控件
代码整合调试能力
7.2 stylesheet样式
设置边框弧度设置某方向边框弧度
设置背景颜色
父控件影响
父控件指定某类控件的样式,子控件都要遵守此样式进行显示,除非子控件内部有做相关修改
7.3 窗体无状态栏-关闭
设置无状态栏
设置左键弹窗关闭功能
7.4 窗口跟随移动
代码实现
border-radius: 4px;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
background-color: rgba(60, 60, 60, 100);
QLabel {
background-color: rgba(0, 200, 200, 200);
border-radius: 4px;
}
setWindowFlag(Qt::FramelessWindowHint);
menuQuit = new QMenu(this);
QAction *closeAct = new QAction(QIcon(":/res/close.png"), tr("退出"), this);
menuQuit->addAction(closeAct);
connect(menuQuit,&QMenu::triggered,this,[=]{
this->close();
});
void Widget::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::RightButton){
//qDebug() << "right Mouse clicked!";
menuQuit->exec(QCursor::pos());
}
}
void Widget::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::RightButton){实现的逻辑
7.5 天气预报数据接口
第一种:
数据返回:
//qDebug() << "right Mouse clicked!";
menuQuit->exec(QCursor::pos());
}
//鼠标当前位置 event->globalPos();,
//窗口当前位置 this->pos()窗口新位置event->globalPos() - mOffset
if(event->button() == Qt::LeftButton){
// qDebug() << event->globalPos() << this->pos();
mOffset = event->globalPos()-this->pos();
}
}
//鼠标左键按下后的移动,导致这个事件被调用,设置窗口的新位置
void Widget::mouseMoveEvent(QMouseEvent *event)
{
this->move(event->globalPos() - mOffset);
}
http://t.weather.itboy.net/api/weather/city/101010100{"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":"愿你拥有比阳光明媚的心情"}}}第二种:
http://v1.yiketianqi.com/api?
unescape=1&version=v61&appid=26371314&appsecret=qOhoD413
数据返回
{"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日上午部分乡镇将出现小雪或雨夹雪。请注意防范!(预警信息来源:国家预警信息发布中
心)"},"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","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":"不需要打开"}}
http://v1.yiketianqi.com/api?
unescape=1&version=v63&appid=26371314&appsecret=qOhoD413 //带小时{"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天
http://v1.yiketianqi.com/api?
unescape=1&version=v9&appid=26371314&appsecret=qOhoD413
数据返回{"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级"},7.6 软件开发网络通信架构
7.6.1 BS架构/CS架构
在计算机网络和软件开发中,CS架构(Client-Server Architecture,客户端-服务器架构)和BS架构
(Browser-Server Architecture,浏览器-服务器架构)是两种主要的应用程序架构。
CS架构(客户端-服务器架构)
CS架构是一种典型的两层结构,包括客户端和服务器两个部分。在这种架构中,客户端和服务器通过网
络进行通信,每部分都有明确的职责。
1. 客户端:
用户界面通常在客户端呈现。
可以是桌面应用程序、移动应用或专用软件。
负责向服务器发送请求,接收和处理服务器响应。
2. 服务器:
管理数据和业务逻辑。
处理来自客户端的请求,并发送回响应。
通常承载在远程系统上,如数据库服务器、应用服务器等。
3. 特点:
需要为每种操作系统或平台单独开发客户端。
高效的数据处理和响应能力。
在客户端设备上占用资源(如内存和处理能力)。
BS架构(浏览器-服务器架构)
BS架构是一种基于Web的三层或多层架构,主要通过Web浏览器作为客户端访问服务器上的应用程序。
1. 浏览器(客户端):
使用标准Web浏览器(如Chrome、Firefox等)作为客户端。
{"hours":"20时","wea":"多云","wea_img":"yun","tem":"14","win":"东风","win_speed":"
<3级"},{"hours":"23时","wea":"多云","wea_img":"yun","tem":"12","win":"西
风","win_speed":"<3级"},{"hours":"02时","wea":"多
云","wea_img":"yun","tem":"10","win":"北风","win_speed":"<3级"},{"hours":"05
时","wea":"多云","wea_img":"yun","tem":"10","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":"中等"}],"aqi":
{"update_time":"10:47","cityid":"101230101","city":"","cityEn":"","country":"","c
ountryEn":"","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":"不需要打开"}}无需安装额外的软件,使用HTML、CSS和JavaScript显示内容。
2. 服务器:
和CS架构中的服务器类似,处理业务逻辑和数据存储。
通过Web服务(如HTTP服务器)提供页面和数据。
3. 特点:
跨平台兼容性强,可以在任何支持Web浏览器的设备上运行。
客户端无需安装专用软件,容易维护和更新。
可能依赖网络性能,因为所有操作都在服务器上进行。
对比
部署和维护:BS架构易于部署和维护,而CS架构通常需要在每个客户端单独安装和更新。
性能:CS架构可以更有效地利用客户端的计算资源,适合高性能要求的应用。BS架构依赖于服务器
的性能和网络延迟。
安全性:CS架构中,数据经常在客户端和服务器之间传输,可能需要更复杂的安全措施。BS架构
中,敏感数据主要存储在服务器端。
用户体验:CS架构通常能提供更丰富的用户界面和交互功能。BS架构的用户体验受限于Web技术的
能力。
在实际应用中,选择哪种架构取决于具体的业务需求、目标用户群、性能要求以及开发和维护的成本。
7.6.2 HTTP基本概念
HTTP(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是万维网
(WWW)的数据通信的基础。了解HTTP的基本概念对于理解现代网络通信至关重要。以下是HTTP的一
些核心概念:
1. 请求和响应
HTTP是一个基于请求-响应模式的协议。客户端(通常是Web浏览器)向服务器发送一个HTTP请求,然
后服务器返回一个HTTP响应。请求包含请求的资源(如网页),而响应包含请求的资源的内容。
2. HTTP方法
HTTP定义了一系列的方法来表明对资源的不同操作,最常用的包括:
GET: 用于请求资源。
POST: 用于提交数据给服务器(例如,表单数据)。
PUT: 用于上传文件或内容。
DELETE: 用于请求删除资源。
HEAD: 用于获取资源的元信息,而不是资源本身。
3. 状态码
服务器对请求的响应中包含一个状态码,它表示请求的成功或失败,以及失败的原因。常见的状态码包
括:
200 OK: 请求成功。
404 Not Found: 请求的资源未找到。
500 Internal Server Error: 服务器内部错误。301 Moved Permanently: 请求的资源已永久移动到新位置。
4. URL(统一资源定位符)
URL是Web上资源的地址。它指定了资源的位置以及用于访问资源的协议(例如,http://)。
5. HTTP头
HTTP请求和响应包含头部信息,这些信息包括元数据,如内容类型、内容长度、服务器信息、客户端信
息等。例如, Content-Type 头部指示响应中的媒体类型(如text/html,application/json)。
6. 无状态协议
HTTP是一个无状态协议,这意味着服务器不会保留任何请求的数据(状态)。然而,通过使用如
Cookies这样的机制,可以在多个请求之间维持状态。
7. 安全性(HTTPS)
HTTPS是HTTP的安全版本,它在HTTP和TCP层之间增加了一个加密层(通常是SSL/TLS)。这提供了数
据传输的加密和更好的安全性。
8. RESTful API
RESTful是一种使用HTTP协议的Web服务设计风格,它利用HTTP的方法来实现API的不同操作。在
RESTful架构中,每个URL代表一个资源,并使用HTTP的方法(如GET, POST)来处理这些资源。
9. Session和Cookies
由于HTTP本身是无状态的,Cookies和会话(Session)被用来在多个请求之间存储用户数据,从而为用
户提供连贯的体验。
这些概念构成了HTTP的基础,是理解和使用HTTP协议的关键。每个概念都有它的具体细节和使用场景,
了解这些有助于更好地在网络应用开发中应用HTTP。
7.7 QT的HTTP编程
Qt中的HTTP编程主要涉及使用Qt的网络模块来进行HTTP请求和处理HTTP响应。Qt提供了一系列类来处
理网络通信,其中最常用的类是 QNetworkAccessManager 、 QNetworkRequest 、 QNetworkReply 以
及相关的支持类。
以下是一个基本的HTTP编程示例,展示了如何使用Qt发送一个简单的HTTP GET请求并处理响应:
步骤 1: 包含必要的头文件
步骤 2: 发送HTTP请求
创建一个 QNetworkAccessManager 对象,并使用它发送HTTP请求。 QNetworkAccessManager 对象会
异步地处理请求,并返回一个 QNetworkReply 对象。
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QObject>
#include <QDebug>
int main(int argc, char *argv[])原因
描述
易于阅读和编写
JSON的结构简单、清晰,对人类来说易于阅读和编写。
轻量级数据格式
相较于XML等标记语言,JSON更轻量,使用更少的符号,数据体积更小。
易于解析和生成
大多数编程语言都提供了解析和生成JSON的内置支持或库。
跨语言支持
JSON是独立于语言的,被广泛支持和使用在多种编程语言中。
在这个例子中,我们使用 QNetworkAccessManager 的 get 方法发送了一个HTTP GET请求到"http://exa
mple.com"。然后,我们连接了 QNetworkReply 对象的 finished 信号到一个lambda函数,该函数在收
到HTTP响应时被调用。
注意事项
1. 异步处理: QNetworkAccessManager 的请求是异步的。这意味着 get 方法会立即返回,而HTTP响
应将在稍后通过信号处理。
2. 错误处理: 应该检查 QNetworkReply 对象是否有错误,并相应地处理。
3. 内存管理: QNetworkReply 对象需要被正确地管理,以避免内存泄漏。通常情况下,使用
QObject::deleteLater 来安排删除它是一个好方法。
7.8 JSON数据
7.8.1 概述
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它易于人阅读和编写,同时也易于
机器解析和生成。JSON是基于JavaScript的一个子集,尽管它是独立于语言的,且有多种语言支持。
JSON常用于网络应用程序中的数据传输,尤其是在Web应用程序中与后端服务器通信。
使用JSON的原因总结如下:
{
QCoreApplication a(argc, argv);
QNetworkAccessManager manager;
QNetworkRequest request(QUrl("http://example.com"));
QNetworkReply *reply = manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, [&]() {
if (reply->error()) {
qDebug() << "Error:" << reply->errorString();
return;
}
QString response = reply->readAll();
qDebug() << "Response:" << response;
});
return a.exec();
}原因
描述
网络友好
JSON格式适合Web环境,易于通过网络传输,是Web API的常用格式。
数据互操作性
作为一种标准化格式,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标
准库中
BS/CS开发过程中,会使用不同的编程语言,JSON作为数据传输的标准化格式,方便程序员协议约定和
数据处理,以下是不同编程语言处理JSON的方案
7.8.2 QT生成JSON数据
在Qt中生成JSON数据并将其保存到文件的一个基本示例涉及使用 QJsonDocument 、 QJsonObject 和
QJsonArray 类。以下是创建一个简单JSON对象并将其保存到文件的示例代码。
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QFile>
#include <QDebug>
void createJsonFile() {
// 创建一个JSON对象 键值对
QJsonObject jsonObj;
jsonObj["name"] = "John Doe";
jsonObj["age"] = 30;
jsonObj["email"] = "john.doe@example.com";
// 创建一个JSON数组
QJsonArray jsonArr;
jsonArr.append("C++");
jsonArr.append("Python");说明
1. 创建JSON对象:使用 QJsonObject 来构建JSON对象,并使用键值对填充数据。
2. 创建JSON数组:使用 QJsonArray 来创建一个数组,并添加元素。
3. 组合JSON结构:将JSON数组添加到JSON对象中。
4. 生成JSON文档:通过 QJsonDocument 来处理JSON数据,可以选择格式化(缩进)或压缩形式。
5. 保存到文件:创建 QFile 对象,打开文件,写入JSON数据,并关闭文件。
这个例子展示了Qt中处理JSON的基础流程,包括创建、填充数据、转换为字符串,以及写入文件。您可
以根据需要调整这个流程来适应更复杂的JSON结构或数据。
jsonArr.append("JavaScript");
jsonArr.append(123);
// 将数组添加到JSON对象
jsonObj["languages"] = jsonArr;
// 将JSON对象转换为JSON文档
QJsonDocument jsonDoc(jsonObj);
// 将JSON文档转换为字符串(也可以是压缩格式)
QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Indented);
// 将JSON数据写入文件
QFile file("output.json");
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "Failed to open file for writing";
return;
}
file.write(jsonData);
file.close();
qDebug() << "JSON data saved to output.json";
}
int main() {
createJsonFile();
return 0;
}
#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)在JSON中,数组可以包含多种类型的元素,包括对象。当您在Qt中处理JSON数组,其中的元素是对象
时,您可以使用 QJsonArray 和 QJsonObject 来创建和处理这些数据结构。以下是一个示例,展示了如
何创建一个包含多个对象的JSON数组,并将该数组添加到一个JSON对象中。
示例代码
{
ui->setupUi(this);
QJsonObject rootObj;
rootObj["cityid"] = "1010100";
rootObj["date"] = "2024-01-23";
rootObj["weather"] = "雨夹雪";
rootObj["tmp"] = 3;
QJsonArray jsonArray;
jsonArray.append("data1");
jsonArray.append("data2");
jsonArray.append("data3");
jsonArray.append(100);
rootObj["testArry"] = jsonArray;
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;
}
#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QJsonObject rootObj;
rootObj["cityid"] = "1010100";
rootObj["date"] = "2024-01-23";
rootObj["weather"] = "雨夹雪";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;
}7.8.3 QT解析JSON数据
在Qt中解析JSON数据通常涉及到使用 QJsonDocument 、 QJsonObject 和 QJsonArray 类。这些类提供
了处理JSON数据的必要工具,使您能够从JSON字符串中提取信息、遍历JSON对象或数组,并访问具体
的数据项。以下是一个基本的示例,展示了如何在Qt中解析JSON字符串。
示例:解析JSON字符串
假设您有一个JSON字符串,例如:
以下是如何在Qt中解析这个JSON字符串的步骤:
{
"name": "John Doe",
"age": 30,
"email": "john.doe@example.com",
"skills": ["C++", "Python", "JavaScript"]
}
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
void parseJson() {
// JSON字符串
/*
R 是用于定义原始字符串字面量(Raw String Literal)的标记。
在C++中,原始字符串字面量是一种方便的语法,
用于创建包含多行文本和特殊字符的字符串,而无需转义。
R"("chenlichen")"
*/
QString testStr = "chenli\"c";
QString jsonString = R"(
{
"name": "John Doe",
"age": 30,
"email": "john.doe@example.com",
"skills": ["C++", "Python", "JavaScript"]
}
)";
/*jsonString = "{\n"
" \"name\": \"John Doe\",\n"
" \"age\": 30\n"
"}";
*/
// 将JSON字符串转换为QJsonDocument
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
// 检查JSON文档是否包含一个对象
if (!jsonDoc.isNull() && jsonDoc.isObject()) {
// 获取JSON对象
QJsonObject jsonObj = jsonDoc.object();说明
1. 字符串转换为 QJsonDocument :使用 QJsonDocument::fromJson 方法将JSON字符串转换为
QJsonDocument 对象。
2. 提取 QJsonObject :如果 QJsonDocument 包含一个JSON对象,使用 object() 方法获取它。
3. 访问对象数据:使用键(如 "name" 、 "age" )访问 QJsonObject 中的数据。
4. 处理数组:如果对象包含一个数组,使用 QJsonArray 来遍历数组中的元素。
这个示例提供了一个基础框架,用于在Qt中解析和处理JSON数据。您可以根据实际需要调整这个过程,
以适应不同的JSON结构和数据类型。
在Qt中,如果你想要将JSON数据解析到一个 QMap 中,你可以遍历JSON对象的所有键值对,并将它们添
加到 QMap 里。这个方法特别适合于当你的JSON对象是一个简单的键值对集合时。以下是一个如何实现
这一点的示例。
示例:将JSON数据解析到QMap中
假设你有以下JSON数据:
以下是如何将这些数据解析到 QMap<QString, QString> 中的步骤:
// 访问对象的键值
QString name = jsonObj["name"].toString();
int age = jsonObj["age"].toInt();
QString email = jsonObj["email"].toString();
qDebug() << "Name:" << name;
qDebug() << "Age:" << age;
qDebug() << "Email:" << email;
// 处理JSON数组
if (jsonObj.contains("skills") && jsonObj["skills"].isArray()) {
QJsonArray skillsArray = jsonObj["skills"].toArray();
for (const QJsonValue &value : skillsArray) {
qDebug() << "Skill:" << value.toString();
}
}
} else {
qDebug() << "Invalid JSON...";
}
}
int main() {
parseJson();
return 0;
}
json
{
"name": "John Doe",
"age": "30",
"email": "john.doe@example.com"
}说明
1. 从JSON字符串创建 QJsonDocument :使用 QJsonDocument::fromJson 来解析JSON字符串。
2. 创建 QMap :定义一个 QMap<QString, QString> 来存储键值对。
3. 遍历JSON对象:使用 keys() 方法获取所有键,然后遍历这些键,将对应的值添加到 QMap 中。
4. 打印 QMap 内容:遍历 QMap 并打印键值对。
这个示例展示了如何将JSON对象的键值对解析到 QMap 中。这种方法适用于键值对类型的简单JSON对
象。对于更复杂的JSON结构,可能需要更详细的解析逻辑。
解析如下JSON
#include <QJsonDocument>
#include <QJsonObject>
#include <QMap>
#include <QDebug>
void parseJsonToMap() {
// JSON字符串
QString jsonString = R"(
{
"name": "John Doe",
"age": "30",
"email": "john.doe@example.com"
}
)";
// 将JSON字符串转换为QJsonDocument
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
// 准备一个QMap来存储解析的数据
QMap<QString, QString> dataMap;
// 解析JSON对象并填充QMap
if (!jsonDoc.isNull() && jsonDoc.isObject()) {
QJsonObject jsonObj = jsonDoc.object();
for (auto key : jsonObj.keys()) {
dataMap[key] = jsonObj.value(key).toString();
}
} else {
qDebug() << "Invalid JSON...";
}
// 打印QMap内容
for (auto key : dataMap.keys()) {
qDebug() << key << ":" << dataMap[key];
}
}
int main() {
parseJsonToMap();
return 0;
}#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>
#include <QJsonArray>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//第一步:读取JSON文件保存到QByteArray中
QFile file("D:/QT/test.json");
file.open(QIODevice::ReadOnly);
QByteArray rawData = file.readAll();
file.close();
//第二步:把QByteArray转成JSONDoc
QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
if( !jsonDoc.isNull() && jsonDoc.isObject()){
//第三步:把JsonDoc转成JsonObj
QJsonObject jsonRoot = jsonDoc.object();
//第四步:如果解析普通键值对,通过“下表键”来获取值
QString strW = jsonRoot["weather"].toString();
QString strCityId = jsonRoot["cityid"].toString();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;
}天气类型和图标
P8 Ubuntu搭建QT开发环境
8.1 安装Ubutnu22
8.1.1 下载和安装Vmware
使用我们提供的安装包或者使用如下地址进行下载
官方下载网址: https://download3.vmware.com/software/WKST-1700-WIN/VMware-workstation-fu
ll-17.0.0-20800274.exe
支持正版
//根据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");如果你的电脑已经安装低版本的VMware,千万不要卸载,直接覆盖安装,更新到17的版本
8.1.2 下载和安装Ubuntu22
使用我们提供的镜像
安装的过程看视频教程,安装之后打开如下图所示
8.1.3 常用功能配置
先掌握如下命令
查看命令所在目录 pwd
查看当前目录下的所有文件和文件夹 ls
创建文件夹 mkdir 文件名
复制拷贝文件 cp 源文件名 目标文件名
复制拷贝文件夹 cp 源文件名 目标文件名 -rf
删除文件 rm 文件名 ,如果删除文件夹 加 -rf选项
特别有用!!善于使用tab键,能自动补全文件名或者命令名,不会造成输入错误
网络配置正常电脑就一台虚拟机,通过以上安装后,就能正常上网
多虚拟机情况,桥接模式冲突,配置不稳定,选择NAT共享主机网络上网
获取IP地址通过命令 ip addr
共享文件配置
windows需要传文件给虚拟机
可以通过共享文件夹的方式
可以通过网络的方式
编译环境
默认情况,系统不带编译环境,通过以下命令安装环境
安装VMware Tool
和windows系统的文本复制黏贴打通
共享文件夹
配置支持ubuntu远程登录
sudo apt update //更新软件获取的源
sudo apt install build-essential //安装编译器
sudo apt install libgl1-mesa-dev //安装QT要用的libGL库
sudo apt install open-vm-tools-desktop //安装命令
sudo reboot //重启生效
//以下步骤用于支持文件传输的环境搭建配置
1. sudo apt install open-vm-tools-desktop // ssh服务器
2. sudo apt-get install tftp-hpa // ssh客户端
3. sudo apt-get install vim //使用新版本vim
4. sudo gedit /etc/default/tftpd-hpa //修改配置,这里大家不一定熟悉vim,建议用gedit来编
辑-记事本
将原来的内容改为:
TFTP_USERNAME=”tftp”
TFTP_ADDRESS=”0.0.0.0:69″
TFTP_DIRECTORY=”tftp根目录” #服务器目录,需要设置权限为777,chomd 777
TFTP_OPTIONS=”-l -c -s”
//以下步骤用于支持ssh远程登陆,使用xshell puty等ssh软件登录
1. sudo apt install -y openssh-server //安装程序
2. sudo systemctl start sshd //启动服务
3. update-rc.d ssh enable //ssh服务开机自启8.2 安装Ubuntu环境下的QT
8.2.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 & 这里的“&”符号代表后台运行,
不占用控制命令终端8.2.2 Ubuntu中文支持
配置Ubuntu的中文环境
配置apt下载的服务器源,选择阿里
更新源 sudo apt-get update
在setting设置那边打开Region&Language设置选择语言安装,在窗口中选择Chinese(simplified)
勾选Chinese,重启配置Ubuntu支持中文输入
安装拼音输入法
sudo apt-get install fcitx-sunpinyin
设置输入法点击应用到整个系统,关闭,重启
拷贝我分享的so文件到QT相关路径,让QT支持输入中文!非常重要!!!用系统自带的不行。P9 加餐课
cp libfcitxplatforminputcontextplugin.so
/home/chen/Qt5.12.9/Tools/QtCreator/lib/Qt/plugins/platforminputcontexts/
chmod 777
Qt5.12.9/Tools/QtCreator/lib/Qt/plugins/platforminputcontexts/libfcitxplatforminp
utcontextplugin.so
cp libfcitxplatforminputcontextplugin.so
Qt5.12.9/5.12.9/gcc_64/plugins/platforminputcontexts/
chmod 777
/opt/Qt5.12.9/5.12.9/gcc_64/plugins/platforminputcontexts/libfcitxplatforminputco
ntextplugin.so