QTableWidget 使用时太耗时
我有4个表格每个都是32行22列。每个单元格里装填的都是自定义QWidget我使用QTableWidget来显示表格。效果为了显示该窗体感觉花费了很多的时间。不符合我的预期。核心原因在于setCellWidget()会为每个单元格创建一个真实的、独立的窗口对象。你一共有4 * 32 * 22 2816个单元格这意味着要创建近3000个独立的QWidget及其子控件。每个控件都拥有自己的窗口句柄、事件循环和绘制上下文内存占用和绘制开销极其庞大最终导致你感受到的严重耗时和卡顿。要解决这个问题最根本的方法是从“重量级的控件”转向“轻量级的绘制”。核心解决方案拥抱 Model/View 框架这是Qt官方推荐的、也是解决此类性能问题的标准做法。迁移到QTableViewQStandardItemModel放弃QTableWidget改用QTableView配合QStandardItemModel来存储数据。QTableWidget本身是QTableView的便捷子类但其“一单元格一对象”的设计在数据量大时是性能瓶颈。使用QStyledItemDelegate进行绘制这是最关键的一步。不要用setCellWidget()而是为QTableView设置一个自定义的QStyledItemDelegate。原理委托不会为每个单元格创建真正的控件而是根据数据模型中的内容在单元格需要被绘制时“画”出你想要的界面。优势这种方式极大地减少了内存占用和对象数量绘制效率极高滚动和刷新会变得非常流畅。如果需要有按钮的交互效果可以在委托的paint()方法中绘制按钮的样式并在editorEvent()中处理点击事件。快速缓解技巧治标不治本如果短期内无法重构可以尝试以下方法可能会有轻微改善但无法解决根本问题。暂停界面更新在批量设置单元格控件时使用setUpdatesEnabled(false)暂停绘制完成后再恢复。tableWidget-setUpdatesEnabled(false); // ... 你的 setCellWidget 循环 ... tableWidget-setUpdatesEnabled(true);阻止信号触发在批量操作前调用blockSignals(true)阻止表格因每个单元格变化而触发不必要的信号和重绘。固定行高如果行高都相同可以开启setUniformRowHeights(true)来加速布局计算。固定列宽将列宽模式设为Fixed避免在插入数据时频繁重新计算列宽。总结与建议根本问题在于选错了工具。setCellWidget()是为少量、交互复杂的单元格设计的便捷方法。对于你这种包含近3000个自定义控件的场景它已经不堪重负。因此最推荐、也最彻底的解决方案是重构代码采用QTableViewQStandardItemModelQStyledItemDelegate的经典 MVC 模式。虽然这需要一些学习和重构工作但这是一次投入、长期受益的优化能让你的表格应用在面对更多数据时依然保持流畅。采用QTableViewQStandardItemModelQStyledItemDelegate#include QApplication #include QWidget // 改为 QWidget #include QVBoxLayout // 新增布局头文件 #include QTableView #include QStandardItemModel #include QStyledItemDelegate #include QPainter #include QPen #include QColor #include QHeaderView class DotDelegate : public QStyledItemDelegate { public: using QStyledItemDelegate::QStyledItemDelegate; void paint(QPainter *painter, const QStyleOptionViewItem option, const QModelIndex index) const override { painter-save(); painter-setRenderHint(QPainter::Antialiasing, true); painter-setRenderHint(QPainter::TextAntialiasing, true); // 1. 填充深蓝色背景 painter-fillRect(option.rect, QColor(#214a6b)); // 2. 绘制浅蓝色网格线 painter-setPen(QPen(QColor(#4d6a8f), 1)); painter-drawRect(option.rect); // 3. 计算左侧圆圈的尺寸和位置 qreal h option.rect.height(); qreal diameter h * 0.6; qreal leftMargin h * 0.1; QRectF circleRect(option.rect.left() leftMargin, option.rect.center().y() - diameter / 2.0, diameter, diameter); // 4. 绘制左侧圆圈 painter-setPen(Qt::NoPen); painter-setBrush(QColor(#8b8b8b)); painter-drawEllipse(circleRect); // 5. 绘制右侧文本 QString text index.data(Qt::DisplayRole).toString(); if (!text.isEmpty()) { painter-setPen(QColor(Qt::white)); QFont font option.font; painter-setFont(font); qreal textSpacing h * 0.1; QRectF textRect(option.rect.left() leftMargin diameter textSpacing, option.rect.top(), option.rect.width() - (leftMargin diameter textSpacing), option.rect.height()); painter-drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, text); } painter-restore(); } }; // 这里将 MainWindow 改为了 externalMonitorWidget 并继承 QWidget class externalMonitorWidget : public QWidget { public: // 添加了标准的 parent 参数 explicit externalMonitorWidget(QWidget *parent nullptr) : QWidget(parent) { setWindowTitle(圆点表格效果 (Qt5 C)); resize(1000, 600); // 1. 创建视图和模型 QTableView *tableView new QTableView(this); int row 32; int col 22; QStandardItemModel *model new QStandardItemModel(row, col, this); // 2. 设置表头文字 QStringList horizontalHeaders; QStringList verticalHeaders; for (int i 1; i col; i) horizontalHeaders QString::number(i); for (int i 1; i row; i) verticalHeaders QString::number(i); model-setHorizontalHeaderLabels(horizontalHeaders); model-setVerticalHeaderLabels(verticalHeaders); for (int i 1; i row; i) { for (int j 1; j col; j) { QStandardItem *item new QStandardItem(-179.1); model-setItem(i - 1, j - 1, item); } } // 3. 设置视图属性 tableView-setModel(model); tableView-setShowGrid(false); tableView-setSelectionMode(QAbstractItemView::NoSelection); tableView-setEditTriggers(QAbstractItemView::NoEditTriggers); // 设置表头样式 QString headerStyle R( QHeaderView::section { background-color: #214a6b; color: white; border: 1px solid #4d6a8f; } ); tableView-horizontalHeader()-setStyleSheet(headerStyle); tableView-verticalHeader()-setStyleSheet(headerStyle); // 调整行高和列宽 tableView-horizontalHeader()-setDefaultSectionSize(65); tableView-verticalHeader()-setDefaultSectionSize(30); // 4. 应用自定义代理 tableView-setItemDelegate(new DotDelegate(tableView)); // 5. 使用布局将 tableView 放入 QWidget 中替代 setCentralWidget QVBoxLayout *layout new QVBoxLayout(this); layout-setContentsMargins(0, 0, 0, 0); // 让表格完全填满 Widget不留边距 layout-addWidget(tableView); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); // 将原来的 MainWindow 改为 externalMonitorWidget externalMonitorWidget w; w.show(); return a.exec(); }进一步优化封装函数接口#include QApplication #include QWidget #include QVBoxLayout #include QTableView #include QStandardItemModel #include QStyledItemDelegate #include QPainter #include QPen #include QColor #include QHeaderView class DotDelegate : public QStyledItemDelegate { public: using QStyledItemDelegate::QStyledItemDelegate; void paint(QPainter *painter, const QStyleOptionViewItem option, const QModelIndex index) const override { painter-save(); painter-setRenderHint(QPainter::Antialiasing, true); painter-setRenderHint(QPainter::TextAntialiasing, true); // 1. 填充深蓝色背景 painter-fillRect(option.rect, QColor(#214a6b)); // 2. 绘制浅蓝色网格线 painter-setPen(QPen(QColor(#4d6a8f), 1)); painter-drawRect(option.rect); // 3. 计算左侧圆圈的尺寸和位置 qreal h option.rect.height(); qreal diameter h * 0.6; qreal leftMargin h * 0.1; QRectF circleRect(option.rect.left() leftMargin, option.rect.center().y() - diameter / 2.0, diameter, diameter); // 4. 获取动态颜色并绘制左侧圆圈 QColor circleColor QColor(#8b8b8b); // 默认灰色 // 读取我们存在 UserRole 里的颜色 QVariant colorVariant index.data(Qt::UserRole); if (colorVariant.isValid() colorVariant.canConvertQColor()) { circleColor colorVariant.valueQColor(); } painter-setPen(Qt::NoPen); painter-setBrush(circleColor); painter-drawEllipse(circleRect); // 5. 绘制右侧文本 QString text index.data(Qt::DisplayRole).toString(); if (!text.isEmpty()) { painter-setPen(QColor(Qt::white)); QFont font option.font; painter-setFont(font); qreal textSpacing h * 0.1; QRectF textRect(option.rect.left() leftMargin diameter textSpacing, option.rect.top(), option.rect.width() - (leftMargin diameter textSpacing), option.rect.height()); painter-drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, text); } painter-restore(); } }; class externalMonitorWidget : public QWidget { public: explicit externalMonitorWidget(QWidget *parent nullptr) : QWidget(parent) { setWindowTitle(圆点表格效果 (Qt5 C)); resize(1000, 600); // 1. 创建视图和模型 tableView new QTableView(this); int row 32; int col 22; model new QStandardItemModel(row, col, this); // 2. 设置表头文字 QStringList horizontalHeaders; QStringList verticalHeaders; for (int i 1; i col; i) horizontalHeaders QString::number(i); for (int i 1; i row; i) verticalHeaders QString::number(i); model-setHorizontalHeaderLabels(horizontalHeaders); model-setVerticalHeaderLabels(verticalHeaders); // 初始化填充数据默认为灰色和 -179.1 for (int i 1; i row; i) { for (int j 1; j col; j) { QStandardItem *item new QStandardItem(-179.1); model-setItem(i - 1, j - 1, item); } } // 3. 设置视图属性 tableView-setModel(model); tableView-setShowGrid(false); tableView-setSelectionMode(QAbstractItemView::NoSelection); tableView-setEditTriggers(QAbstractItemView::NoEditTriggers); // 设置表头样式 QString headerStyle R( QHeaderView::section { background-color: #214a6b; color: white; border: 1px solid #4d6a8f; } ); tableView-horizontalHeader()-setStyleSheet(headerStyle); tableView-verticalHeader()-setStyleSheet(headerStyle); tableView-horizontalHeader()-setDefaultSectionSize(65); tableView-verticalHeader()-setDefaultSectionSize(30); // 4. 应用自定义代理 tableView-setItemDelegate(new DotDelegate(tableView)); // 5. 布局 QVBoxLayout *layout new QVBoxLayout(this); layout-setContentsMargins(0, 0, 0, 0); layout-addWidget(tableView); // // 展示如何调用接口测试代码实际使用时可删除 // 将第一列设置为绿色第二列红色第三列灰色 for (int i 0; i row; i) { setItemGreen(i, 0); // 第一列变绿 setItemRed(i, 1); // 第二列变红 setItemGray(i, 2); // 第三列变灰 setItemText(i, 3, OK); // 第四列修改文字 setItemText(i, 4, ERR); // 第五列修改文字 } // } // 封装的接口 // 通用接口修改指定行、列的圆圈颜色 // 注意row 和 col 都是从 0 开始计数的 void setItemColor(int row, int col, const QColor color) { QModelIndex index model-index(row, col); if (index.isValid()) { model-setData(index, color, Qt::UserRole); } } // 变绿 void setItemGreen(int row, int col) { setItemColor(row, col, QColor(#00FF00)); // 或者 QColor(Qt::green) } // 变红 void setItemRed(int row, int col) { setItemColor(row, col, QColor(#FF0000)); // 或者 QColor(Qt::red) } // 变灰 void setItemGray(int row, int col) { setItemColor(row, col, QColor(#8b8b8b)); // 之前的默认灰色 } // 修改显示的数字 void setItemText(int row, int col, const QString text) { QModelIndex index model-index(row, col); if (index.isValid()) { model-setData(index, text, Qt::DisplayRole); } } // 获取当前TableView的指针如果需要外部彻底接管可以开放这个 QTableView* getTableView() { return tableView; } private: QTableView *tableView; QStandardItemModel *model; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); externalMonitorWidget w; w.show(); return a.exec(); }再进一步拆分把类以.h,.cpp的形式来写。#ifndef DOTDELEGATE_H #define DOTDELEGATE_H #include QStyledItemDelegate class DotDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit DotDelegate(QObject *parent nullptr); void paint(QPainter *painter, const QStyleOptionViewItem option, const QModelIndex index) const override; }; #endif // DOTDELEGATE_H#include dotdelegate.h #include QPainter #include QPen #include QColor #include QVariant DotDelegate::DotDelegate(QObject *parent) : QStyledItemDelegate(parent) {} void DotDelegate::paint(QPainter *painter, const QStyleOptionViewItem option, const QModelIndex index) const { painter-save(); painter-setRenderHint(QPainter::Antialiasing, true); painter-setRenderHint(QPainter::TextAntialiasing, true); // 1. 填充深蓝色背景 painter-fillRect(option.rect, QColor(#214a6b)); // 2. 绘制浅蓝色网格线 painter-setPen(QPen(QColor(#4d6a8f), 1)); painter-drawRect(option.rect); // 3. 计算左侧圆圈的尺寸和位置 qreal h option.rect.height(); qreal diameter h * 0.6; qreal leftMargin h * 0.1; QRectF circleRect(option.rect.left() leftMargin, option.rect.center().y() - diameter / 2.0, diameter, diameter); // 4. 获取动态颜色并绘制左侧圆圈 QColor circleColor QColor(#8b8b8b); // 默认灰色 QVariant colorVariant index.data(Qt::UserRole); if (colorVariant.isValid() colorVariant.canConvertQColor()) { circleColor colorVariant.valueQColor(); } painter-setPen(Qt::NoPen); painter-setBrush(circleColor); painter-drawEllipse(circleRect); // 5. 绘制右侧文本 QString text index.data(Qt::DisplayRole).toString(); if (!text.isEmpty()) { painter-setPen(QColor(Qt::white)); QFont font option.font; painter-setFont(font); qreal textSpacing h * 0.1; QRectF textRect(option.rect.left() leftMargin diameter textSpacing, option.rect.top(), option.rect.width() - (leftMargin diameter textSpacing), option.rect.height()); painter-drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, text); } painter-restore(); }#ifndef EXTERNALMONITORWIDGET_H #define EXTERNALMONITORWIDGET_H #include QWidget #include QColor #include QString class QTableView; class QStandardItemModel; class externalMonitorWidget : public QWidget { Q_OBJECT public: explicit externalMonitorWidget(QWidget *parent nullptr); // 封装的接口 void setItemColor(int row, int col, const QColor color); void setItemGreen(int row, int col); void setItemRed(int row, int col); void setItemGray(int row, int col); void setItemText(int row, int col, const QString text); QTableView* getTableView() const; private: QTableView *tableView; QStandardItemModel *model; }; #endif // EXTERNALMONITORWIDGET_H#include externalmonitorwidget.h #include dotdelegate.h #include QTableView #include QStandardItemModel #include QHeaderView #include QVBoxLayout externalMonitorWidget::externalMonitorWidget(QWidget *parent) : QWidget(parent) { setWindowTitle(圆点表格效果 (Qt5 C)); resize(1000, 600); // 1. 创建视图和模型 tableView new QTableView(this); int row 32; int col 22; model new QStandardItemModel(row, col, this); // 2. 设置表头文字 QStringList horizontalHeaders; QStringList verticalHeaders; for (int i 1; i col; i) horizontalHeaders QString::number(i); for (int i 1; i row; i) verticalHeaders QString::number(i); model-setHorizontalHeaderLabels(horizontalHeaders); model-setVerticalHeaderLabels(verticalHeaders); // 初始化填充数据默认为灰色和 -179.1 for (int i 0; i row; i) { for (int j 0; j col; j) { QStandardItem *item new QStandardItem(-179.1); model-setItem(i, j, item); } } // 3. 设置视图属性 tableView-setModel(model); tableView-setShowGrid(false); tableView-setSelectionMode(QAbstractItemView::NoSelection); tableView-setEditTriggers(QAbstractItemView::NoEditTriggers); // 设置表头样式 QString headerStyle R( QHeaderView::section { background-color: #214a6b; color: white; border: 1px solid #4d6a8f; } ); tableView-horizontalHeader()-setStyleSheet(headerStyle); tableView-verticalHeader()-setStyleSheet(headerStyle); tableView-horizontalHeader()-setDefaultSectionSize(65); tableView-verticalHeader()-setDefaultSectionSize(30); // 4. 应用自定义代理 tableView-setItemDelegate(new DotDelegate(tableView)); // 5. 布局 QVBoxLayout *layout new QVBoxLayout(this); layout-setContentsMargins(0, 0, 0, 0); layout-addWidget(tableView); } // 封装的接口实现 void externalMonitorWidget::setItemColor(int row, int col, const QColor color) { QModelIndex index model-index(row, col); if (index.isValid()) { model-setData(index, color, Qt::UserRole); } } void externalMonitorWidget::setItemGreen(int row, int col) { setItemColor(row, col, QColor(#00FF00)); } void externalMonitorWidget::setItemRed(int row, int col) { setItemColor(row, col, QColor(#FF0000)); } void externalMonitorWidget::setItemGray(int row, int col) { setItemColor(row, col, QColor(#8b8b8b)); } void externalMonitorWidget::setItemText(int row, int col, const QString text) { QModelIndex index model-index(row, col); if (index.isValid()) { model-setData(index, text, Qt::DisplayRole); } } QTableView* externalMonitorWidget::getTableView() const { return tableView; }#include QApplication #include externalmonitorwidget.h int main(int argc, char *argv[]) { QApplication a(argc, argv); externalMonitorWidget w; w.show(); // 演示接口调用 // 将第1列变绿第2列变红第3列变灰第4列修改文字 for (int i 0; i 32; i) { w.setItemGreen(i, 0); w.setItemRed(i, 1); w.setItemGray(i, 2); w.setItemText(i, 3, OK); w.setItemText(i, 4, ERR); } return a.exec(); }

相关新闻

OpenAI开源Codex Harness:真正改变的不是聊天框,而是AI Agent生产系统

OpenAI开源Codex Harness:真正改变的不是聊天框,而是AI Agent生产系统

写在前面 欢迎大家关注Rocky的公众号:WeThinkIn 欢迎大家关注Rocky的知乎:Rocky Ding 《三年面试五年模拟》AIGC/LLM/AI Agent算法工程师/开发工程师求职面试秘籍独家资源:【三年面试五年模拟】WeThinkIn/AIGC-Interview-Book,欢迎…

2026/8/23 7:25:46 阅读更多 →
Enterprise Architect 入门实战:从 UML 建模到代码生成

Enterprise Architect 入门实战:从 UML 建模到代码生成

1. 项目概述:从“EA”的迷雾到“Enterprise Architect”的利器刚接触“EA”这个词,很多人第一反应可能是那个游戏公司,或者是在金融交易圈里常说的“专家顾问”(Expert Advisor)。但如果你身处软件开发、系统设计或者企…

2026/8/23 7:25:46 阅读更多 →
从零实现流式Markdown解析器:状态机与渐进式渲染实战

从零实现流式Markdown解析器:状态机与渐进式渲染实战

在实际前端面试中,流式 Markdown 解析器是一个能很好考察候选人综合能力的问题。它不像简单的算法题有标准答案,而是需要你理解流式处理、状态机、词法分析、语法解析、异步渲染等多个概念,并能将它们组合成一个可工作的方案。很多开发者对 M…

2026/8/23 7:25:46 阅读更多 →

最新新闻

Java大厂面试实战:核心、分布式与系统设计解析

Java大厂面试实战:核心、分布式与系统设计解析

1. Java大厂面试实战:三轮技术问答深度解析 最近帮几位准备跳槽的朋友模拟面试,发现很多工作3-5年的Java开发者在面对大厂系统化考察时容易陷入"能干活但说不清"的困境。本文将以模拟面试的形式,还原互联网大厂Java岗位的真实技术考…

2026/8/23 8:27:31 阅读更多 →
6.3.3 drm_exec —— 多 BO 无死锁加锁框架

6.3.3 drm_exec —— 多 BO 无死锁加锁框架

6.3.2 剖析的 ww_mutex 提供了多锁死锁避免的原语,但其「取号 → 遍历加锁 → 遇 -EDEADLK 回退 → 从冲突锁重试」的样板逻辑,若由每个驱动手写,既繁琐又极易在错误路径上遗漏回退而泄漏锁。drm_exec 正是对这一模式的官方封装:调…

2026/8/23 8:27:31 阅读更多 →
Python招聘推荐系统:Django与协同过滤实战

Python招聘推荐系统:Django与协同过滤实战

1. 项目概述:当招聘遇上机器学习 去年帮学弟调试毕业设计时,接触到一个挺有意思的Python招聘推荐系统。这个项目把Django框架、协同过滤算法和数据可视化技术打包在一起,解决了求职者和招聘方的双向匹配问题。不同于普通的招聘网站&#xff0…

2026/8/23 8:27:31 阅读更多 →
C++模板编程:typename与class关键字的区别与应用场景详解

C++模板编程:typename与class关键字的区别与应用场景详解

1. 从一次编译错误说起&#xff1a;template的两种面孔 前两天在review团队里一个实习生的代码时&#xff0c;碰到了一个挺有意思的问题。他在实现一个泛型的链表容器&#xff0c;代码大致是这样的&#xff1a; template<class T> class LinkedList { public:void inse…

2026/8/23 8:27:31 阅读更多 →
YOLO 全栈性能调优:训练速度、显存占用与推理效率全方位优化

YOLO 全栈性能调优:训练速度、显存占用与推理效率全方位优化

做工业视觉项目的人大概率都遇到过这类场景:数据集刚标注完,一开训练就提示显存溢出;好不容易调小 batch 跑起来,一轮要训大半个小时,百轮数据要等三四天;好不容易训完部署到边缘端,帧率不到 10,完全达不到实时要求。 很多人遇到性能问题第一反应是升级硬件、加显存、…

2026/8/23 8:27:31 阅读更多 →
嵌入式大赛命题解析:从瑞芯微RK3568到边缘AI实战

嵌入式大赛命题解析:从瑞芯微RK3568到边缘AI实战

1. 项目概述&#xff1a;一次产教融合的深度实践最近在嵌入式圈子里&#xff0c;一个消息引起了不小的讨论&#xff1a;飞凌嵌入式与瑞芯微正式成为2025年全国大学生嵌入式大赛的命题企业。这不仅仅是一个简单的商业合作新闻&#xff0c;对于像我这样长期关注嵌入式技术发展和人…

2026/8/23 8:26:31 阅读更多 →

日新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态&#xff0c;宏观上观察到的光是由无数个微观的光量子组成的&#xff0c;每个光子在产生的瞬间&#xff0c;其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前&#xff0c;在微观层面&#xff0c;每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”&#xff0c;而是SIP会话的动态重定向你有没有遇到过这样的场景&#xff1a;客服坐席A正在和客户通电话&#xff0c;突然需要把这通对话无缝转给专家坐席B&#xff0c;客户完全感知不到中间的断连——既没听到忙音&#xff0c;也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack&#xff1f;如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法&#xff0c;那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态&#xff0c;宏观上观察到的光是由无数个微观的光量子组成的&#xff0c;每个光子在产生的瞬间&#xff0c;其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前&#xff0c;在微观层面&#xff0c;每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”&#xff0c;而是SIP会话的动态重定向你有没有遇到过这样的场景&#xff1a;客服坐席A正在和客户通电话&#xff0c;突然需要把这通对话无缝转给专家坐席B&#xff0c;客户完全感知不到中间的断连——既没听到忙音&#xff0c;也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack&#xff1f;如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法&#xff0c;那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速&#xff1a;macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/22 18:08:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南&#xff1a;3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#xff1f;ncmdump解密工具帮你轻松解决这个困…

2026/8/22 7:31:03 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片&#xff1a;为英语学习 App 打造桌面级学习助手适用平台&#xff1a;HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0&#xff08;API 26 Beta&#xff09;新增了 AgentCard 智能体卡片能力&#xff0c;这是继 HMAF&#xff08;鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →