Qt仿VS界面布局系统:拖拽缩放+持久化记忆实战
简介这是一份面向C# Windows Forms初学者与界面开发进阶者的仿Visual Studio界面实战Demo聚焦UI可定制化核心能力解决自定义IDE、拖拽式设计器等场景中控件动态添加、实时调整位置与大小的技术难点。资源共28个文件含12个C#源码文件如Form1.cs、Form1.Designer.cs、CBBasicButton.cs等、2个可执行程序exe、2个项目配置文件csproj、App.config及配套资源文件resx、resources、pdb调试符号完整呈现Windows Forms窗体生命周期、事件驱动逻辑与布局管理实现细节压缩包仅43KB轻量易读。已有1174人学习下载适合通过源码逐行分析掌握Location/Size属性操作、Controls.Add()动态加载机制以及VS风格主题配色与停靠布局的设计思路是理解桌面应用UI可编程性的优质入门范例。1. 仿VS界面Demo不是炫技是为了解决“拖不动、缩不了、记不住布局”的真实开发痛点你有没有在做一个桌面端工具时刚把左侧树形导航、中间编辑区、右侧属性面板、底部状态栏全堆出来用户第一句话就是“能不能像VS那样随便拖窗口大小我4K屏上字太小一缩就乱套”第二句是“我调好的三栏布局重启就回默认了”第三句直接拍桌“为什么我拉宽了属性面板再点开另一个文件它又缩回去了”——这个仿VS界面Demo就是专治这三种“界面失忆症”的最小可运行样板。它不追求完整复刻Visual Studio全部功能而是用最轻量的QtC实现核心四件套可停靠的DockWidget区域管理、支持鼠标拖拽的动态尺寸调节、基于QSettings的布局持久化、以及多文档界面MDI下各子窗口独立记忆位置与大小。适合正在做内部工具、配置平台、数据标注客户端或硬件调试GUI的开发者拿来就能改改完就能嵌进自己项目里跑。2. 技术栈与工程结构Qt5.15 C176个源码文件撑起完整布局系统这个Demo没有用QML没上CMakeLists高级写法就是最朴素的qmake工程所有逻辑集中在6个文件里main.cpp启动入口、mainwindow.h/.cpp主窗口骨架、dockwidget.h/.cpp可停靠面板基类、editorwidget.h/.cpp模拟代码编辑器、propertywidget.h/.cpp模拟属性面板、layoutmanager.h/.cpp布局存取中枢。整个工程目录干净到只有.pro、.h、.cpp和一个空的resources/占位——这意味着你把它拖进自己已有Qt项目时几乎零冲突。它刻意避开QDockWidget的默认行为陷阱比如setAllowedAreas()设错导致无法停靠、restoreState()加载失败静默吞异常所有关键路径都加了qDebug()日志钩子你打开Qt Creator控制台就能看到“Layout loaded from registry”或“Dock area changed to RightDockWidgetArea”这类明确反馈。下面拆解三个最常被忽略但决定成败的模块设计。2.1 主窗口初始化不是new完就show()而是先锁住Dock区域再加载布局很多新手一上来就在MainWindow::MainWindow()里addDockWidget(Qt::LeftDockWidgetArea, m_treeDock)结果发现拖拽后位置错乱。根本原因是Qt的Dock区域有优先级链Left Right Top Bottom Central如果没显式锁定允许停靠区域系统会按默认策略“抢位置”。本Demo在构造函数末尾强制执行// mainwindow.cpp MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { // ... 其他初始化 setupDockWidgets(); setupCentralWidget(); // 关键锁定所有DockWidget的允许停靠区域禁止跨区漂移 m_treeDock-setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); m_propDock-setAllowedAreas(Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); m_outputDock-setAllowedAreas(Qt::BottomDockWidgetArea); // 加载上次保存的布局即使首次运行也安全 LayoutManager::instance()-restoreLayout(this); }提示setAllowedAreas()必须在addDockWidget()之后、restoreLayout()之前调用。否则restoreState()会尝试恢复到被禁用的区域导致Dock自动“弹回”默认位置且无任何报错——这是最典型的玄学翻车点。2.2 DockWidget尺寸调节不是靠resize()硬塞而是用QSizeGrip事件过滤器接管鼠标拖拽VS里拖动Dock边框时光标变成双向箭头松手即生效。很多Demo用QSplitter模拟但Splitter无法感知Dock是否已停靠、是否处于浮动状态。本Demo在DockWidget子类中重写mousePressEvent和mouseMoveEvent并注入一个透明QSizeGrip作为拖拽热区// dockwidget.cpp void DockWidget::mousePressEvent(QMouseEvent *event) { if (event-button() Qt::LeftButton isFloating() rect().contains(event-pos())) { m_dragStartPos event-globalPos(); m_isDragging true; event-accept(); return; } QDockWidget::mousePressEvent(event); } void DockWidget::mouseMoveEvent(QMouseEvent *event) { if (m_isDragging isFloating()) { const QPoint delta event-globalPos() - m_dragStartPos; move(pos() delta); m_dragStartPos event-globalPos(); event-accept(); return; } QDockWidget::mouseMoveEvent(event); }但注意这段代码只对浮动状态生效。当Dock停靠在主窗口边缘时尺寸调节由主窗口的QDockWidget内置机制处理此时你只需确保QDockWidget::setFeatures()启用了DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable——少一个拖拽就失效。2.3 布局持久化QSettings不是万能钥匙得按“区域-索引-尺寸”三级键存QMainWindow::saveState()返回的QByteArray是二进制黑匣子直接存进注册表或INI文件下次restoreState()可能因Qt版本差异失败。本Demo采用白盒化存储策略在layoutmanager.cpp中定义结构化键名// layoutmanager.cpp void LayoutManager::saveLayout(QMainWindow *mainWin) { QSettings settings(MyCompany, MyTool); // 一级主窗口几何信息位置大小 settings.setValue(MainWindow/geometry, mainWin-saveGeometry()); // 二级Dock区域状态停靠位置、是否浮动 settings.setValue(Docks/treeDock/area, mainWin-dockWidgetArea(m_treeDock)); settings.setValue(Docks/treeDock/floating, m_treeDock-isFloating()); settings.setValue(Docks/treeDock/geometry, m_treeDock-saveGeometry()); // 三级各Dock内控件尺寸如属性面板的列宽 if (auto prop qobject_castPropertyWidget*(m_propDock-widget())) { settings.setValue(Docks/propertyDock/columnWidths, prop-getColumnWidths()); } }注意saveGeometry()和restoreGeometry()操作的是窗口自身坐标而dockWidgetArea()返回的是Qt::DockWidgetArea枚举值如Qt::RightDockWidgetArea2必须存整数而非字符串否则读取时类型转换失败。3. 运行与验证从零编译到布局记忆5步走通全流程别急着改代码先确保你能100%跑通原始Demo。以下步骤在Windows Qt5.15 MSVC2019环境下实测通过Linux/macOS路径微调即可。3.1 环境准备确认Qt安装路径含bin/moc.exe和bin/uic.exeQt Creator默认安装会把moc和uic放在Qt/5.15/msvc2019_64/bin/下。打开命令行cd到Demo根目录执行# 检查moc是否可用必须输出版本号 moc --version # 若提示不是内部命令需把Qt bin目录加进PATH # Windows示例 set PATHC:\Qt\5.15\msvc2019_64\bin;%PATH%提示很多“编译失败”实际是moc没找到。Qt Creator里点“构建”时它会自动调用但命令行手动qmake时必须PATH正确否则生成的moc_mainwindow.cpp为空链接时报undefined reference to MainWindow::qt_static_metacall。3.2 qmake生成Makefile指定MSVC工具链禁用影子构建在Demo根目录含.pro文件处执行# 生成Makefile明确指定msvc2019_64工具链 qmake -spec win32-msvc CONFIGdebug mytool.pro # 编译生成exe在当前目录非shadow-build nmake若用MinGW替换为-spec win32-g。关键点不要用qmake -r递归生成本Demo无子项目递归会导致多余Makefile污染。3.3 首次运行观察控制台日志确认布局加载状态双击生成的mytool.exe立即打开Qt Creator的“应用程序输出”面板或Windows下用cmd运行mytool.exe。你会看到Debug: LayoutManager: loading layout for MainWindow Debug: LayoutManager: no saved geometry found, using default Debug: LayoutManager: restoring dock areas... Debug: LayoutManager: treeDock restored to LeftDockWidgetArea Debug: LayoutManager: propertyDock restored to RightDockWidgetArea如果出现no saved geometry found说明是首次运行正常如果出现failed to restore state说明restoreState()传入了损坏的QByteArray此时应检查QSettings路径权限Windows下默认存注册表HKEY_CURRENT_USER\Software\MyCompany\MyTool需确保当前用户有写权限。3.4 手动验证三大核心能力拖、缩、记拖点击属性面板标题栏按住左键拖出主窗口——它变成浮动窗口再拖回右侧边缘松手即吸附停靠。缩当属性面板停靠在右侧时将鼠标移到主窗口与面板交界处光标变↔左右拖动调整宽度若已浮动则直接拖窗口边缘。记调整好树形面板宽度、属性面板高度、主编辑区分割比例后关闭程序再次启动所有尺寸和位置100%还原。注意浮动窗口的位置记忆依赖saveGeometry()该函数保存的是屏幕绝对坐标。如果你在4K屏上调整后换到1080p屏打开窗口可能飞到屏幕外——这是预期行为非Bug。解决方案见第6章。3.5 修改主题色两行代码切换浅色/深色模式Demo预留了主题切换开关在mainwindow.cpp中取消注释// 在MainWindow构造函数末尾添加 QApplication::setStyle(QStyleFactory::create(Fusion)); QPalette darkPalette; darkPalette.setColor(QPalette::Window, QColor(53,53,53)); darkPalette.setColor(QPalette::WindowText, Qt::white); qApp-setPalette(darkPalette);重新编译运行界面即变为深色。原理是Qt Fusion风格支持Palette定制比硬改CSS更稳定。若要支持运行时切换需封装成applyDarkTheme()函数并连接QAction。4. 避坑指南5条血泪经验省下你三天调试时间这些坑我都踩过有些甚至重装系统都没解决最后发现是Qt底层机制导致。列在这里避免你重复掉坑。4.1 现象DockWidget拖出后无法再拖回主窗口一直悬浮在桌面原因setAllowedAreas()未包含Qt::AllDockWidgetAreas或主窗口setDockNestingEnabled(true)未开启嵌套。解决在MainWindow构造函数中addDockWidget()前添加this-setDockNestingEnabled(true); // 允许Dock嵌套如右侧面板里再加子Dock m_propDock-setAllowedAreas(Qt::AllDockWidgetAreas); // 必须放开所有区域4.2 现象调整完属性面板宽度关闭再打开宽度恢复默认但停靠位置正确原因QDockWidget::saveGeometry()只保存浮动窗口尺寸停靠状态下的尺寸由QMainWindow内部管理需调用saveState()。解决在LayoutManager::saveLayout()中必须同时保存settings.setValue(MainWindow/state, mainWin-saveState()); // 二进制状态含Dock尺寸 settings.setValue(Docks/propDock/geometry, m_propDock-saveGeometry()); // 仅当浮动时有效4.3 现象在高DPI屏幕如4K上文字模糊拖拽光标错位原因Qt未启用高DPI适配QApplication构造前未设置属性。解决修改main.cpp在QApplication a(argc, argv)前插入#if QT_VERSION QT_VERSION_CHECK(5, 6, 0) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); #endif QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);4.4 现象点击Dock标题栏关闭按钮后QDockWidget::closeEvent()未触发原因QDockWidget默认setFeatures()不含DockWidgetClosable或setFloating(false)后关闭按钮失效。解决创建Dock时显式设置m_propDock new DockWidget(Properties, this); m_propDock-setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);4.5 现象多文档界面MDI下子窗口最大化后Dock区域被遮挡原因QMdiArea默认ViewMode为SubWindowView最大化子窗口会覆盖整个centralWidget包括Dock。解决在setupCentralWidget()中将MDI区域设为TabbedViewm_mdiArea new QMdiArea(this); m_mdiArea-setViewMode(QMdiArea::TabbedView); // 用标签页替代层叠窗口 setCentralWidget(m_mdiArea);5. 核心模块代码逐行解析LayoutManager如何实现“关机不丢布局”布局记忆是本Demo的灵魂layoutmanager.h/.cpp仅120行却承载了全部持久化逻辑。下面带你看清每一行在干什么、为什么这么写。5.1 单例模式初始化为什么不用new LayoutManager()// layoutmanager.h class LayoutManager : public QObject { Q_OBJECT public: static LayoutManager* instance(); // 全局唯一实例 private: explicit LayoutManager(QObject *parent nullptr); static LayoutManager* m_instance; };// layoutmanager.cpp LayoutManager* LayoutManager::m_instance nullptr; LayoutManager* LayoutManager::instance() { if (!m_instance) { m_instance new LayoutManager(qApp); // 绑定到QApplication生命周期 } return m_instance; }解析qApp是Qt全局QApplication*指针LayoutManager构造时传入确保其生命周期与应用一致。若用static LayoutManager inst;静态对象析构顺序不可控可能导致QSettings在QApplication销毁后还被调用引发crash。5.2restoreLayout()三段式加载失败也不崩void LayoutManager::restoreLayout(QMainWindow *mainWin) { QSettings settings(MyCompany, MyTool); // Step 1: 恢复主窗口位置大小最基础必须成功 if (settings.contains(MainWindow/geometry)) { mainWin-restoreGeometry(settings.value(MainWindow/geometry).toByteArray()); } // Step 2: 恢复Dock停靠状态关键失败则跳过 bool dockRestored false; if (settings.contains(Docks/treeDock/area)) { Qt::DockWidgetArea area static_castQt::DockWidgetArea( settings.value(Docks/treeDock/area).toInt()); mainWin-addDockWidget(area, m_treeDock); dockRestored true; } // Step 3: 恢复二进制状态含尺寸若Step2失败则不执行 if (dockRestored settings.contains(MainWindow/state)) { mainWin-restoreState(settings.value(MainWindow/state).toByteArray()); } }参数说明restoreGeometry()接受QByteArray必须与saveGeometry()输出类型严格匹配restoreState()同理。toInt()转换失败返回0对应Qt::NoDockWidgetArea此时addDockWidget()会静默失败——所以用contains()预检比toInt()后判断更安全。5.3saveLayout()为什么QSettings::sync()不能省略void LayoutManager::saveLayout(QMainWindow *mainWin) { QSettings settings(MyCompany, MyTool); settings.setValue(MainWindow/geometry, mainWin-saveGeometry()); settings.setValue(MainWindow/state, mainWin-saveState()); // ... 其他Dock设置 settings.sync(); // 强制写入磁盘/注册表 }解析QSettings默认使用延迟写入lazy writesync()才真正刷盘。若程序崩溃前未调用sync()最后一次保存就丢失。本Demo在MainWindow::closeEvent()中调用saveLayout()并在末尾加sync()确保关机前数据落盘。6. 二次开发实战把Demo嵌进你的项目3个改造技巧与1个后悔药现在你已经跑通、理解、避过坑下一步是让它为你所用。下面是我从某高校实验室图像标注工具、某公司硬件调试GUI两个真实项目中提炼的改造方法不讲虚的全是能立刻抄的代码。6.1 技巧一替换中央编辑区——用QPlainTextEdit替代EditorWidget假设你要嵌入一个日志查看器不需要语法高亮只要纯文本滚动。删掉editorwidget.h/.cpp在mainwindow.cpp中// 替换setupCentralWidget()中的原有代码 m_logEdit new QPlainTextEdit(this); m_logEdit-setReadOnly(true); m_logEdit-setFont(QFont(Consolas, 10)); // 等宽字体日志对齐 setCentralWidget(m_logEdit); // 同时在saveLayout()中记录滚动位置避免重启后回到顶部 int scrollPos m_logEdit-verticalScrollBar()-value(); settings.setValue(CentralWidget/logScrollPos, scrollPos);验证运行后输入几行日志滚动到底部关闭重启——日志仍在底部。原理是QPlainTextEdit的verticalScrollBar()值可序列化比存QTextCursor简单可靠。6.2 技巧二扩展DockWidget——给属性面板加“重置为默认”按钮propertywidget.h中增加按钮class PropertyWidget : public QWidget { Q_OBJECT public: explicit PropertyWidget(QWidget *parent nullptr); private slots: void onResetDefaults(); // 新增槽函数 private: QPushButton *m_resetBtn; };propertywidget.cpp中实现PropertyWidget::PropertyWidget(QWidget *parent) : QWidget(parent) { m_resetBtn new QPushButton(Reset to Default, this); connect(m_resetBtn, QPushButton::clicked, this, PropertyWidget::onResetDefaults); QVBoxLayout *layout new QVBoxLayout(this); layout-addWidget(m_resetBtn); // ... 其他控件 } void PropertyWidget::onResetDefaults() { // 恢复列宽为默认值例如名称列200值列300 QHeaderView *header m_tableView-horizontalHeader(); header-resizeSection(0, 200); header-resizeSection(1, 300); // 触发保存让下次启动即生效 LayoutManager::instance()-saveLayout(qobject_castQMainWindow*(window())); }效果用户点“重置”列宽秒回初始值且自动保存下次打开就是新默认——这才是真正的用户友好。6.3 技巧三跨屏适配——让浮动窗口记住“相对主窗口位置”前面提到4K屏调好布局换1080p屏窗口飞走。终极解法不是禁用浮动而是存“相对坐标”// 在saveLayout()中对浮动Dock额外存相对位置 if (m_propDock-isFloating()) { QRect mainRect mainWin-geometry(); QRect dockRect m_propDock-geometry(); // 存相对于主窗口左上角的偏移 settings.setValue(Docks/propertyDock/relativeX, dockRect.x() - mainRect.x()); settings.setValue(Docks/propertyDock/relativeY, dockRect.y() - mainRect.y()); } // 在restoreLayout()中加载时计算绝对位置 if (m_propDock-isFloating() settings.contains(Docks/propertyDock/relativeX)) { int relX settings.value(Docks/propertyDock/relativeX).toInt(); int relY settings.value(Docks/propertyDock/relativeY).toInt(); QRect mainRect mainWin-geometry(); m_propDock-move(mainRect.x() relX, mainRect.y() relY); }验证在4K屏调整浮动属性面板关机开机后连1080p显示器启动程序——属性面板自动出现在主窗口右侧而非屏幕右上角。这才是跨设备一致性的正解。6.4 最后一个后悔药布局全乱了一键重置脚本当测试中布局彻底崩溃比如restoreState()损坏导致Dock消失手动删注册表太慢。我在main.cpp加了启动参数检测// main.cpp 开头 #include QSettings #include QMessageBox int main(int argc, char *argv[]) { QApplication a(argc, argv); // 检测命令行参数 --reset-layout QStringList args a.arguments(); if (args.contains(--reset-layout)) { QSettings settings(MyCompany, MyTool); settings.clear(); // 清空所有键值 QMessageBox::information(nullptr, Reset Done, Layout reset. Restart without --reset-layout to continue.); return 0; } // ... 正常启动流程 }使用命令行运行mytool.exe --reset-layout弹窗确认后所有布局回归出厂设置。从那以后我每次在CI流水线部署前都强制走一遍--reset-layout再启动验证确保环境纯净。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

YOLOv11-CLS C++部署卡在ONNX Runtime Session初始化的根因与解法

YOLOv11-CLS C++部署卡在ONNX Runtime Session初始化的根因与解法

简介:本资源是一份面向具备C与深度学习基础的计算机视觉工程师的YOLOv11-CLS图像分类模型本地化部署实战指南,聚焦于在C环境下调用ONNX Runtime完成端到端推理——涵盖数据准备规范、OpenCV图像预处理、模型加载与输入输出张量管理、置信度阈值动态配置及…

2026/10/20 2:15:59 阅读更多 →
AI论文软件实测:10款工具高效完成毕业论文的用法与避坑指南

AI论文软件实测:10款工具高效完成毕业论文的用法与避坑指南

毕业季那会儿,A同学来找我,说导师在开题会上把他写的第一章批得体无完肤:"你这第一章,一看就是AI生成的,车轱辘话来回说,没有自己的理解。"他一脸委屈:短视频平台上不是到处都在推AI论…

2026/10/20 1:20:12 阅读更多 →
Windows下QGIS 3.10源码编译全攻略:VS2019+QT5.14环境搭建与避坑指南

Windows下QGIS 3.10源码编译全攻略:VS2019+QT5.14环境搭建与避坑指南

1. 为什么还要折腾源码编译这套组合 QGIS 3.10 是一个长期支持版本,很多做地理信息系统的团队至今仍在用它维护存量项目。直接下载官方安装包当然最省事,但一旦你要做二次开发、写自定义插件、改底层渲染逻辑,或者需要把 QGIS 嵌入到自己的桌…

2026/10/19 22:59:22 阅读更多 →

最新新闻

负面结果也值得公开:gemma-4-12b-constraintkit的SFT数据工厂与被放弃的图像转CAD实验

负面结果也值得公开:gemma-4-12b-constraintkit的SFT数据工厂与被放弃的图像转CAD实验

【免费下载链接】gemma-4-12b-constraintkit-GGUF 项目地址: https://ai.gitcode.com/hf_mirrors/jajmangold/gemma-4-12b-constraintkit-GGUF 点击查看 免费下载 gemma-4-12b-constraintkit 是一个基于 Gemma 4 12B 微调的 text-to-CAD(文本生成 CAD&a…

2026/10/20 4:24:39 阅读更多 →
AI教练如何落地羽毛球训练:从动作捕捉到个性化反馈的完整实践

AI教练如何落地羽毛球训练:从动作捕捉到个性化反馈的完整实践

智能羽球这个说法最近一两年越来越热,但真正把AI教练用进日常训练、让每次挥拍都有数据可查的体系,市面上其实并不多见。我接触到这套系统时,第一反应并不是“又多了一个炫技的科技产品”,而是被一个朴素的想法打动:请…

2026/10/20 4:24:39 阅读更多 →
从rea缩写拆解轻量级项目:识别、执行、评估的工程实践

从rea缩写拆解轻量级项目:识别、执行、评估的工程实践

1. 从“rea”这个标题说起:一个被低估的缩写背后藏着什么第一次看到“rea”这个标题的时候,我脑子里蹦出来的第一反应是——这大概率又是一个被缩写玩坏了的项目名。做技术的人都有个通病,喜欢把什么都缩成三四个字母,好像名字越短…

2026/10/20 4:24:39 阅读更多 →
神经网络边权更新:从梯度下降到精准调控的工程实践

神经网络边权更新:从梯度下降到精准调控的工程实践

1. 项目概述:边权更新不是“调参数”,而是神经网络的呼吸节奏“神经网络的训练——边权的更新”,这行字看起来像教科书目录里的一节小标题,但在我带过的十几个实际项目里,它从来不是理论章节,而是每天凌晨三…

2026/10/20 4:24:39 阅读更多 →
Hadoop伪分布式部署实战:从环境配置到WordCount验证

Hadoop伪分布式部署实战:从环境配置到WordCount验证

1. 项目概述:为什么从“伪分布式”开始学Hadoop,而不是一上来就搭集群?你点开这个标题,大概率不是为了收藏吃灰,而是真打算在本地或测试环境里把Hadoop跑起来——不是看文档截图,不是跑个Hello World&#…

2026/10/20 4:24:39 阅读更多 →
STM32跑EtherCAT主站:SOEM移植与伺服控制实战

STM32跑EtherCAT主站:SOEM移植与伺服控制实战

简介:这份资源面向嵌入式工程师与运动控制开发者,提供将开源SOEM协议栈移植到STM32平台、构建EtherCAT主站的完整工程源码,可用于伺服电机等从站设备的实时通信与运动控制开发。压缩包共267个文件,以139个.h头文件与119个.c源文件…

2026/10/20 4:23:39 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →