ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MATLAB App Designer实战:从界面设计到软件著作权申请全流程

MATLAB App Designer实战:从界面设计到软件著作权申请全流程 MATLAB App Designer 从界面设计到软件著作权申请4分钟跑通一个可交付的GUI工具如果你在网上搜索“MATLAB 做界面”大概率会翻到两类结果一类是几年前的 GUIDE 老教程另一类是一堆不成体系的“App Designer 入门”片段。很多人对 MATLAB 的印象还停留在“写脚本跑算法”但实际项目里导师、客户、同事想要的不是一个.m脚本而是一个能输入参数、点按钮、看结果的小软件。这篇文章想解决的就是这个问题怎么用 MATLAB App Designer 在很短的时间内搭出一个能交付、能打包、甚至能申请软件著作权的桌面应用。先给一个明确判断App Designer 真正的价值不是“画界面更漂亮”而是把 MATLAB 从“计算引擎”变成了“应用开发环境”。它跟传统 GUIDE 最大的不同是组件系统、回调机制和代码管理方式发生了根本变化。你不需要精通面向对象编程也不需要写复杂的事件框架但需要理解“回调函数”“属性”“组件树”这几个核心概念否则做出来的界面一运行就报错或者数据在各回调之间传不出去。读完这篇文章你可以做到三件事第一用 App Designer 从零做出一个完整可运行的信号分析工具包含输入参数、按钮、绘图和结果导出第二把 Simulink 模型的仿真结果显示到 GUI 界面上解决“模型跑完但结果只能在 Scope 里看”的尴尬第三了解 MATLAB 项目申请软件著作权的材料准备、代码文档整理和常见风险。全文会包含完整示例代码、运行验证方式和问题排查清单建议收藏备用。1. 这篇文章真正要解决的问题如果你正在做 MATLAB 相关的课程设计、毕业设计、科研项目或者公司里的内部工具开发下面这些场景应该很熟悉算法写好了、仿真跑通了但每次给导师演示都要打开一堆.m文件手动改参数。同事想用你写的滤波函数但不会 MATLAB 命令行操作你不得不在旁边一步步教。项目结题需要提交一个“软件”但你的交付物是一个脚本文件夹。想给 MATLAB 写的小工具申请软件著作权却不知道界面的代码、流程图、文档材料怎么组织。这些问题本质上是同一个你的 MATLAB 代码缺少一个“软件外壳”。算法本身只是计算逻辑而“软件产品”还需要界面、事件交互、数据传递、部署方式和知识产权材料。App Designer 恰好把这几件事集中到了一个工具链里。从学习成本角度看App Designer 的曲线比很多人想象中低。它采用拖拽式界面设计类似 Visual Studio 的 WinForms 或 Qt Designer但跟 MATLAB 的矩阵计算、绘图功能天然集成。对于一个已经会用 MATLAB 写脚本、调函数的人来说上手 App Designer 可以控制在小时级别——这一点是它最大的优势也是为什么“4分钟搞定 APP 设计”这类标题能成立的原因。但也要说清楚边界App Designer 适合工具类、科研演示类、数据分析和简单交互的应用不适合做高并发、复杂 UI 动画、跨平台原生体验的商业软件。它不是取代 Java/Python 桌面开发的存在而是在 MATLAB 技术生态内部形成闭环——从数据生成、算法处理到界面展示同一个语言体系全部完成。2. MATLAB App Designer 的核心概念从 GUIDE 到现代 GUI 开发2.1 App Designer 到底是什么MATLAB App Designer 是 MATLAB 自带的应用程序开发环境用于设计交互式界面并生成对应的面向对象代码。它提供画布式的窗口布局、组件库、代码编辑区和实时预览功能。从 R2016a 开始MathWorks 逐步用 App Designer 取代传统的 GUIDE目前新版 MATLAB 中 App Designer 已经是官方推荐的主要 GUI 开发方式。它的本质是把“界面描述”和“业务代码”组织在一个.mlapp文件中。.mlapp文件不是纯文本代码文件而是包含界面布局元数据和代码逻辑的封装格式。你可以在 App Designer 里同时拖组件、写回调也可以把.mlapp转换成普通.m类文件继续编辑。2.2 核心概念一组件与组件树组件树Component Tree是 App Designer 设计视图左侧的组件层级列表。它展示了界面上的所有元素及其嵌套关系。比如一个常见的布局是App ├── GridLayout │ ├── Label │ ├── EditField │ ├── Button │ └── UIAxesGridLayout网格布局是 App Designer 最重要的布局组件。它把窗口划分成网格区域组件拖入后会自动“锚定”到对应网格单元。相比 GUIDE 的绝对定位GridLayout 显著减少了窗口缩放时组件错位的困扰。初学者最容易犯的错误是直接用坐标定位Position 属性手动摆放组件结果换一台不同分辨率的电脑界面就变形了。2.3 核心概念二回调函数回调函数是 GUI 应用的核心逻辑。当用户点击按钮、修改输入框、移动滑块时MATLAB 会调用对应的回调函数。App Designer 中你双击某个组件或右键选择“回调”系统会自动生成一个回调函数模板例如按钮的ButtonPushed回调% Button pushed function: Button function ButtonPushed(app, event) % 在这里编写点击按钮后要执行的逻辑 end理解回调的关键在于它不像脚本那样从上往下顺序执行而是由用户操作“触发”的。界面上可以有多个输入框、多个按钮每个组件的事件各自独立。新手容易遇到的问题是把所有逻辑都堆在一个按钮回调里导致代码难以维护。合理的做法是让按钮回调拆分为多个子函数每个子函数只做一件事。2.4 核心概念三app 对象的属性绑定App Designer 中app对象是当前应用实例的引用。所有组件的值和状态都可以通过app.ComponentName访问。比如一个名为FreqEditField的输入框读取它的输入值用app.FreqEditField.Value往一个名为UIAxes的坐标轴绘图用plot(app.UIAxes, x, y)。如果你需要在多个回调之间共享数据比如在一个回调里计算出的结果在另一个回调里使用最简单的做法是把它存为 app 的属性。在代码视图的“属性”区域定义properties (Access public) ResultData double end然后在回调里写入app.ResultData ...其他回调就能读取。这个设计模式对应了面向对象编程中“把状态放在对象内部”的思想但使用门槛很低。很多 App Designer 用户一开始不明白这个频繁用全局变量global或handles来传数据这是从 GUIDE 时代延续下来的坏习惯不仅容易出错而且不利于后续申请软件著作权时的代码审查。3. 环境准备如何确认你的 MATLAB 支持 App Designer3.1 版本要求App Designer 从 R2016a 版本开始提供但早期版本功能较弱。如果你使用的是 R2019b 及以后的版本界面设计和代码生成能力已经比较成熟本文的示例均基于较新的通用版本编写。版本不确定时可以在 MATLAB 命令行窗口输入version查看当前版本号。如果版本过旧建议升级到至少 R2020a 之后的版本因为新版对组件回调、坐标轴交互、打包工具的兼容性更好。3.2 打开 App Designer 的三种方式方式一在 MATLAB 工具栏选择“APP” - “Design App”下的“App Designer”。方式二在命令行窗口输入appdesigner方式三直接双击一个已有的.mlapp文件。打开后你会看到三个区域中间是界面设计画布Design View左侧是组件库和组件树右侧是代码视图Code View。在设计画布上方有一个“运行”按钮可以快速测试当前界面。3.3 检查依赖工具箱App Designer 本身不依赖额外的 Toolbox属于 MATLAB 基础功能。但如果你要开发特定领域的应用需要提前确认对应工具箱已安装。例如图像处理工具Image Processing Toolbox信号分析Signal Processing ToolboxSimulink 仿真联动Simulink 本体神经网络模型调用Deep Learning Toolbox查看工具箱安装情况ver如果缺少工具箱运行时会提示“未定义函数或变量”这属于最常见的环境类报错。因此项目启动前把需要的工具箱列一张清单能省去很多后期排查时间。4. 实战完整示例——正弦信号分析与频谱显示工具为了体现 App Designer 的核心开发流程这里做一个非常实用的信号分析小工具。功能包括输入信号频率、采样率、信号时长点击“生成并显示”按钮后在上方坐标轴绘制时域波形在下方坐标轴显示频谱图。这个示例恰好覆盖了 App Designer 的核心操作组件布局、回调编写、属性访问、数值计算和绘图。4.1 创建空白应用并设计界面打开 App Designer选择“Blank App”。从左侧组件库拖入以下组件两个Edit Field (Numeric)分别用于输入频率和采样率。一个Edit Field (Numeric)用于输入信号时长。一个Button文字改为“生成并显示”。两个UIAxes一个用于时域图一个用于频谱图。通过“GridLayout”调整布局让组件对齐。设计界面时的核心原则每个输入组件要配一个Label明确标注含义这不仅是用户体验问题也是申请软著时界面截图完整性的要求。4.2 给组件重命名在代码视图中每个组件都有一个默认名称比如EditField、EditField2。为了代码可读性强烈建议重命名频率输入框命名为FreqEditField采样率输入框命名为FsEditField时长输入框命名为DurationEditField按钮命名为GenerateButton。重命名方法是在组件树中选中组件在右侧属性检查器的“Identifier”中修改名称。名称修改后所有回调参数和引用会自动更新但如果你在代码里手写过旧的组件名需要手动同步。4.3 编写回调代码双击GenerateButton按钮App Designer 会自动生成GenerateButtonPushed回调模板。在其中填写完整逻辑% Button pushed function: GenerateButton function GenerateButtonPushed(app, event) % 读取界面输入 freq app.FreqEditField.Value; fs app.FsEditField.Value; duration app.DurationEditField.Value; % 参数合法性检查 if fs 0 || freq 0 || duration 0 uialert(app.UIFigure, 请输入大于0的有效参数, 参数错误); return; end % 生成时间序列 t 0:1/fs:duration-1/fs; y sin(2*pi*freq*t); % 绘制时域波形 plot(app.TimeAxes, t, y); xlabel(app.TimeAxes, 时间/s); ylabel(app.TimeAxes, 幅值); title(app.TimeAxes, [信号时域波形 f, num2str(freq), Hz]); grid(app.TimeAxes, on); % 计算频谱并绘图 N length(y); Y fft(y); f (0:N-1) * fs / N; amplitude abs(Y(1:N)) * 2 / N; plot(app.FreqAxes, f(1:floor(N/2)), amplitude(1:floor(N/2))); xlabel(app.FreqAxes, 频率/Hz); ylabel(app.FreqAxes, 幅值); title(app.FreqAxes, 单边频谱); grid(app.FreqAxes, on); end这段代码里有两个关键点值得注意。第一个是参数校验。很多初学者跳过这步当用户输入 0 或负数时MATLAB 会产生奇怪的错误而使用uialert弹出对话框是 App Designer 推荐的用户反馈方式。第二个是频谱绘图的双边转单边处理。用过fft的人都知道直接画abs(Y)会得到对称的双边频谱物理意义不直观。代码里取前半段并乘以 2/N是信号处理里的标准做法。这个小细节展示了 App Designer 应用和“纯脚本绘图”一样需要算法基础不是只把组件拖上去就行。4.4 运行与测试点击工具栏的运行按钮或按 F5界面启动后在频率框输入 10采样率输入 1000时长输入 1点击“生成并显示”上方显示正弦波形下方显示 10Hz 处的频谱峰。整个操作流程在熟练后确实可以在几分钟内完成这也是为什么这类教程能在社区传播得很快。4.5 导出代码为 .m 类文件默认情况下App Designer 应用保存在.mlapp文件中。如果你想用文本编辑器审查代码、参与版本控制或者申请软著时整理源码可以导出为.m文件MATLAB 菜单路径APP-Save As格式选择MATLAB Code File (.m)。导出的.m文件是一个标准的 MATLAB classdef 类文件包含组件定义、属性和所有回调方法。用文本编辑器打开后可以看到完整的代码结构包括classdef SignalAnalysisApp matlab.apps.AppBase % Properties that correspond to app components properties (Access public) UIFigure matlab.ui.Figure ... end end了解这个结构很有意义。它说明 App Designer 应用本质上是 MATLAB 面向对象程序底层是基于matlab.apps.AppBase的类。理解到这一层你就不会被“只能拖拽、不能写代码”的刻板印象限制住了。4.6 添加结果导出功能实际项目中用户往往还需要把仿真结果保存下来。可以在界面上加一个“导出数据”按钮回调里用uigetfile让用户选择保存路径% Button pushed function: ExportButton function ExportButtonPushed(app, event) if isempty(app.ResultData) uialert(app.UIFigure, 没有可导出的数据请先生成信号, 导出失败); return; end [file, path] uiputfile(*.mat, 保存数据文件); if isequal(file, 0) return; % 用户取消保存 end data app.ResultData; save(fullfile(path, file), data); end这里引入了一个app.ResultData属性保存计算结果需要在 properties 区增加定义properties (Access public) ResultData struct end5. Simulink 联动把仿真结果显示到 App 界面搜索“matlab 之 app designer simulink模型调用及仿真结果显示在gui界面上”这类关键词的人很多这也是 MATLAB 开发中的高频需求Simulink 模型仿真完之后结果默认显示在 Scope 里但交付给用户时要集成到统一界面里。App Designer 可以通过几种方式实现这个目标。5.1 方案一使用sim命令和simout工作区变量这是最常规的做法。在 Simulink 模型中使用To Workspace模块把某个信号输出到工作区变量。然后在 App Designer 回调中调用sim函数执行仿真仿真结束后从工作区读取结果。核心代码逻辑如下% 在按钮回调中执行 Simulink 仿真 function RunSimButtonPushed(app, event) % 读取界面输入的仿真参数 simTime app.SimTimeEditField.Value; % 设置模型参数并运行仿真 modelName my_sim_model; load_system(modelName); % 设置仿真时间 set_param([modelName /Simulation], StopTime, num2str(simTime)); % 运行仿真 simOut sim(modelName); % 从仿真输出中提取信号 % 假设模型中 To Workspace 模块变量名为 simout y simOut.get(simout); t y.time; data y.signals.values; % 在 App 的坐标轴上绘图 plot(app.ResultAxes, t, data); end这里需要强调一个容易踩坑的点在新版本 MATLAB 中simOut.get(simout)返回的是Simulink.SimulationData.Dataset对象访问数据的方式可能不同。更稳妥的写法是先y simOut.get(simout)再查看y的结构再决定如何取值。因为不同 MATLAB 版本对数据格式的处理有差异写代码时用whos simout或在命令行窗口查看返回对象结构是成本最低的排查方式。5.2 方案二使用assignin将结果写入 base 工作区如果模型配置是向 base workspace 输出变量尤其是在模型配置参数里勾选了“Single simulation output”或直接输出变量名可以使用assignin(base, simout, simOut); data evalin(base, simout);虽然这种做法效率不高但在老项目中遇到很多兼容性问题时它仍然是一个实用兜底方案。5.3 方案三模型内嵌matlab function模块把结果写回 App如果你对模型有控制权更工程化的做法是在 Simulink 模型里通过MATLAB Function模块在仿真过程中逐步把数据写入 App 的 UserData 或通过事件方式通知 App。这种方法适用于长时间仿真需要实时界面更新的场景但实现复杂度较高需要掌握 Simulink 回调机制。对大多数开发场景来说先采用方案一跑通“模型仿真 - 结果读取 - App 绘图”的链路再考虑实时交互是一种更务实的技术路线。记住一个判断先把数据从仿真引擎拿回到 MATLAB 工作区再交给 App 绘图这是两个环节不要混在一起调试。6. 打包与部署让没有 MATLAB 的同事也能运行App Designer 开发完成后交付方式有三种直接把.mlapp文件发给装有 MATLAB 的人运行。打包为独立桌面应用需要 MATLAB Compiler 工具箱。生成 Web App 部署到 MATLAB Web Server需要额外服务器环境。日常科研和课程设计第一种方式够用。但如果你想作为“软件产品”交付或申请软件著作权时需要演示可执行程序推荐使用 MATLAB Compiler 打包为独立 exeWindows 平台。6.1 打包操作步骤在 MATLAB 命令行或菜单中运行 Application CompilerapplicationCompiler然后在压缩工具中添加主文件.mlapp文件指定运行时点“Package”即可。打包完成后会生成一个for_redistribution文件夹其中包含安装程序。6.2 注意事项MATLAB Compiler 需要额外购买授权不是 MATLAB 基础功能。生成 exe 的运行速度会比 MATLAB 环境内稍慢启动时间约 10 到 30 秒这是因为要加载 MATLAB Runtime。这在界面提示上要提前设计不要让人以为程序卡死了。不同版本的 MATLAB Runtime 体积可能达到数百 MB分发给用户时要注意带宽和安装时间。打包后如果需要调用 Simulink 模型建议先确认目标机器上能运行模型因为 Simulink 模型依赖的求解器和工具箱会比普通 MATLAB 代码更复杂。7. 软件著作权申请MATLAB 写的软件如何登记这是“MATLAB APP Designer 软件著作权”组合下很多人关心的问题。先说结论MATLAB 开发的应用可以申请软件著作权但材料组织和源码整理方式与 Java/Python 项目有明显差异。7.1 申请流程概述软件著作权登记的常规流程是在中国版权保护中心进行在线实名注册并提交申请按申请表填写软件名称、开发完成日期、开发方式、编程语言等信息提交源程序文档和软件说明书等待审核周期一般在 1 到 3 个月左右。对于 MATLAB 项目关键材料就是两类源程序文档和软件说明书用户手册。7.2 源程序文档怎么准备软著申请要求提交源程序的前、后各连续 30 页每页不少于 50 行。如果程序不到 60 页全部提交。MATLAB 代码的整理方式和传统源码不同因为.mlapp文件并不是纯文本格式不能直接作为源代码文档提交。通常的做法是第一步在 App Designer 中把应用导出为.m文件导出后得到包含 classdef 定义的 MATLAB 代码。第二步把导出代码整理到一个统一的源码文件夹如果项目包含多个.m文件按功能模块放在不同子目录。第三步将代码全部合并或按目录形成一个可打印的文本文件。这里推荐脚本自动处理% 将当前目录下所有 m 文件合并为一个大文本 files dir(*.m); fid fopen(source_all.txt, w); for i 1:length(files) fprintf(fid, %%%% %s \n, files(i).name); content fileread(files(i).name); fprintf(fid, %s\n, content); end fclose(fid); disp(源代码文档生成完成);需要提醒的是即使你的应用只有一个.mlapp文件导出的.m类代码通常也有几百行整理成 60 页的源代码材料不算难但不要直接把.mlapp二进制文件放入材料评审员无法查看也会导致材料审核被退回。7.3 软件说明书怎么写说明书就是“用户手册”要求有软件界面截图和操作说明。对 App Designer 项目建议围绕以下结构编写软件概述说明软件的用途、运行环境、功能范围。安装与启动如何打开.mlapp或运行打包后的程序。界面说明在 App Designer 中运行界面截取完整窗口截图标注每个组件的作用。操作流程从输入参数到得到结果每一步配上截图。把关键操作闭环地写出来。异常情况说明比如输入无效参数时的提示。说明书不要求是学术论文但一定要有“步骤感”。审核员是否熟悉 MATLAB 并不重要重要的是他们能依据说明书理解软件的使用方式和功能逻辑。7.4 申请软著的常见误区第一软件名称尽量用中文名字加版本号不要直接叫“untitled”或“App1”。你在 App Designer 里可以设置应用的Name属性这个名称会显示在窗口标题栏。准备申请软著前先把这个属性改成正式的软件名称。第二MATLAB 代码的注释量和可读性会影响审核体验。App Designer 自动生成的代码注释较少建议在关键回调函数上补充中文注释这样不仅方便审核也让代码文档更专业。第三如果使用 Simulink 模型不要试图把.slx文件作为源代码提交。仿真模型可以作为“说明书”里的功能描述部分展示但源程序文档主体是.m代码。第四不得使用破解版 MATLAB 开发并申请软著这涉及知识产权风险。如果你所在单位有正版授权要在软件说明书的开发环境部分如实填写 MATLAB 版本和工具箱列表。7.5 一个务实的建议软著申请不是软件开发完成后的“事后补票”它的材料准备和代码工程化要求命名规范、注释、模块划分、用户文档正好是软件质量的反向约束。如果你在设计 App Designer 应用的每一步都按“将来可能要提交软著材料”的标准来做代码可维护性会明显提高这也是申请软著这件事对个人开发者最有价值的地方。8. 常见问题与排查思路App Designer 开发中下面几个问题是出现频率非常高的问题现象可能原因排查方式解决方案运行时报错“未定义函数或变量”组件名拼写错误或回调中对象名已被重命名查看报错代码行确认app.组件名与组件树一致在组件树中重命名组件同步修改代码引用界面可以打开但点按钮无响应回调函数未正确关联到组件双击组件查看回调绑定检查生成的回调函数名删除旧回调重新双击组件生成回调窗口缩放后组件位置错乱使用绝对坐标定位而没使用 GridLayout查看组件 Position 属性重建布局使用网格布局管理组件排列输入中文后按钮回调出现乱码MATLAB 编码设置与系统字体不兼容检查代码编辑器中文字符是否正常改用 utf-8 编码保存代码或避免在代码中硬编码中文字符串Simulink 仿真后读取不到数据To Workspace 变量名与代码中不一致在命令行who查看工作区变量名统一变量命名或使用 simOut.get 精确获取应用打包后在其他机器运行失败缺少 MATLAB Runtime 版本检查安装日志与运行时版本号安装对应版本 MATLAB Runtime或重新打包uialert 弹出后界面闪烁回调中同时执行大量绘图操作去掉多余 grid 操作减少绘图数据点合理降采样分批绘图对于新手最常见的失败原因几乎都集中在“组件名不一致”和“回调没触发”这两类。排查思路建议遵循固定顺序先看代码视图中最底部的输出信息再检查错误行涉及的变量名是否能在组件树中找到最后确认回调函数名是否与组件的事件绑定一致。按这个顺序走绝大多数问题能在几分钟内定位。9. 最佳实践与工程建议9.1 命名规范给组件命名时建议采用“类型缩写 功能名”的方式FreqEditField、RunButton、ResultAxes。避免默认的EditField3、Button5。这个习惯在代码行数超过 200 行后会极大提高可读性也是申请软著时代码质量的加分项。9.2 回调拆分与数据流设计不要把复杂业务逻辑全部堆在一个按钮回调里。建议每个回调只做三件事读取输入、调用子函数、更新界面。计算和数据处理逻辑放到普通成员函数中便于独立测试和代码复用。例如methods (Access public) function resultData processSignal(app, freq, fs, duration) t 0:1/fs:duration-1/fs; y sin(2*pi*freq*t); resultData struct(t, t, y, y); end end然后在按钮回调中调用这个方法。这样即便日后把同一个算法包装成命令行函数或 Web App核心逻辑也能复用。9.3 参数校验与错误提示App Designer 生成的界面虽然在输入框层面可以设置数值范围但依然要在回调入口做一次参数校验。这是一个防御性编程习惯。使用uialert给用户友好的错误提示而不是让 MATLAB 抛出红色 stack trace。在正式交付的软件中“用户看到报错信息不是错误堆栈而是清晰的对话框”是基本要求。9.4 版本兼容与代码备份不同 MATLAB 版本导出的.mlapp文件可能存在兼容差异特别是老版本打不开新版本创建的文件。建议在项目说明文档中明确记录开发所用的 MATLAB 版本和工具箱列表。每个里程碑导出一次.m代码并连同.mlapp一起放入 Git 托管。不要过度依赖云端自动保存重要节点手动备份。9.5 把软著材料建设纳入开发流程如果你有软著申请计划建议从第一天就启动“说明书文档”把每个功能模块的操作步骤边开发边记录。等到开发完成后再补文档不仅时间紧张内容也容易遗漏。一个轻量做法是在项目文件夹中维护一个docs/manual.md每完成一个功能就更新一部分最终形成完整的用户手册。10. 总结与下一步实践建议App Designer 的入门速度确实可以很快但真正决定一个 MATLAB 应用是否“像软件”的是界面设计之外的东西参数校验、数据流组织、文档材料、打包交付和知识产权保护。这些能力恰恰是你今后做科研工具、毕业设计或商业项目交付时无法绕开的环节。建议你按下面路径继续练手先复现本文的信号分析工具把整个流程跑通。尝试给它增加一个“保存到 Excel”的按钮用writetable实现。如果熟悉 Simulink找一个已有的简单模型按第 5 节的方式把仿真结果接到 App 界面中。把应用导出成.m文件用文本编辑器通读一遍生成的类代码体会组件属性和回调的绑定关系。如果准备申请软著先从整理现有源码和截图开始做一版说明书文档再走在线登记流程。MATLAB 的技术栈已经不只是“仿真计算”的代名词它完全可以支撑一个从算法验证到桌面应用交付再到软件著作权申请的完整项目周期。理解到这一层你以后接到的任何 MATLAB 项目都不会只是“写个脚本交差”而是能交付一个真正能用的工具。
返回列表