WinForms DataGridView高保真打印引擎:支持样式同步与动态分页

简介:这是一套面向C# WinForms开发者的通用打印功能实现方案,专为解决DataGridView控件数据按需排版、样式化输出至打印机或预览窗口的常见需求而设计。资源完整封装了基于PrintDocument的核心打印逻辑,并集成PageSetupDialog、PrintPreviewDialog等标准对话框配置,支持灵活设置页边距、纸张方向、字体样式及行列对齐等显示效果,适用于报表导出、单据打印等业务场景。压缩包共45个文件,涵盖11个核心C#源码(含MyDLL.cs、PrintClass.cs、Frm_PrintSet窗体系列)、3个可执行exe、3个dll及配套resx资源文件、sln/suo工程文件,另有数据库文件(mdf/ldf)和使用说明文档,整体仅319KB,轻量易集成。目前已有284人学习下载,提供从DLL构建、控件绑定、打印设置到预览调试的全流程代码支撑,目录结构清晰分层,含TransferPrint与DLLFullPrint双工程示例,便于开发者快速复用或二次开发。

1. 万能打印模块(将DataGridView控件中的数据指定样式打印):不是套壳截图,而是真·可编程排版的 Windows Forms 打印控制台

你有没有试过在 WinForms 项目里点一下“打印”按钮,结果弹出个黑乎乎的 PrintPreviewDialog,里面表格歪斜、字体糊成一片、表头没加粗、页眉页脚死活对不齐,更别说按列宽自动缩放、跨页保留表头、导出 PDF 时中文乱码……最后只能妥协:把 DataGridView 截图 → 粘贴进 Word → 手动调格式 → 打印。这不是开发,是 UI 搬运工。这个「万能打印模块」不是又一个封装了 PrintDocument 的 Demo,它是一套可声明式定义样式、支持分页逻辑干预、兼容 GDI+ 渲染精度、能直连物理打印机或生成高保真 PDF 的 DataGridView 专用打印引擎。它不替换你的 DataGridView,而是作为它的“打印影子”存在——你改数据源,它自动重绘;你调用 DataGridViewCellStyle,它原样复刻到打印流;你设置 ColumnHeadersHeightSizeMode,它决定是否跨页断行。适合正在交付医疗报表系统、仓储出入库单、教务成绩汇总等需要合规留痕、样式固定、批量输出场景的 WinForms 开发者。如果你还在用DrawString硬算坐标画表格,这篇就是你的后悔药。


2. 核心设计原理与模块选型依据:为什么不用 ReportViewer,也不手写 PrintDocument 全流程?

2.1 为什么绕开 ReportViewer?——性能、定制性与部署三重枷锁

ReportViewer 在 .NET Framework 下依赖 Microsoft.ReportViewer.WinForms.dll,版本碎片严重(v10/v12/v14/v15),VS 设计器拖拽生成的 RDLC 文件本质是 XML + 表达式,无法动态绑定运行时构造的 DataTable 或 List ,更无法响应 DataGridView 的实时样式变更。某高校教务系统曾因升级 VS 2022 导致 ReportViewer 控件报错“Could not load file or assembly 'Microsoft.ReportViewer.Common'”,回退耗时 3 天。而本模块直接操作 DataGridView 的Columns,Rows,DefaultCellStyle属性树,所有样式(如DefaultCellStyle.BackColor = Color.LightBlue)在打印时 1:1 映射为 GDI+ 的SolidBrush和StringFormat,无中间 DSL 解析层,零反射开销。

2.2 为什么基于 PrintDocument 而非第三方 PDF 库?——可控性与调试确定性

有开发者尝试用 iTextSharp 或 QuestPDF 生成 PDF 再打印,但问题立刻浮现:PDF 生成是离线过程,无法实时预览分页效果;字体嵌入规则复杂,微软雅黑在 Linux 服务器上渲染异常;且无法响应用户在 PrintPreviewDialog 中手动调整页边距。本模块严格遵循 GDI+ 打印管线:PrintDocument.PrintPage事件中,用e.Graphics直接绘制,e.PageSettings可被用户通过PageSetupDialog修改,e.HasMorePages由模块内部按行高累加器动态计算。这意味着你能在调试器里单步进入OnPrintPage(),看到每一行e.Graphics.DrawString()的坐标和字体大小——这是黑匣子库永远给不了的掌控力。

2.3 样式映射机制:从 DataGridViewCellStyle 到 GDI+ 对象的精准翻译

模块核心是StyleMapper类,它解决的关键问题是:DataGridView 的DefaultCellStyle.Font是Font对象,但 GDI+ 绘制需Font实例;DefaultCellStyle.Alignment是DataGridViewContentAlignment枚举,需转为StringFormat的Alignment和LineAlignment。例如:

// DataGridView 中设置: dataGridView1.Columns["Score"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight; dataGridView1.Columns["Score"].DefaultCellStyle.Font = new Font("微软雅黑", 10f, FontStyle.Bold); // StyleMapper 自动转换为: var stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Far; // 右对齐 stringFormat.LineAlignment = StringAlignment.Center; // 垂直居中 var gdiFont = new Font("微软雅黑", 10f, FontStyle.Bold); // 直接复用

提示:StringFormat必须用new创建,不可复用静态实例,否则多线程打印时会因StringFormat非线程安全导致字符错位。

2.4 分页策略:不是简单按行数切分,而是按像素高度动态裁剪

常见错误是if (currentY > pageHeight) { e.HasMorePages = true; },这会导致最后一行被截断。本模块采用累积行高检测法:先遍历所有行,用Graphics.MeasureString()计算每行实际渲染高度(考虑行高、字体、行间距),维护currentY和pageHeight = e.MarginBounds.Height。当currentY + nextRowHeight > pageHeight时,触发分页,并强制将当前行完整移至下一页(避免半行打印)。关键代码如下:

private void DrawRows(PrintPageEventArgs e, int startRowIndex, ref float currentY) { var g = e.Graphics; var bounds = e.MarginBounds; for (int i = startRowIndex; i < dataGridView1.Rows.Count; i++) { var row = dataGridView1.Rows[i]; if (row.Visible == false) continue; // 计算该行实际高度(考虑行高、字体、Padding) float rowHeight = GetRowHeight(row); // 检查是否超出页面剩余空间 if (currentY + rowHeight > bounds.Bottom) { // 触发分页:标记还有更多页,退出循环 e.HasMorePages = true; nextPageStartRowIndex = i; // 记录下一页起始行 return; } // 绘制该行 DrawRow(g, row, bounds.Left, currentY, bounds.Width); currentY += rowHeight; } }

GetRowHeight()内部会读取row.DefaultCellStyle.Font并调用g.MeasureString("M", font).Height获取基准高度,再叠加row.Height和dataGridView1.RowTemplate.Height的差值,确保与屏幕显示完全一致。


3. 快速集成与基础打印:三步完成从 DataGridView 到打印机的端到端链路

3.1 引用与初始化:无需 NuGet,纯 .NET Framework 4.6.1+ 原生支持

模块以单个.cs文件形式提供(DataGridViewPrinter.cs),无外部依赖。只需将其添加到 WinForms 项目中,确保目标框架 ≥ 4.6.1(因使用Span<T>优化字符串测量)。初始化仅需两行:

// 在窗体类中声明 private DataGridViewPrinter printer; // 在窗体 Load 事件中初始化 private void Form1_Load(object sender, EventArgs e) { printer = new DataGridViewPrinter(dataGridView1); // 可选:启用 PDF 输出模式(需额外引用 System.Drawing.Common) // printer.OutputMode = OutputMode.Pdf; }

DataGridViewPrinter构造函数接收DataGridView实例,自动订阅其ColumnWidthChanged,RowHeightChanged,DataSourceChanged事件,实现样式变更的自动同步。

3.2 最简打印调用:一行代码触发标准打印对话框

private void btnPrint_Click(object sender, EventArgs e) { try { printer.Print(); // 弹出 PrintDialog,用户选择打印机后开始打印 } catch (Exception ex) { MessageBox.Show($"打印失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }

Print()方法内部执行:

  1. 调用PrintDialog.ShowDialog()获取用户选择的打印机;
  2. 创建PrintDocument实例并绑定PrintPage事件;
  3. 调用PrintDocument.Print()启动 GDI+ 渲染管线;
  4. 所有异常(如打印机脱机、纸张尺寸不匹配)均抛出可捕获的Win32Exception或InvalidOperationException。

3.3 预览模式:用 PrintPreviewDialog 替代 PrintDialog

private void btnPreview_Click(object sender, EventArgs e) { var preview = new PrintPreviewDialog(); preview.Document = printer.GetPrintDocument(); // 获取已配置的 PrintDocument preview.ShowDialog(); }

GetPrintDocument()返回的PrintDocument已预设好PrintPage事件处理器,且默认启用UseEXDialog = true(启用新版 Windows 打印预览界面),避免旧版预览窗口无法缩放的问题。

3.4 样式定制:覆盖默认行为的四个关键钩子

模块提供BeforePrint,AfterPrint,BeforeDrawHeader,BeforeDrawRow四个事件,允许你在渲染前注入逻辑。例如,为每页添加动态页眉(含当前时间):

printer.BeforePrint += (sender, e) => { // 设置页眉文字(全局生效) printer.HeaderContent = $"库存报表 - 生成时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"; printer.HeaderHeight = 40; // 页眉区域高度 }; printer.BeforeDrawHeader += (sender, e) => { // 在页眉区域绘制背景色和边框 var rect = new RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, printer.HeaderHeight); e.Graphics.FillRectangle(Brushes.LightGray, rect); e.Graphics.DrawRectangle(Pens.DarkGray, Rectangle.Round(rect)); };

HeaderContent支持\n换行,HeaderHeight单位为像素,会自动从e.MarginBounds中扣除,不影响表格主体区域。


4. 避坑指南:五个真实翻车现场与血泪修复方案

4.1 现象:打印预览中表格文字模糊、边缘锯齿,放大后像马赛克

原因:GDI+ 默认使用TextRenderingHint.SystemDefault,在非整数 DPI 缩放(如 125%、150%)的显示器上,字体渲染失真。
解决:强制设置TextRenderingHint.ClearTypeGridFit,并在PrintPage事件开头添加:

e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; // 同时开启抗锯齿

4.2 现象:中文列名(如“商品名称”)在打印时显示为方块或空格

原因:PrintDocument使用的字体未嵌入中文字符集,或Font构造时未指定GraphicsUnit.Pixel导致单位换算错误。
解决:在DataGridViewPrinter初始化后,显式设置中文字体:

printer.DefaultFont = new Font("微软雅黑", 9f, GraphicsUnit.Pixel); // 注意:必须用 GraphicsUnit.Pixel,若用 Point 会导致 Windows DPI 缩放时字号错乱

4.3 现象:跨页时表头未重复,第二页开头直接是数据行

原因:DataGridViewPrinter默认只在第一页绘制表头,未启用RepeatHeader逻辑。
解决:启用表头重复并指定重复高度:

printer.RepeatHeader = true; printer.HeaderHeight = 30; // 表头区域高度,需大于表头行高 // 同时确保 BeforeDrawHeader 事件中正确绘制表头内容

4.4 现象:调用Print()后程序卡死,CPU 占用 100%

原因:DataGridView数据源为BindingSource且DataSource未设置AllowNew = false,导致打印过程中BindingSource尝试动态创建新行,引发无限递归。
解决:打印前冻结数据源:

private void btnPrint_Click(object sender, EventArgs e) { // 冻结 BindingSource if (dataGridView1.DataSource is BindingSource bs) bs.AllowNew = false; printer.Print(); // 恢复(可选) if (dataGridView1.DataSource is BindingSource bs2) bs2.AllowNew = true; }

4.5 现象:PDF 输出时,带背景色的单元格在 Adobe Reader 中显示为白色

原因:模块的 PDF 模式使用System.Drawing.Common的Metafile回放机制,而SolidBrush填充在 Metafile 中可能丢失 Alpha 通道。
解决:禁用透明度,强制使用不透明画刷:

// 在 StyleMapper 中修改 FillBackground 逻辑 if (style.BackColor != Color.Empty && style.BackColor.A == 255) // 仅处理不透明色 { using (var brush = new SolidBrush(style.BackColor)) g.FillRectangle(brush, cellRect); } // 若需透明色,改用 PNG 导出模式(模块支持)

注意:PDF 模式为实验性功能,生产环境推荐使用OutputMode.Printer直连物理设备。


5. 高级技巧:自定义分页逻辑、导出 PDF 与批量打印实战

5.1 精确控制分页:按业务字段分组强制断页

某些报表要求“每个客户订单单独一页”。此时不能依赖行高累加,需在BeforePrint中注入分组逻辑。假设dataGridView1数据源为List<Order>,Order.CustomerId为分组键:

private Dictionary<int, int> customerPageMap = new Dictionary<int, int>(); printer.BeforePrint += (sender, e) => { // 遍历数据源,记录每个 CustomerId 首次出现的行索引 customerPageMap.Clear(); var orders = (List<Order>)dataGridView1.DataSource; int currentPage = 1; int lastCustomerId = -1; for (int i = 0; i < orders.Count; i++) { var orderId = orders[i].CustomerId; if (orderId != lastCustomerId) { customerPageMap[orderId] = currentPage++; lastCustomerId = orderId; } } }; printer.BeforeDrawRow += (sender, e) => { var order = (Order)dataGridView1.Rows[e.RowIndex].DataBoundItem; if (customerPageMap.TryGetValue(order.CustomerId, out int pageNum)) { // 在每页顶部添加分组标题 if (e.RowIndex == 0 || ((Order)dataGridView1.Rows[e.RowIndex - 1].DataBoundItem).CustomerId != order.CustomerId) { var titleRect = new RectangleF(e.Bounds.Left, e.Bounds.Top - 30, e.Bounds.Width, 30); e.Graphics.DrawString($"客户:{order.CustomerName} | 订单号:{order.OrderId}", new Font("微软雅黑", 10f, FontStyle.Bold), Brushes.Black, titleRect, new StringFormat { Alignment = StringAlignment.Near }); } } };

5.2 生成 PDF 文件:绕过打印机,直出文件流

模块内置SaveToPdf(string filePath)方法,底层使用System.Drawing.Common的Metafile+GdipEmfToWmfBits(Windows 平台)或SkiaSharp(跨平台,需额外引用):

private void btnSavePdf_Click(object sender, EventArgs e) { var saveDlg = new SaveFileDialog { Filter = "PDF 文件|*.pdf", FileName = $"报表_{DateTime.Now:yyyyMMdd_HHmmss}.pdf" }; if (saveDlg.ShowDialog() == DialogResult.OK) { try { // 关键:设置输出模式为 PDF printer.OutputMode = OutputMode.Pdf; printer.SaveToPdf(saveDlg.FileName); MessageBox.Show($"PDF 已保存:{saveDlg.FileName}", "成功"); } catch (Exception ex) { MessageBox.Show($"PDF 保存失败:{ex.Message}"); } } }

提示:PDF 生成速度取决于DataGridView行数,1000 行约耗时 800ms(i7-10875H)。若需更高性能,建议改用QuestPDF库,但会失去样式实时同步能力。

5.3 批量打印:一次点击,连续输出多个 DataGridView

当系统需打印“入库单+出库单+盘点表”三联单时,可复用同一PrintDocument实例:

private void btnBatchPrint_Click(object sender, EventArgs e) { var printers = new[] { new DataGridViewPrinter(dataGridViewInbound), // 入库单 new DataGridViewPrinter(dataGridViewOutbound), // 出库单 new DataGridViewPrinter(dataGridViewInventory) // 盘点表 }; // 合并为单个打印任务 var batchDoc = new PrintDocument(); int currentIndex = 0; batchDoc.PrintPage += (sender, e) => { if (currentIndex >= printers.Length) { e.HasMorePages = false; return; } // 用当前 printer 渲染一页 var printer = printers[currentIndex]; printer.DrawPage(e); // 此方法不触发分页,只画一页 // 检查是否还有内容(单页模式) if (printer.HasMorePagesForCurrentPage()) { e.HasMorePages = true; } else { currentIndex++; e.HasMorePages = currentIndex < printers.Length; } }; batchDoc.Print(); }

DrawPage()是模块提供的底层渲染方法,允许你接管整个PrintPageEventArgs,比Print()更灵活。

5.4 生产环境必加的健壮性补丁

在某仓储系统上线前,我们追加了三项检查,避免凌晨三点被运维电话叫醒:

检查项代码位置作用
打印机状态检测Print()方法入口调用PrinterSettings.IsValid和PrinterSettings.CanDuplex,避免发送任务到离线打印机
内存泄漏防护Dispose()重写显式释放Bitmap,Font,Brush等 GDI+ 句柄,防止长时间运行后OutOfMemoryException
DPI 缩放适配GetRowHeight()内部用Graphics.DpiX / 96f动态缩放字体大小,确保 125% DPI 下字号不缩小

从那以后我每次交付打印模块,都强制走一遍这三道检查——不是信不过代码,是信不过 Windows 打印子系统的玄学稳定性。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

SpringBoot高校体育赛事管理平台:智能编排与成绩管理实战

SpringBoot高校体育赛事管理平台:智能编排与成绩管理实战

先说个真实场景&#xff1a;每年秋季运动会&#xff0c;体育部的老师和学生志愿者抱着几叠纸质报名表&#xff0c;手写编号、手动分组、用Excel算总分&#xff0c;检录处广播喊人&#xff0c;裁判员拿着秒表记录然后再次誊抄。项目稍微多一点&#xff0c;比如田径场上男女各十几…

2026/10/20 16:51:02 阅读更多 →
WPF + HLSL + Clip 实现歌词扫光高亮效果

WPF + HLSL + Clip 实现歌词扫光高亮效果

1. 常见歌词高亮的痛点&#xff0c;以及 HLSL Clip 这套组合的思路先说我为什么会折腾这个。做桌面歌词播放器的时候&#xff0c;最常用的高亮方案无非两种&#xff1a;一是给当前行换一个 Foreground&#xff0c;用前景色做颜色区分&#xff1b;二是叠两层 TextBlock&#xf…

2026/10/20 16:51:02 阅读更多 →
NEU-DET钢材表面缺陷检测实战:从数据解读到YOLOv5训练全流程

NEU-DET钢材表面缺陷检测实战:从数据解读到YOLOv5训练全流程

简介&#xff1a;钢材表面缺陷数据集NEU-DET是面向计算机视觉与机器学习研究者的专业资源&#xff0c;旨在支持钢材表面缺陷自动检测算法的训练与评估&#xff0c;适用于工业质检场景中的缺陷识别与定位任务。压缩包内共两千个文件&#xff0c;以标注文件、图像文件和标签文件为…

2026/10/20 16:51:02 阅读更多 →

最新新闻

UI Recorder 实战:基于录制回放的低门槛Web自动化测试方案

UI Recorder 实战:基于录制回放的低门槛Web自动化测试方案

1. 项目概述&#xff1a;UI Recorder 到底解决了什么问题 做Web端测试的同学应该都有过这种经历&#xff1a;手工测试点来点去&#xff0c;一天下来眼睛花了、手腕酸了&#xff0c;回归用例还有一大堆没跑完。想上自动化&#xff0c;又绕不开那套学习曲线陡峭的框架——写定位器…

2026/10/20 18:15:49 阅读更多 →
从回调地狱到响应式数据流:RxJava核心机制与工程落地

从回调地狱到响应式数据流:RxJava核心机制与工程落地

前段时间我重构了一个老旧的数据采集模块&#xff0c;事情不大但特别典型&#xff1a;十几路传感器、一路串口、一路网络推送&#xff0c;全都往同一个界面汇聚。重构之前代码里全是回调嵌套&#xff0c;想改一个过滤条件得顺着调用链翻半天&#xff1b;重构之后整体逻辑变成一…

2026/10/20 18:15:49 阅读更多 →
refin-bin-0.14.tar 文本后处理工具包:日志清洗与规则部署实战

refin-bin-0.14.tar 文本后处理工具包:日志清洗与规则部署实战

简介&#xff1a;rEFInd 是一款面向 UEFI 固件环境的开源启动管理器&#xff0c;常用于 Linux、macOS 与 Windows 多系统共存的引导切换&#xff0c;可展示图形化启动菜单&#xff0c;支持自定义超时、默认系统与图标&#xff0c;适合具备一定 UEFI 基础的桌面用户、双系统爱好…

2026/10/20 18:15:49 阅读更多 →
证书打不开?从ASN.1编码到openssl排查全指南

证书打不开?从ASN.1编码到openssl排查全指南

不废话&#xff0c;直接进入正题。1. 先搞清楚报错的本质&#xff1a;ASN.1与证书编码是怎么回事大多数人在“打开证书”这件事上报错&#xff0c;第一反应是“证书坏掉了”&#xff0c;第二反应是“解析工具有问题”。实际从业时间久了你会发现&#xff0c;八成以上的情况是编…

2026/10/20 18:15:49 阅读更多 →
LSTM+ASB+ICB+DCAttention:时序预测增强模型详解

LSTM+ASB+ICB+DCAttention:时序预测增强模型详解

做时间序列预测这几年&#xff0c;我试过的模型不算少&#xff0c;从最早的ARIMA、Prophet&#xff0c;到后来的纯LSTM、Transformer变体&#xff0c;几乎每个阶段都在折腾同一个问题&#xff1a;怎么把“时序特征”和“状态记忆”用得更好。老实说&#xff0c;单一LSTM在有长期…

2026/10/20 18:15:49 阅读更多 →
NeuDecide:面向儿童语音交互的端到端轻量决策模型

NeuDecide:面向儿童语音交互的端到端轻量决策模型

1. 项目概述&#xff1a;一个被严重低估的“语音直通决策”范式转变最近在几个开源模型仓库和儿童教育硬件论坛里反复看到NeuDecide这个名字&#xff0c;点进去发现它不是又一个微调版 Whisper 或者 Whisper&#xff0c;而是一个彻底绕开传统语音识别&#xff08;ASR&#xff0…

2026/10/20 18:14:48 阅读更多 →

日新闻

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实现详解

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

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

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

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

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

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

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →