MATLAB App 设计 【第四期】计算器实战
本期小编将带着大家回顾并深度应用前两期的核心知识点MATLAB App 设计 【第二期】设计界面与容器组件介绍MATLAB App 设计 【第三期】输入组件与按钮的介绍把之前学到的界面设计、逻辑编写、功能调试等技巧串联起来,制作一个计算器。跟着步骤一步步操作,你就能收获一个属于自己的 MATLAB 计算器 App,快来试试吧!
第一步:打开设计界面,并将页面调整为合适大小

第二步:用网格布局搭建计算器基础框架
调用第二期MATLAB App 设计 【第二期】设计界面与容器组件介绍学到的布局知识,快速搭好界面骨架:
1.打开 MATLAB App Designer,把「网格布局」组件拖拽到设计页面;咱们做简易计算器,直接将网格设置为 4×6(4行6列)即可;
2.调整行权重:第一行要放计算器的「显示屏幕」,需要更宽的空间,所以把第一行的权重设为 1.2(其余行保持默认),这样屏幕区域会更符合使用习惯。

第三步:制作计算器 “显示屏幕”
-
1.拖拽「编辑文本」组件到设计界面,这个组件默认带左右两部分(标签 + 文本框),我们只需要右侧的文本显示区域,直接选中左侧标签,按键盘 Backspace 键删除; -
2.选中剩余的文本框,调整它的尺寸,让它刚好占满整个第一行(4×6 网格的第一行全列),作为计算器的显示屏幕。

第四步:添加按钮并规范命名
-
1.往下方的网格里逐个拖拽「按钮」组件,每个网格放一个,然后将按钮的「文本」修改为对应的内容(0-9 数字、加减乘除符号、等号、清空等); -
2.关键提示:计算器按钮数量多,后续写代码容易混乱!一定要在「组件浏览器」里给每个按钮规范重命名(比如 “数字 1 按钮” 命名为 btn_Num1,“加号按钮” 命名为 btn_Add),只要符合自己的命名习惯、自己能区分即可; -
3.重复步骤 1-2,把所有需要的按钮都添加完成(可以根据自己的喜好微调布局)。

第五步:统一设置字体样式
-
1.批量美化按钮:按住 Ctrl 键批量选中所有按钮,统一设置字体 —— 中文(若有)设为宋体,英文和符号设为 Times New Roman,字号调为 24(可按需调整); -
2.设置显示屏幕:先在文本框里随便输入几个数字(方便预览效果),然后将字体设为 Times New Roman,字号调大到 48,对齐方式设为「右对齐」(符合计算器显示习惯); -
3.预览满意后,把文本框里的测试数字删除,保持屏幕空白。 
第六步:编写回调函数 —— 先实现 0-9 数字输入功能
1.界面搭好后,先从最基础的 0-9 数字按钮开始,逐个编写回调函数
-
2.逻辑梳理:平时用计算器时,按数字键会在屏幕上显示对应数字,若屏幕已有内容,新数字会跟在后面拼接(比如先按 1、再按 2,屏幕显示 12); -
3.实操示例(以数字 0 按钮为例):右键点击 “0 按钮”,选择「添加回调函数」,跳转至代码视图,接下来就可以根据 “拼接数字” 的逻辑编写代码了。
% 读取屏幕上之前输入的内容currentText = app.EditField.Value; % EditField为屏幕的名字% 判断屏幕上是否为0ifstrcmp(currentText, '0')% 若为0则不变(防止000这种情况出现)app.EditField.Value = '0';else% 若不为0则在输入的数字后面添加一个0app.EditField.Value = [currentText '0'];end
4.下面是1-9的回调函数
% 这个代码是按钮1的回调函数,可将出现1的地方改为需要的数字即可变成需要的回调函数currentText= app. EditField.Value;ifstrcmp(currentText,'0')app. EditField.Value = '1';elseapp. EditField.Value = [currentText'1'];end
5.下面为小数点的回调函数
currentText = app.EditField.Value;if contains(currentText, '.')return;endapp.EditField.Value = [currentText '.'];
6.下面为左括号的回调函数
% 读取屏幕的内容currentText = app.EditField.Value;ifstrcmp(currentText, '0') % 修正:把中文单引号’改为英文单引号'% 如果为0,屏幕的内容就显示为“(”app.EditField.Value = '(';elselastChar = currentText(end);% 若不为0则读取文本最后一个内容,若为数字、小数点、右括号就自动输入*(,ifisstrprop(lastChar, 'digit') || lastChar == ')' || lastChar == '.'app.EditField.Value = [currentText '*('];else % 修正:把Else改为小写else(MATLAB区分大小写)% 否则就输入(app.EditField.Value = [currentText '('];endend
7.下面为右括号的回调函数
if strcmp(currentText, '0')return;end% 计算左右括号数量leftCount = count(currentText, '(');rightCount = count(currentText, ')');% 检查括号匹配:右括号数量必须小于左括号数量if rightCount >= leftCountreturn;end% 获取最后一个字符lastChar = currentText(end);% 如果最后是运算符或左括号,不允许直接添加右括号if ismember(lastChar, {'+', '-', '*', '/', '('})return;end% 添加右括号app.EditField.Value = [currentText ')'];
8.下面为+的回调函数
currentText = app.EditField.Value;% 如果为0,设置为0+if strcmp(currentText, '0')app.EditField.Value = '0+';return;end% 获取最后一个字符lastChar = currentText(end);% 检查最后字符是否为运算符或左括号if ismember(lastChar, {'+', '-', '*', '/', '('})% 如果是运算符,替换为新的运算符(加号)% 特殊情况:如果最后是减号,允许+-(如:2+-3)app.EditField.Value = [currentText(1:end-1) '+'];else% 否则直接添加加号app.EditField.Value = [currentText '+'];end
9.下面为-的回调函数
currentText = app.EditField.Value;% 如果为空(此处原注释与代码逻辑匹配为"如果是0"),设置为负号形式if strcmp(currentText, '0')app.EditField.Value = '-';return;endlastChar = currentText(end);app.EditField.Value = [currentText '-'];
10.下面为×的回调函数
currentText = app.EditField.Value;% 检查是否为空(代码逻辑为检查是否是0)if strcmp(currentText, '0')% 不能以乘号开始return;endlastChar = currentText(end);% 检查最后字符if ismember(lastChar, {'+', '-', '*', '/', '('})% 如果最后是运算符(除了减号)或左括号,不能直接跟乘号% 特殊情况:允许 (-2) 这种情况if lastChar == '('% 左括号后不能跟乘号return;else% 其他运算符替换为乘号app.EditField.Value = [currentText(1:end-1) '*'];endelse% 正常添加乘号app.EditField.Value = [currentText '*'];end
11.下面为÷的回调函数
currentText = app.EditField.Value;% 检查是否为空(代码逻辑为检查是否是0)if strcmp(currentText, '0')return;endlastChar = currentText(end);% 检查最后字符if ismember(lastChar, {'+', '-', '*', '/', '('})% 如果最后是运算符(除了减号)或左括号,不能直接跟除号if lastChar == '('return;else% 其他运算符替换为除号app.EditField.Value = [currentText(1:end-1) '/'];endelse% 正常添加除号app.EditField.Value = [currentText '/'];end
12.下面为=的回调函数
currentText = app.EditField.Value;% 检查是否是错误状态if strcmp(currentText, 'Error') || strcmp(currentText, 'Inf') || strcmp(currentText, 'NaN')app.EditField.Value = '0';return;end% 如果显示内容为空或只有0,不做计算if isempty(currentText) || strcmp(currentText, '0')return;end% 移除末尾可能存在的运算符(除了表示负号的减号)if ~isempty(currentText)lastChar = currentText(end);% 如果是运算符,移除它if ismember(lastChar, {'+', '*', '/', '^'})currentText = currentText(1:end-1);elseif lastChar == '-'% 检查减号是否是负数的一部分if length(currentText) > 1prevChar = currentText(end-1);% 如果前一个字符是数字或右括号,则这个减号是运算符,应该移除if isstrprop(prevChar, 'digit') || prevChar == ')'currentText = currentText(1:end-1);endendendend% 再次检查是否为空if isempty(currentText)return;end% 检查括号匹配leftParen = sum(currentText == '(');rightParen = sum(currentText == ')');if leftParen ~= rightParen% 自动补充缺失的右括号for i = 1:(leftParen - rightParen)currentText = [currentText ')'];endend% 替换用户界面中的运算符符号为MATLAB可识别的符号currentText = strrep(currentText, '×', '*');currentText = strrep(currentText, '÷', '/');% 处理π和e常数currentText = strrep(currentText, 'π', 'pi');currentText = strrep(currentText, 'e', 'exp(1)');% 处理科学计数法中的e(确保大小写)currentText = regexprep(currentText, '(\d+\.?\d*)e', '$1*10^');currentText = regexprep(currentText, '(\d+\.?\d*)E', '$1*10^');% 添加隐式乘法(例如:2(3+4) -> 2*(3+4))% 数字后跟左括号currentText = regexprep(currentText, '(\d)(\()', '$1*$2');% 右括号后跟数字currentText = regexprep(currentText, '(\))(\d)', '$1*$2');% 右括号后跟左括号currentText = regexprep(currentText, '(\))(\()', '$1*$2');try% 使用MATLAB的eval函数计算表达式result = eval(currentText);% 处理特殊结果if isinf(result)app.EditField.Value = 'Inf';elseif isnan(result)app.EditField.Value = 'NaN';else% 格式化结果absValue = abs(result);% 如果是整数且不大,显示为整数if result == floor(result) && absValue < 1e10app.EditField.Value = sprintf('%d', result);elseif absValue > 1e10 || (absValue < 1e-6 && absValue > 0)% 使用科学计数法显示formatted = sprintf('%.6e', result);% 简化显示formatted = regexprep(formatted, '(\.[0-9]*?)0+e', '$1e');formatted = regexprep(formatted, '\.e', 'e');app.EditField.Value = formatted;else% 普通小数,最多显示10位有效数字formatted = sprintf('%.10g', result);% 移除末尾的0formatted = regexprep(formatted, '\.0*$|(\.\d*?)0+$', '$1');if ~isempty(formatted) && formatted(end) == '.'formatted = formatted(1:end-1);endapp.EditField.Value = formatted;end% 保存计算结果到属性中(如果有定义)if isprop(app, 'LastResult')app.LastResult = result;endif isprop(app, 'LastExpression')app.LastExpression = currentText;endendcatch ME% 错误处理errorMsg = ME.message;if contains(errorMsg, 'division by zero')app.EditField.Value = 'Inf';elseif contains(errorMsg, 'Undefined function')app.EditField.Value = 'Error: 未定义函数';elseif contains(errorMsg, '未定义的变量')app.EditField.Value = 'Error: 未定义变量';elseif contains(errorMsg, '括号')app.EditField.Value = 'Error: 括号错误';elseapp.EditField.Value = 'Error';end% 在命令行显示详细错误信息(可选)fprintf('计算错误: %s\n', errorMsg);end
13.下面为清除的回调函数
app.EditField.Value = '0';
14.下面为删除的回调函数
currentText = app.EditField.Value;if strcmp(currentText, '0')return; % 补充分号,符合MATLAB语法规范endif isempty(app.EditField.Value)app.EditField.Value = '0';elseapp.EditField.Value(end) = [];end
通过这些设置,就得到了一个完整的计算器,下面是演示动画:
已关注
关注
重播 分享 赞
至此一个简单的计算器就设计完成了,欢迎大家评论区互相交流~
源码后台私信“app3”自动发送
– END –
夜雨聆风
