QMenu、Qmap、QHash、QPainter
文章目录
1.QMenu

一般窗口都有一个退出键,而在没有这个退出键的时候怎么退出?
QMenu可以解决这一点,示例如下:
| 信号 | 触发时机 |
|---|---|
| QMenu::triggered | 菜单(或其子菜单)中的任意 action 被触发,只要菜单里任何一项被点击都会进来 |
| QAction::triggered | 这个特定的 action 被触发,只有点击特定才会触发 |


右击出现菜单,点击任意,即可关闭窗口
2.Qmap
QMap 是 Qt 提供的一个关联容器类,用于存储键值对(key-value),它非常类似于 C++ 标准库的 std::map
核心特点
自动排序:按键升序存储(默认使用 < 运算符)
对数时间复杂度:查找、插入、删除都是 O(log n)
键唯一:每个键只能对应一个值
内存效率高:比 QHash 占用更少内存(无额外哈希表开销)
支持范围操作:可用 lowerBound/upperBound 获取范围内的键
排序规则是 字典序(lexicographical order),具体取决于 QString::operator< 的实现,它逐个字符比较 Unicode 码点(即区分大小写,且数字、字母、中文等都有确定的顺序)
示例
QMap<QString, int> map;
map["banana"] = 1;
map["apple"] = 2;
map("Apple") = 3; // 注意大写 A
map["100"] = 4;
map["20"] = 5;
// 遍历输出
for (auto it = map.begin(); it != map.end(); ++it)
qDebug() << it.key() << it.value();
输出顺序(实际按 Unicode 码点比较)
"100" : 4 ← 字符 '1' 码点 49,最小
"20" : 5 ← 字符 '2' 码点 50,比 '1' 大但比字母小
"Apple" : 3 ← 'A' 码点 65
"apple" : 2 ← 'a' 码点 97
"banana" : 1 ← 'b' 码点 98
常规操作示例
#include <QMap>
#include <QDebug>
// 创建
QMap<QString, int> map;
// 插入
map["apple"] = 3; // 方式1
map.insert("banana", 5); // 方式2
map.insert("orange", 2);
// 遍历(按键升序自动排列:apple, banana, orange)
for (auto it = map.begin(); it != map.end(); ++it) {
qDebug() << it.key() << ":" << it.value();
}
// 查找
if (map.contains("apple")) {
int count = map["apple"]; // 3
}
// 获取值(带默认值)
int grapes = map.value("grape", 0); // 不存在,返回0
// 修改
map["apple"] = 10;
// 删除
map.remove("banana");
// 获取所有键(或值)
QList<QString> keys = map.keys();
QList<int> values = map.values();
// 清空
map.clear();
map.begin() 返回一个迭代器,指向 QMap 中第一个(key 最小) 元素。map.end() 返回一个迭代器,指向最后一个元素之后的位置(不指向实际元素),作为循环结束标志
3.QHash
QHash 是 Qt 框架中的一个模板类,用于实现哈希表(散列表)数据结构。它提供键-值对的存储与快速查找,平均时间复杂度为 O(1)。
核心特点
- 快速查找:基于哈希函数直接定位,比 QMap(基于红黑树,O(log n))更快
- 无序存储:元素顺序不固定,依赖于哈希值
- 键唯一:每个键只能对应一个值
- 支持动态扩容:自动调整内部桶数组大小
基本用法示例
#include <QHash>
#include <QDebug>
int main() {
// 创建哈希表
QHash<QString, int> hash;
// 插入元素
hash["apple"] = 5;
hash.insert("banana", 3);
hash.insert("orange", 7);
// 访问元素
qDebug() << hash["apple"]; // 输出 5
qDebug() << hash.value("grape", 0); // 不存在返回默认值 0
// 检查键是否存在
if (hash.contains("banana")) {
qDebug() << "Found banana";
}
// 遍历
QHashIterator<QString, int> it(hash);
while (it.hasNext()) {
it.next();
qDebug() << it.key() << ":" << it.value();
}
// 使用范围循环(C++11)
for (auto key : hash.keys()) {
qDebug() << key << hash[key];
}
// 删除元素
hash.remove("orange");
hash.clear(); // 清空所有
return 0;
}
常用函数
| 函数 | 说明 |
|---|---|
| insert(key, value) | 插入键值对 |
| value(key, defaultValue) | 获取值,不存在返回默认值 |
| contains(key) | 判断键是否存在 |
| remove(key) | 删除指定键 |
| keys() | 返回所有键的列表 |
| values() | 返回所有值的列表 |
| size() / isEmpty() | 大小和判空 |
| find(key) | 查找并返回迭代器 |
自定义类型作为键,需要自定义哈希函数需实现 qHash
struct Person {
QString name;
int age;
bool operator==(const Person &other) const {
return name == other.name && age == other.age;
}
};
// 为自定义类型实现哈希函数
uint qHash(const Person &p, uint seed = 0) {
return qHash(p.name, seed) ^ qHash(p.age, seed + 1);
}
// 使用
QHash<Person, QString> hash;
hash[{ "Alice", 25 }] = "Engineer";
QMap 与 QHash 选择指南
使用 QMap :
- 需要按键排序遍历:QMap 内部基于红黑树实现,元素按键排序存储
- 需要进行范围查询:如查找所有键在 [a, b] 之间的元素
- 内存有限,QHash 开销太大:QMap 通常比 QHash 更节省内存
- 键类型不容易实现好的哈希函数:某些复杂类型难以实现高效的哈希函数
使用 QHash :
- 追求最快的查找速度:哈希表平均时间复杂度 O(1),比 QMap 的 O(log n) 更快
- 不关心元素顺序:哈希表不保证元素的存储顺序
- 键类型有现成的 qHash 函数:如 QString、QByteArray 等 Qt 内置类型
- 键数量非常大:哈希表在大数据量下平均性能更好
4.QPainter
QPainter 是 Qt 框架中用于 2D 绘图 的核心类。它可以在各种“画布”(称为 绘图设备 QPaintDevice)上绘制图形,包括窗口部件,如:QWidget
1.QPainter 的核心能力
-
绘制基本图元:点、直线、矩形、椭圆、圆弧、多边形等
绘制文本:支持字体、对齐、换行 -
填充和渐变:纯色、线性渐变、径向渐变、纹理
-
变换:平移、旋转、缩放、剪切(支持仿射变换)
-
抗锯齿:使图形边缘平滑
-
合成模式:控制新绘制内容与背景的混合方式
-
裁剪区域:限制绘图范围
2.QPainter 使用的基本步骤
-
创建 QPainter 对象,并传入一个 QPaintDevice(如 QWidget)。
-
设置画笔(QPen) 和 画刷(QBrush) 以定义线条和填充样式。
-
调用绘图函数(如 drawRect、drawLine、drawText)。
-
QPainter 对象通常会在 绘图事件(paintEvent) 中创建,并且绘制结束后会自动销毁
注意
QPainter 必须处于 激活(active) 状态才能进行绘图操作(如 drawRect、drawText)。激活意味着它已经与一个具体的绘图设备(QPaintDevice,比如 QWidget)关联起来
QPainter 只能在使用 QPainter 构造函数时激活,或者通过 begin() / end() 显式管理
示例:
构造函数直接关联设备
QPainter painter(widget); // 传入 QPaintDevice*,自动调用 begin()
painter.drawRect(10, 10, 100, 100); // 可以直接绘图
// 析构时自动调用 end()
先构造无参对象,再手动调用 begin() / end()
QPainter painter;
painter.begin(widget); // 手动激活,关联绘图设备
painter.drawRect(10, 10, 100, 100);
painter.end(); // 手动结束绘图
关键规则:
- 在 begin() 之后、end() 之前,QPainter 处于激活状态,可以绘图。
不能嵌套激活:begin() 后再次调用 begin() 会出错。- 必须在 end() 之后才能重新 begin() 到另一个设备。
- 忘记调用 end()(或者在析构前未调用)通常不会有严重后果,因为析构函数会自动调用 end(),但显式 end() 有利于资源及时释放。
简单示例
在 QWidget 上画一个红色矩形
// 自定义窗口类
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this); // 1. 创建对象,画布是当前窗口
painter.setPen(Qt::red); // 2. 设置画笔(线条颜色)
painter.setBrush(Qt::blue); // 3. 设置画刷(填充颜色)
painter.drawRect(50, 50, 100, 80); // 4. 绘制矩形(x, y, width, height)
}
};
4.QPainter 核心组件
1.画笔(QPen)
控制线条的 颜色、宽度、样式(实线、虚线、点线等)、端点样式、连接样式。
QPen pen(Qt::green, 2, Qt::DashLine); // 2px 绿色虚线
painter.setPen(pen);
Qt::PenStyle 枚举总结
| 枚举值 | 说明 |
|---|---|
| Qt::NoPen | 无线条(不绘制轮廓) |
| Qt::SolidLine | 实线 |
| Qt::DashLine | 虚线(由若干短线组成) |
| Qt::DotLine | 点线(由点组成) |
| Qt::DashDotLine | 虚点线(短线和点交替) |
| Qt::DashDotDotLine | 虚点点线(短线、点、点交替) |
| Qt::CustomDashLine | 自定义虚线样式(需通过 QPen::setDashPattern() 设置) |
2. 画刷(QBrush)
控制填充区域的 颜色、图案(斜线、网格等)、渐变、纹理。
QBrush(Qt::red)
函数原型
QBrush::QBrush(Qt::GlobalColor color)
参数说明
color:Qt::GlobalColor 枚举值,如 Qt::red、Qt::blue、Qt::green 等。表示标准预定义颜色。
示例
QPainter painter(this);
painter.setBrush(QBrush(Qt::red));
painter.drawRect(10, 10, 100, 100); // 绘制一个红色实心矩形
QBrush(Qt::blue, Qt::DiagCrossPattern)
函数原型
QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
// 或 QBrush::QBrush(const QColor &color, Qt::BrushStyle style)
参数说明
color:画刷的基本颜色(线条或底色)。
style:Qt::BrushStyle 枚举值,指定填充图案。Qt::DiagCrossPattern 表示双斜线交叉图案(米字形网格)。
示例
QPainter painter(this);
painter.setBrush(QBrush(Qt::blue, Qt::DiagCrossPattern));
painter.drawRect(10, 10, 100, 100); // 蓝色交叉斜线填充的矩形
QBrush(pixmap)
函数原型
QBrush::QBrush(const QPixmap &pixmap)
参数说明
pixmap:QPixmap 对象,用作纹理图样。该图片会平铺(tile)填充整个区域。
创建一个纹理画刷。当用它填充形状时,pixmap 会像瓷砖一样重复平铺。纹理的起始点默认为设备坐标原点 (0,0)。
示例
QPixmap tile(":/images/pattern.png"); // 小纹理图
QPainter painter(this);
painter.setBrush(QBrush(tile));
painter.drawRect(10, 10, 200, 150); // 矩形内平铺 pattern.png
QBrush(gradient)
函数原型
QBrush::QBrush(const QGradient &gradient)
参数说明
gradient:QGradient 对象(或其子类 QLinearGradient、QConicalGradient、QRadialGradient),定义颜色在区域内的渐变规则。
创建一个渐变画刷。填充时颜色会按照渐变规则平滑过渡。可用于绘制立体感或光影效果。具体可见高级特性中的渐变填充
Qt::BrushStyle 枚举总结
| 枚举值 | 说明 |
|---|---|
| Qt::NoBrush | 无填充(透明) |
| Qt::SolidPattern | 纯色实心填充 |
| Qt::Dense1Pattern | 极稀疏的点阵 |
| Qt::Dense2Pattern | 稀疏的点阵 |
| Qt::Dense3Pattern | 较稀疏的点阵 |
| Qt::Dense4Pattern | 中等密度的点阵 |
| Qt::Dense5Pattern | 较密集的点阵 |
| Qt::Dense6Pattern | 密集的点阵 |
| Qt::Dense7Pattern | 极密集的点阵(接近实心) |
| Qt::HorPattern | 水平线 |
| Qt::VerPattern | 垂直线 |
| Qt::CrossPattern | 水平+垂直线网格 |
| Qt::BDiagPattern | 反斜线(\) |
| Qt::FDiagPattern | 斜线(/) |
| Qt::DiagCrossPattern | 双斜线交叉(米字) |
| Qt::LinearGradientPattern | 线性渐变 |
| Qt::RadialGradientPattern | 径向渐变 |
| Qt::ConicalGradientPattern | 锥形渐变 |
| Qt::TexturePattern | 纹理填充 |
函数总结
| 画刷构造方式 | 填充效果 |
|---|---|
| QBrush(Qt::red) | 纯红色 |
| QBrush(Qt::blue, Qt::DiagCrossPattern) | 蓝色底+斜线图案 |
| QBrush(pixmap) | 图片平铺(纹理) |
| QBrush(gradient) | 渐变填充 |
理解区分,drawPixmap和setBrush(QBrush(QPixmap))
drawPixmap:单次绘制原始图片,位置、大小由参数决定,不会平铺。
setBrush(QBrush(pixmap)):设置纹理画刷,后续绘制任何形状(矩形、圆形等)时,会用该图片平铺填充整个形状区域,图片重复出现。图片,图片会重复出现(类似瓷砖)。
所以如果你想让图片单次绘制,直接用 drawPixmap 或 drawImage。如果你想让图片重复铺满一个区域,就用 setBrush(QBrush(pixmap))
3. 字体(QFont)
控制文本的 字体族、大小、粗体、斜体 等。
QFont font("Arial", 16, QFont::Bold);
painter.setFont(font);
painter.drawText(100, 100, "Hello Qt");
4. 坐标系统
- 默认原点
(0,0)在绘图设备的左上角,默认坐标系:x 轴向右,y 轴向下 - 可通过 平移(translate)、旋转(rotate)、缩放(scale) 变换坐标系。
- 可以使用 save() / restore() 保存/恢复坐标系状态
translate --平移坐标系
函数原型
void translate(const QPointF &offset);
void translate(qreal dx, qreal dy);
void translate(const QPoint &offset);
void translate(int dx, int dy);
参数说明
dx / dy 或 offset:将坐标原点沿 X 轴、Y 轴移动的距离(支持整数或浮点数)。
作用
将当前坐标系的原点移动到指定位置。后续所有绘图坐标都基于新的原点。
示例
QPainter painter(this);
painter.drawPoint(0, 0); // 在原位置 (0,0) 画点
painter.translate(100, 50);
painter.drawPoint(0, 0); // 实际画在 (100,50) 处
rotate – 旋转坐标系
函数原型
void rotate(qreal angle);
参数说明
angle:旋转角度,单位为度,正值表示顺时针旋转(默认坐标系 X 轴向右、Y 轴向下)。
作用
将坐标系绕当前原点顺时针旋转 angle 度。
示例
painter.translate(100, 100);
painter.rotate(45); // 顺时针45度
painter.drawRect(-50, -50, 100, 100); // 画一个正方形,实际显示为旋转45度的菱形
scale – 缩放坐标系
函数原型
void scale(qreal sx, qreal sy);
参数说明
sx:X 轴缩放因子(>1 放大,0~1 缩小,负数产生镜像翻转)。
sy:Y 轴缩放因子。
作用
将坐标系在水平和垂直方向进行缩放。所有后续绘制的图形尺寸都会随之缩放。
示例
painter.scale(2.0, 0.5); // X 方向放大2倍,Y 方向缩小为0.5倍
painter.drawRect(10, 10, 100, 100); //相当于从(20,5)开始绘图,矩形的大小是宽200,高50
注解
painter.scale(2.0, 0.5) 将坐标系在 X 方向放大 2 倍,Y 方向缩小为 0.5 倍。随后 drawRect(10, 10, 100, 100) 中的坐标和尺寸都会受当前变换影响:
矩形左上角原 (10, 10) 变为 (10×2, 10×0.5) = (20, 5)
宽度 100 变为 100×2 = 200
高度 100 变为 100×0.5 = 50
所以相当于从(20,5)开始绘图,矩形的大小是宽200,高50
shear —— 切变(错切)坐标系
函数原型
void shear(qreal sh, qreal sv);
参数说明
sh:水平切变系数(表示 Y 坐标对 X 坐标的偏移影响,即新 X = 原 X + sh * 原 Y)。
sv:垂直切变系数(表示 X 坐标对 Y 坐标的偏移影响,即新 Y = 原 Y + sv * 原 X)。
作用
对坐标系应用切变变换,可将矩形变为平行四边形。
示例
painter.shear(0.5, 0); // 水平切变,矩形变成平行四边形
painter.drawRect(50, 50, 100, 100);
注解
矩形 (50, 50, 100, 100) 的四个角
| 原始坐标 (x,y) | 应用 shear(0.5, 0) 后 |
|---|---|
| (50,50) 左上 | (75, 50) |
| (150,50) 右上 | (175, 50) |
| (50,150) 左下 | (125, 150) |
| (150,150) 右下 | (225, 150) |
原始正方形: 错切后:
(50,50)---(150,50) (75,50)-------(175,50)
| | \ \
| | \ \
(50,150)--(150,150) (125,150)-----(225,150)
setTransform – 直接设置变换矩阵
函数原型
void setTransform(const QTransform &transform, bool combine = false);
参数说明
transform:一个 QTransform 矩阵对象(包含平移、旋转、缩放、切变所有信息)。
combine:若为 false(默认),替换当前变换;若为 true,则将新矩阵与当前变换相乘组合。
作用
完全控制坐标变换矩阵,适合复杂或非标准的变换。
示例
QTransform transform;
transform.translate(100, 100);
transform.rotate(45);
transform.scale(1.5, 1.5);
painter.setTransform(transform); // 一次性应用平移+旋转+缩放
painter.drawRect(-50, -50, 100, 100);
resetTransform – 重置变换
函数原型
void resetTransform();
无参数
作用
清除所有坐标变换,将坐标系恢复为默认状态(单位矩阵)。
示例
painter.translate(200, 200);
painter.rotate(90);
// ... 画一些东西
painter.resetTransform(); // 回到原始坐标系
painter.drawPoint(0, 0); // 在窗口左上角(0,0)画点
函数总结表

| 函数 | 参数 | 作用 |
|---|---|---|
| translate(dx, dy) | 偏移量 | 移动原点 |
| rotate(angle) | 角度(度,正顺时针) | 绕原点旋转 |
| scale(sx, sy) | 缩放因子 | 缩放坐标系 |
| shear(sh, sv) | 切变系数 | 错切变换 |
| setTransform(t, combine) | 矩阵,是否组合 | 设置整个变换矩阵 |
| resetTransform() | 无 | 恢复为单位矩阵 |
| save() / restore() | 无 | 保存/恢复所有状态(不仅是变换) |
5、常用绘图函数
| 函数 | 描述 |
|---|---|
| drawPoint(x, y) | 绘制点 |
| drawLine(x1, y1, x2, y2) | 绘制直线 |
| drawRect(x, y, w, h) | 绘制矩形 |
| drawRoundedRect(…) | 圆角矩形 |
| drawEllipse(x, y, w, h) | 椭圆 |
| drawArc(…) | 圆弧 |
| drawPolygon(points) | 多边形(自动闭合) |
| drawText(x, y, text) 绘制文本 | (x,y 为基线坐标) |
| drawPixmap(x, y, pixmap) | 绘制图片 |
| drawPath(path) | 绘制由 QPainterPath 定义的复杂路径 |
drawPolygon(points)
drawPolygon(points) 是 QPainter 中用于绘制多边形的函数。它会根据传入的点集,依次连接各点(首尾自动闭合),并用当前画笔(QPen)描边,用当前画刷(QBrush)填充内部。
void MyWidget::paintEvent(QPaintEvent *) {
QPainter painter(this);
painter.setPen(Qt::blue);
painter.setBrush(Qt::yellow);
// 定义三个顶点 (三角形)
QPolygon triangle;
triangle << QPoint(50, 50) << QPoint(150, 50) << QPoint(100, 120);
painter.drawPolygon(triangle);
}
QPainterPath
QPainterPath 是一个图形组合容器,可以将多个图形元素(线段、矩形、椭圆、曲线等)组合成一个复合路径,并且可以执行布尔运算(并集、差集等)。
作用:预先定义好一系列绘图指令,然后通过 drawPath 一次性绘制。
优势:可以复用、缓存路径;支持复杂的填充规则;容易进行坐标变换。
void MyWidget::paintEvent(QPaintEvent *) {
QPainter painter(this);
painter.setPen(Qt::red);
painter.setBrush(Qt::blue);
// 创建一个 QPainterPath
QPainterPath path;
// 添加一个矩形
path.addRect(50, 50, 100, 80);
// 添加一个椭圆(与矩形相交)
path.addEllipse(80, 70, 80, 60);
// 一次性绘制整个路径,填充会按填充规则填充
painter.drawPath(path);
}

默认填充规则是,重叠区域不填充
运行效果
6.高级特性
抗锯齿
是 Qt 中 QPainter 的一个设置函数,用于开启抗锯齿(Antialiasing)渲染,使绘制的图形边缘更平滑,消除锯齿状的阶梯效应。
painter.setRenderHint(QPainter::Antialiasing,true);
渐变填充
QPainter painter(this);
QLinearGradient gradient(0, 0, 100, 100);//创建渐变对象,起点 (0, 0),终点 (100, 100)
gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1, Qt::black);
painter.setBrush(gradient);
painter.drawRect(0, 0, 100, 100);
注解
1.创建渐变对象
-
QLinearGradient gradient(0, 0, 100, 100);
-
QLinearGradient 表示线性渐变,即颜色沿着一条直线方向平滑变化。
参数 (0, 0, 100, 100) 定义了渐变的起点和终点: 起点 (0, 0):逻辑坐标,通常对应矩形的左上角。 终点 (100, 100):逻辑坐标,对应矩形的右下角(矩形宽高各为100)。
渐变方向是从起点到终点的直线,本例中为从左上到右下的对角线。
2. 设置颜色停止点
-
gradient.setColorAt(0, Qt::white);
-
gradient.setColorAt(1, Qt::black);
setColorAt(position, color):在渐变路径的某个位置(0到1之间)定义颜色。 position = 0 表示起点((0,0))处的颜色为白色。 position = 1 表示终点((100,100))处的颜色为黑色。 中间位置的颜色会自动插值(例如位置0.5处为灰色)。
可以设置多个颜色停止点,例如 setColorAt(0.5, Qt::red) 实现更复杂的渐变。
3. 将渐变设置为画刷
- painter.setBrush(gradient);
- QPainter::setBrush() 设置填充画刷。画刷可以是纯色、纹理、渐变等。
这里将上面定义的线性渐变作为画刷,后续的图形(如矩形)将使用此渐变填充。
4. 绘制矩形
- painter.drawRect(0, 0, 100, 100);
绘制一个矩形,左上角在 (0,0),宽度 100,高度 100。
矩形内部用当前画刷(即对角线渐变)填充
运行结果
7.paintEvent 的什么时候触发?
-
窗口首次显示:调用 show() 或窗口从隐藏变为可见。
-
窗口大小改变:用户拖动边缘或代码调用 resize()。
-
窗口从被遮挡到重新暴露:其他窗口移开、最小化恢复、切换标签页等。
如:窗口收起来,然后再打开,会触发paintEvent
-
代码主动请求重绘:
update():异步,最常用的人为触发方式(不会立即重绘,而是投递一个绘制事件到事件队列) repaint():同步,立即重绘(会直接触发 paintEvent,不经过事件循环) -
系统属性变化:修改样式表(QSS)、字体、调色板时,系统自动触发。
-
父部件重绘传播:父部件重绘时可能连带子部件(取决于属性设置)。
核心:只要 Qt 认为窗口内容“需要刷新”,就会调用 paintEvent。绝大部分情况下,你只需要调用 update() 来触发它
8.示例
这里是给指定的控件绘图,所以没用 paintEvent()(给整个窗口添加),会导致覆盖,所以用了bool eventFilter(QObject *watched,QEvent *event);(事件过滤),事件相关知识可见事件
bool eventFilter(QObject *watched,QEvent *event);
bool eventFilter(QObject * watched,QEvent *event)
- watched:被监视的对象,即事件原本要发送给的对象。
- event:将要被处理的事件(如鼠标点击、键盘按下、定时器事件等)。
返回值:
- true:表示事件已被你处理,不再继续传递给目标对象。
- false:表示事件未被处理(或你希望继续正常处理),Qt 会把它继续发送给目标对象。

给窗口安装过滤器


这里窗口运行,会绘制一次,但是不是用户想要的曲线,所以调用update()再一次绘制,得到正确的曲线

运行效果
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)