Qt C++ 图形绘制完全指南:从基础到进阶实战

前言

Qt框架提供了强大的2D图形绘制能力,通过QPainter类及其相关组件,开发者可以轻松实现各种复杂的图形绘制需求。本文将系统介绍Qt图形绘制的核心技术,并通过实例代码演示各种绘制技巧。

一、Qt图形绘制基础架构

1.1 核心类介绍

Qt图形绘制主要涉及以下核心类:

  • QPainter:执行绘制操作的主要类
  • QPaintDevice:绘制设备的抽象基类
  • QPaintEngine:定义QPainter如何在特定平台绘制
  • QWidget:最常用的绘制设备
  • QPixmap/QImage:图像绘制设备

1.2 绘制系统架构图

┌─────────────┐
│  QPainter   │ ← 绘制工具
└──────┬──────┘│
┌──────▼──────┐
│QPaintDevice │ ← 绘制表面
└──────┬──────┘│
┌──────▼──────┐
│QPaintEngine │ ← 底层引擎
└─────────────┘

二、基础图形绘制实战

2.1 创建自定义绘制Widget

首先创建一个自定义Widget类,重写paintEvent方法:

DrawWidget.h

#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
#include <QTimer>
#include <cmath>class DrawWidget : public QWidget
{Q_OBJECTpublic:explicit DrawWidget(QWidget *parent = nullptr);protected:void paintEvent(QPaintEvent *event) override;private slots:void updateAnimation();private:int m_animationAngle;QTimer *m_timer;void drawBasicShapes(QPainter &painter);void drawGradients(QPainter &painter);void drawTransformations(QPainter &painter);void drawPath(QPainter &painter);void drawText(QPainter &painter);
};#endif // DRAWWIDGET_H

DrawWidget.cpp

#include "DrawWidget.h"
#include <QLinearGradient>
#include <QRadialGradient>
#include <QPainterPath>
#include <QFont>DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent), m_animationAngle(0)
{setFixedSize(800, 600);setWindowTitle("Qt图形绘制示例");// 设置定时器用于动画m_timer = new QTimer(this);connect(m_timer, &QTimer::timeout, this, &DrawWidget::updateAnimation);m_timer->start(50); // 20 FPS
}void DrawWidget::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);// 设置白色背景painter.fillRect(rect(), Qt::white);// 绘制各种图形drawBasicShapes(painter);drawGradients(painter);drawTransformations(painter);drawPath(painter);drawText(painter);
}void DrawWidget::drawBasicShapes(QPainter &painter)
{painter.save();// 绘制标题painter.setPen(QPen(Qt::black, 2));painter.setFont(QFont("Arial", 12, QFont::Bold));painter.drawText(20, 30, "基础图形绘制");// 设置画笔和画刷QPen pen(Qt::blue, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);painter.setPen(pen);// 绘制直线painter.drawLine(50, 50, 150, 50);// 绘制矩形painter.setBrush(QBrush(Qt::yellow, Qt::SolidPattern));painter.drawRect(50, 70, 100, 60);// 绘制圆角矩形painter.setBrush(QBrush(Qt::cyan, Qt::Dense4Pattern));painter.drawRoundedRect(170, 70, 100, 60, 15, 15);// 绘制椭圆painter.setBrush(QBrush(Qt::magenta, Qt::DiagCrossPattern));painter.drawEllipse(290, 70, 100, 60);// 绘制多边形QPolygon polygon;polygon << QPoint(420, 70) << QPoint(470, 70) << QPoint(495, 100) << QPoint(470, 130) << QPoint(420, 130) << QPoint(395, 100);painter.setBrush(QBrush(Qt::green, Qt::CrossPattern));painter.drawPolygon(polygon);// 绘制弧形painter.setBrush(Qt::NoBrush);painter.setPen(QPen(Qt::red, 3));painter.drawArc(520, 70, 80, 60, 30 * 16, 120 * 16);// 绘制扇形painter.setBrush(QBrush(Qt::darkCyan));painter.drawPie(620, 70, 80, 60, 45 * 16, 90 * 16);painter.restore();
}void DrawWidget::drawGradients(QPainter &painter)
{painter.save();// 绘制标题painter.setPen(QPen(Qt::black, 2));painter.setFont(QFont("Arial", 12, QFont::Bold));painter.drawText(20, 180, "渐变效果");// 线性渐变QLinearGradient linearGrad(50, 200, 150, 260);linearGrad.setColorAt(0, Qt::red);linearGrad.setColorAt(0.5, Qt::yellow);linearGrad.setColorAt(1, Qt::green);painter.setBrush(linearGrad);painter.drawRect(50, 200, 100, 60);// 径向渐变QRadialGradient radialGrad(220, 230, 50);radialGrad.setColorAt(0, Qt::white);radialGrad.setColorAt(0.5, Qt::cyan);radialGrad.setColorAt(1, Qt::blue);painter.setBrush(radialGrad);painter.drawEllipse(170, 200, 100, 60);// 锥形渐变QConicalGradient conicalGrad(320, 230, 0);conicalGrad.setColorAt(0, Qt::red);conicalGrad.setColorAt(0.25, Qt::yellow);conicalGrad.setColorAt(0.5, Qt::green);conicalGrad.setColorAt(0.75, Qt::blue);conicalGrad.setColorAt(1, Qt::red);painter.setBrush(conicalGrad);painter.drawEllipse(290, 200, 60, 60);painter.restore();
}void DrawWidget::drawTransformations(QPainter &painter)
{painter.save();// 绘制标题painter.setPen(QPen(Qt::black, 2));painter.setFont(QFont("Arial", 12, QFont::Bold));painter.drawText(20, 310, "变换效果(动画)");// 保存原始状态painter.save();// 平移到旋转中心painter.translate(100, 360);// 应用旋转(动画)painter.rotate(m_animationAngle);// 绘制旋转的矩形painter.setBrush(QBrush(Qt::darkBlue));painter.drawRect(-30, -20, 60, 40);painter.restore();// 缩放效果painter.save();painter.translate(220, 360);double scale = 1.0 + 0.5 * sin(m_animationAngle * M_PI / 180.0);painter.scale(scale, scale);painter.setBrush(QBrush(Qt::darkGreen));painter.drawEllipse(-30, -30, 60, 60);painter.restore();// 错切效果painter.save();painter.translate(340, 360);painter.shear(0.5 * sin(m_animationAngle * M_PI / 180.0), 0);painter.setBrush(QBrush(Qt::darkRed));painter.drawRect(-30, -20, 60, 40);painter.restore();painter.restore();
}void DrawWidget::drawPath(QPainter &painter)
{painter.save();// 绘制标题painter.setPen(QPen(Qt::black, 2));painter.setFont(QFont("Arial", 12, QFont::Bold));painter.drawText(20, 440, "路径绘制");// 创建复杂路径QPainterPath path;path.moveTo(50, 460);path.lineTo(100, 460);path.cubicTo(120, 440, 140, 480, 160, 460);path.lineTo(200, 460);path.quadTo(220, 480, 240, 460);path.arcTo(240, 440, 40, 40, 0, 180);// 绘制路径painter.setPen(QPen(Qt::darkMagenta, 3));painter.setBrush(QBrush(Qt::lightGray));painter.drawPath(path);// 创建星形路径QPainterPath starPath;int starX = 400, starY = 470;for (int i = 0; i < 5; ++i) {double angle = i * 72 * M_PI / 180.0 - M_PI / 2;double x = starX + 30 * cos(angle);double y = starY + 30 * sin(angle);if (i == 0) {starPath.moveTo(x, y);} else {starPath.lineTo(x, y);}angle = (i * 72 + 36) * M_PI / 180.0 - M_PI / 2;x = starX + 15 * cos(angle);y = starY + 15 * sin(angle);starPath.lineTo(x, y);}starPath.closeSubpath();painter.setPen(QPen(Qt::darkYellow, 2));painter.setBrush(QBrush(Qt::yellow));painter.drawPath(starPath);painter.restore();
}void DrawWidget::drawText(QPainter &painter)
{painter.save();// 绘制标题painter.setPen(QPen(Qt::black, 2));painter.setFont(QFont("Arial", 12, QFont::Bold));painter.drawText(20, 540, "文字绘制");// 普通文字painter.setFont(QFont("Times New Roman", 14));painter.setPen(Qt::darkBlue);painter.drawText(50, 565, "Hello Qt Graphics!");// 带阴影的文字painter.setFont(QFont("Arial", 16, QFont::Bold));painter.setPen(Qt::gray);painter.drawText(202, 567, "Shadow Text");painter.setPen(Qt::black);painter.drawText(200, 565, "Shadow Text");// 旋转文字painter.save();painter.translate(400, 560);painter.rotate(-30);painter.setFont(QFont("Courier", 14));painter.setPen(Qt::darkGreen);painter.drawText(0, 0, "Rotated Text");painter.restore();// 渐变文字QLinearGradient textGrad(500, 550, 600, 570);textGrad.setColorAt(0, Qt::blue);textGrad.setColorAt(1, Qt::red);painter.setPen(QPen(QBrush(textGrad), 2));painter.setFont(QFont("Arial", 18, QFont::Bold));painter.drawText(500, 565, "Gradient");painter.restore();
}void DrawWidget::updateAnimation()
{m_animationAngle = (m_animationAngle + 5) % 360;update(); // 触发重绘
}

2.2 主窗口实现

main.cpp

#include <QApplication>
#include "DrawWidget.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);DrawWidget widget;widget.show();return app.exec();
}

三、高级绘制技术

3.1 双缓冲绘制

为了避免闪烁,Qt默认启用双缓冲。也可以手动实现:

void CustomWidget::paintEvent(QPaintEvent *event)
{QPixmap pixmap(size());pixmap.fill(Qt::white);QPainter pixmapPainter(&pixmap);pixmapPainter.setRenderHint(QPainter::Antialiasing);// 在pixmap上绘制drawContent(pixmapPainter);// 将pixmap绘制到widgetQPainter widgetPainter(this);widgetPainter.drawPixmap(0, 0, pixmap);
}

3.2 图形项框架 (Graphics View Framework)

对于复杂的图形场景,使用Graphics View框架更合适:

// 场景图形项
class CustomItem : public QGraphicsItem
{
public:CustomItem(){setFlag(ItemIsMovable);setFlag(ItemIsSelectable);}QRectF boundingRect() const override{return QRectF(-50, -50, 100, 100);}void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) override{Q_UNUSED(option);Q_UNUSED(widget);painter->setBrush(isSelected() ? Qt::yellow : Qt::lightBlue);painter->setPen(QPen(Qt::black, 2));painter->drawEllipse(boundingRect());}
};// 使用场景
QGraphicsScene *scene = new QGraphicsScene();
scene->addItem(new CustomItem());QGraphicsView *view = new QGraphicsView(scene);
view->setRenderHint(QPainter::Antialiasing);
view->show();

3.3 OpenGL集成

Qt支持OpenGL绘制,可以实现高性能3D图形:

class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
protected:void initializeGL() override{initializeOpenGLFunctions();glClearColor(0.0f, 0.0f, 0.0f, 1.0f);}void paintGL() override{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// OpenGL绘制代码}void resizeGL(int w, int h) override{glViewport(0, 0, w, h);}
};

四、性能优化技巧

4.1 绘制优化策略

  1. 减少重绘区域
void Widget::updatePartial()
{// 只更新特定区域update(QRect(10, 10, 100, 100));
}
  1. 使用绘制缓存
class CachedWidget : public QWidget
{
private:QPixmap m_cache;bool m_cacheValid = false;protected:void paintEvent(QPaintEvent *event) override{if (!m_cacheValid) {m_cache = QPixmap(size());QPainter cachePainter(&m_cache);drawComplexContent(cachePainter);m_cacheValid = true;}QPainter painter(this);painter.drawPixmap(0, 0, m_cache);}
};
  1. 批量绘制操作
// 低效方式
for (int i = 0; i < 1000; ++i) {painter.drawPoint(points[i]);
}// 高效方式
painter.drawPoints(points.data(), 1000);

4.2 渲染提示设置

painter.setRenderHint(QPainter::Antialiasing, true);        // 抗锯齿
painter.setRenderHint(QPainter::TextAntialiasing, true);    // 文字抗锯齿
painter.setRenderHint(QPainter::SmoothPixmapTransform, true); // 平滑变换

五、实战案例:自定义图表控件

5.1 简单饼图实现

class PieChart : public QWidget
{
private:QVector<QPair<QString, double>> m_data;QVector<QColor> m_colors;public:void setData(const QVector<QPair<QString, double>> &data){m_data = data;generateColors();update();}protected:void paintEvent(QPaintEvent *event) override{Q_UNUSED(event);QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);QRect pieRect = rect().adjusted(20, 20, -20, -20);double total = 0;for (const auto &item : m_data) {total += item.second;}int startAngle = 0;for (int i = 0; i < m_data.size(); ++i) {int spanAngle = static_cast<int>(m_data[i].second / total * 360 * 16);painter.setBrush(m_colors[i]);painter.drawPie(pieRect, startAngle, spanAngle);startAngle += spanAngle;}}private:void generateColors(){m_colors.clear();for (int i = 0; i < m_data.size(); ++i) {m_colors.append(QColor::fromHsv(i * 360 / m_data.size(), 200, 200));}}
};

六、常见问题与解决方案

6.1 绘制闪烁问题

问题:快速更新时界面闪烁
解决方案

  • 启用双缓冲(Qt默认启用)
  • 使用setAttribute(Qt::WA_OpaquePaintEvent)
  • 避免在paintEvent中进行复杂计算

6.2 坐标系统混淆

问题:绘制位置不正确
解决方案

// 理解Qt坐标系统
// (0,0) 在左上角
// x轴向右增长
// y轴向下增长// 坐标变换
painter.translate(100, 100);  // 移动原点
painter.scale(2.0, 2.0);      // 缩放
painter.rotate(45);           // 旋转(顺时针)

6.3 性能问题

问题:绘制大量图形时卡顿
解决方案

  • 使用Graphics View框架
  • 实现图形项的LOD(细节层次)
  • 使用OpenGL加速
  • 裁剪不可见区域

七、最佳实践总结

  1. 合理选择绘制方式

    • 简单绘制:重写paintEvent
    • 复杂场景:Graphics View框架
    • 3D/高性能:OpenGL
  2. 性能优化原则

    • 最小化重绘区域
    • 缓存复杂绘制结果
    • 批量处理绘制操作
  3. 代码组织建议

    • 分离绘制逻辑和业务逻辑
    • 使用绘制状态的保存/恢复
    • 合理使用渲染提示

八、项目配置

.pro文件配置

QT += core gui widgetsCONFIG += c++11TARGET = QtGraphicsDemo
TEMPLATE = appSOURCES += \main.cpp \DrawWidget.cppHEADERS += \DrawWidget.h# 如果使用OpenGL
# QT += opengl

总结

本文系统介绍了Qt C++图形绘制的核心技术,从基础的QPainter使用到高级的Graphics View框架和OpenGL集成。通过实际代码示例,展示了各种绘制技巧和优化方法。掌握这些技术,可以开发出功能丰富、性能优异的图形应用程序。

Qt的图形系统非常强大和灵活,本文只是涵盖了最常用的部分。建议读者在实际项目中根据具体需求选择合适的技术方案,并持续关注Qt的最新特性和最佳实践。

参考资源

  • Qt官方文档 - Painting Classes
  • Qt Graphics View Framework
  • Qt OpenGL Integration

作者: Qt开发者
发布时间: 2024
标签: Qt, C++, 图形绘制, QPainter, Graphics View

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二分搜索边界问题

在使用二分搜索的时候&#xff0c;更新条件不总是相同&#xff0c;虽然说使用bS目的就是为了target&#xff0c;但也有如下几种情况&#xff1a;求第一个target的索引求第一个>target的索引求第一个>target的索引求最后一个target的索引求最后一个<target的索引求最后…

【springboot+vue3】博客论坛管理系统(源码+文档+调试+基础修改+答疑)

目录 一、整体目录&#xff1a; 项目包含源码、调试、修改教程、调试教程、讲解视频、开发文档&#xff08;项目摘要、前言、技术介绍、可行性分析、流程图、结构图、ER属性图、数据库表结构信息、功能介绍、测试致谢等约1万字&#xff09; 二、运行截图 三、代码部分&…

20250907_梳理异地备份每日自动巡检Python脚本逻辑流程+安装Python+PyCharm+配置自动运行

一、逻辑流程(autocheckbackup.py在做什么) 1.连接Linux服务器 用 paramiko 登录你配置的 Linux 服务器(10.1.3.15, 10.1.3.26),进入指定目录(如 /home, /backup/mes),递归列出文件。 采集到的信息:服务器IP、目录、数据库名称、文件名、大小、修改时间。 2.连接Wind…

terraform-state详解

一、Treeaform-state的作用 Terraform-state是指Terroform的状态&#xff0c;是terraform不可缺少的生命周期元素。本质上来讲&#xff0c;terraform状态是你的基础设施配置的元数据存储库&#xff0c;terraform会把它管理的资源状态保存在一个状态文件里。 默认情况下&#xf…

四、kubernetes 1.29 之 Pod 生命周期

一、概述当容器与 pause 容器共享网络&#xff08;Network&#xff09;、IPC&#xff08;进程间通信&#xff09;和 PID&#xff08;进程命名空间&#xff09;后&#xff0c;二者形成了一种紧密的 "共享命名空间" 关系&#xff0c;共同构成了 Kubernetes 中 "Po…

AI与环保:礼貌用语背后的能源挑战与解决方案

程序员的技术管理推荐阅读 窄化效应&#xff1a;程序员与管理者的隐形情绪陷阱 从“激励”到“保健”&#xff1a;80后与90后程序员&#xff0c;到底想要什么&#xff1f; 从“激励”到“保健”&#xff1a;80后与90后程序员&#xff0c;到底想要什么&#xff1f; 场景引入&…

OpenCV C++ 特征提取:从角点检测到对象识别

特征提取是计算机视觉的核心技术,通过识别图像中具有代表性的关键点及其描述信息,实现图像匹配、对象识别、姿态估计等高级任务。本章将系统讲解从基础的图像金字塔、角点检测,到复杂的 ORB 和 SIFT 特征提取与匹配,最终实现基于特征的对象检测完整流程。 一、图像金字塔 …

Codeforces Round 1049 (Div. 2) D题题解记录

大致题意&#xff1a;给定nnn个区间(li,ri)(l_i,r_i)(li​,ri​)。每次选取两个尚未被标记的区间(l1,r1)(l_1,r_1)(l1​,r1​)与(l2,r2)(l_2,r_2)(l2​,r2​)&#xff0c;使得他们均被标记&#xff0c;同时可以任选x∈[l1,r1]&#xff0c;y∈[l2,r2]x\in[l_1,r_1]&#xff0c;y…

《WINDOWS 环境下32位汇编语言程序设计》第15章 注册表和INI文件

15.1 注册表和INI文件简介在一个操作系统中&#xff0c;无论是操作系统本身还是运行于其中的大部分应用程序&#xff0c;都需要使用某种方式保存配置信息。在DOS系统中&#xff0c;配置信息往往是软件的开发者根据自己的喜好用各种途径加以保存的&#xff0c;比如在磁盘上面写一…

JDK 17、OpenJDK 17、Oracle JDK 17 的说明

Java生态系统的核心概念&#xff1a;简单来说&#xff1a;JDK 17 是一个标准规范&#xff0c;定义了Java开发工具包第17个长期支持版应该包含什么功能。openjdk-17-jdk 是一个具体的实现&#xff0c;是遵循上述规范、由OpenJDK社区提供的开源软件包。下面我们通过一个表格和详细…

手写MyBatis第58弹:如何优雅输出可执行的SQL语句--深入理解MyBatis日志机制:

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

Spring Boot 监控实战:集成 Prometheus 与 Grafana,打造全方位监控体系

前言 在当今微服务架构盛行的时代&#xff0c;应用程序的监控变得尤为重要。Spring Boot 作为广泛使用的微服务框架&#xff0c;其监控需求也日益增加。Prometheus 和 Grafana 作为开源监控领域的佼佼者&#xff0c;为 Spring Boot 应用提供了强大的监控能力。本文将详细介绍如…

JS中的多线程——Web Worker

众所周知&#xff0c;JavaScript 是单线程运行的&#xff08;至于为什么是单线程可以看一下这篇文章——事件循环机制&#xff09;&#xff0c;当浏览器主线程被大量计算任务阻塞时&#xff0c;页面就会出现明显的卡顿现象。Web Worker 提供了在独立线程中运行 JavaScript 的能…

【SQL注入】延时盲注

sleep(n)​​: 核心延时函数。使数据库程序暂停 n秒。​​if(condition, true_expr, false_expr)​​: 条件判断函数。如果 condition为真&#xff0c;执行 true_expr&#xff0c;否则执行 false_expr。​​用于将延时与判断条件绑定​​。​​mid(a, b, c)​​: 字符串截取函数…

IntelliJ IDEA 2025.1 Java Stream Debugger 快速使用指南

1. 功能概览 Java Stream Debugger 提供 Trace Current Stream Chain 功能&#xff0c;用来在调试时分析和可视化 Stream 操作链。 主要用途&#xff1a; 在运行时查看流操作链的每一步输出找出 map/filter 等操作的问题避免手动加 peek() 打印调试2. 使用入口 在 IDEA 2025.1 …

ARM-指令集全解析:从基础到高阶应用

一、ARM 指令集体系结构版本ARM 公司定义了多个指令集版本&#xff1a;ARMv1&#xff1a;原型机 ARM1&#xff0c;没有用于商业产品。ARMv2&#xff1a;扩展 V1&#xff0c;包含 32 位乘法指令和协处理器指令。ARMv3&#xff1a;第一个微处理器 ARM6 核心&#xff0c;支持 Cach…

第3讲 机器学习入门指南

近年来&#xff0c;随着企业和个人生成的数据量呈指数级增长&#xff0c;机器学习已成为日益重要的技术领域。从自动驾驶汽车到流媒体平台的个性化推荐&#xff0c;机器学习算法已广泛应用于各个场景。让我们深入解析机器学习的核心要义。3.1 机器学习定义机器学习是人工智能的…

深入理解跳表:多层索引加速查找的经典实现

跳表&#xff08;Skip List&#xff09;是一种多层有序链表结构&#xff0c;通过引入多级索引加速查找&#xff0c;其核心设计类似于“立体高速公路系统”&#xff0c;底层是原始链表&#xff0c;上面有各种高度的"高架桥"。 高层道路跨度大&#xff0c;连接远方节点…

Flutter 视频播放器——flick_video_player 介绍与使用

在移动端应用中&#xff0c;视频播放是一个常见的功能场景&#xff0c;例如短视频、直播、课程、广告展示等。 Flutter 本身并没有直接提供视频播放器组件&#xff0c;而是依赖第三方库来实现。 今天要介绍的库是 flick_video_player&#xff0c;它基于 video_player 封装&…

编写cmakelists文件常用语句

cmake_minimum_required (VERSION 3.10) 指定最小版本project(XXXX) 指定项目名字 ---------------set(MAIN_EXEC_NAME dwarf_parser) 定义变量${ MAIN_EXEC_NAME } 变量取值set(CMAKE_CXX_STANDARD 14) 指定c14标准&#xff0c;还有11、17、20等标准…