MATLAB 之 App designer 小白学习(二)
三 示例学习
2.响应数值输入
(1)主页——新建——APP——响应数值输入
(2)知识点解读
这里将学习 数值输入 响应 图像的相关内容。界面如下,包括左面板:四个数值文本编辑框、一个按钮button、右面板:一个坐标区,坐标区内有网格布局,并相应地对控件的名称、属性进行了修改,这些内容可以自行尝试设计。
我们进入代码视图,学习如何编程实现 界面输入数值 进行 绘图。我按顺次一段一段进行分析。
classdef Mortgage < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
MortgageCalculatorUIFigure matlab.ui.Figure
GridLayout matlab.ui.container.GridLayout
LeftPanel matlab.ui.container.Panel
LoanAmountEditFieldLabel matlab.ui.control.Label
LoanAmountEditField matlab.ui.control.NumericEditField
InterestRateEditFieldLabel matlab.ui.control.Label
InterestRateEditField matlab.ui.control.NumericEditField
LoanPeriodYearsEditFieldLabel matlab.ui.control.Label
LoanPeriodYearsEditField matlab.ui.control.NumericEditField
MonthlyPaymentButton matlab.ui.control.Button
MonthlyPaymentEditField matlab.ui.control.NumericEditField
RightPanel matlab.ui.container.Panel
PrincipalInterestUIAxes matlab.ui.control.UIAxes
end
这段代码的作用: 定义APP类,类名称为 Mortgage,控件属性有 :整个界面图布 MortgageCalculatorUIFigure、 网格布局GridLayout、LeftPanel 左面板、数值文本编辑框 及相应的文本框标签LoanAmountEditFieldLabel、LoanAmountEditField、 InterestRateEditFieldLabel、InterestRateEditField , LoanPeriodYearsEditFieldLabel 、LoanPeriodYearsEditField 、 MonthlyPaymentEditField ;按钮 MonthlyPaymentButton 、右面板 RightPanel、坐标区PrincipalInterestUIAxes
% Properties that correspond to apps with auto-reflow
properties (Access = private)
onePanelWidth = 576;
end
界面自动重排刷新时的属性定义
onePanelWidth = 576;
因为这个界面是分为左面板和右面板两个面板,所以这里只定义了一个面板宽度。意思就是,当你在运行程序的时候,程序界面可以最大化,也可以手动调整大小,为了自适应界面的大小变化,这里固定了一个面板的宽度,无论界面变大变小,这个面板的宽度始终为576.
可以对比一下,小界面为下图
我拉大界面后,可以发现左面板的宽度始终不变,右面板宽度在随界面大小变化。
类比一下,如果是三栏式的,就需要对其中两个进行控制,这样的话界面不容易崩溃报错,如下面黄色部分。
% Properties that correspond to apps with auto-reflow
properties (Access = private)
onePanelWidth = 576;
twoPanelWidth = 768;
end
但是这两个代码实际意义只是定义面板宽度值,给定这两个面板的宽度是确定值,方便后面对界面调整大小的操作。
我们继续分析接下来的代码
% Callbacks that handle component events
methods (Access = private)
% Changes arrangement of the app based on UIFigure width
function updateAppLayout(app, event)
currentFigureWidth = app.MortgageCalculatorUIFigure.Position(3);
if(currentFigureWidth <= app.onePanelWidth)
% Change to a 2x1 grid
app.GridLayout.RowHeight = {316, 316};
app.GridLayout.ColumnWidth = {\'1x\'};
app.RightPanel.Layout.Row = 2;
app.RightPanel.Layout.Column = 1;
else
% Change to a 1x2 grid
app.GridLayout.RowHeight = {\'1x\'};
app.GridLayout.ColumnWidth = {257, \'1x\'};
app.RightPanel.Layout.Row = 1;
app.RightPanel.Layout.Column = 2;
end
end
% Button pushed function: MonthlyPaymentButton
function MonthlyPaymentButtonPushed(app, event)
% Calculate the monthly payment
amount = app.LoanAmountEditField.Value ;
rate = app.InterestRateEditField.Value/12/100 ;
nper = 12*app.LoanPeriodYearsEditField.Value ;
payment = (amount*rate)/(1-(1+rate)^-nper);
app.MonthlyPaymentEditField.Value = payment;
% pre allocating and initializing variables
interest = zeros(1,nper);
principal = zeros(1,nper);
balance = zeros (1,nper);
balance(1) = amount;
% Calculate the principal and interest over time
for i = 1:nper
interest(i) = balance(i)*rate ;
principal(i) = payment - interest(i) ;
balance(i+1) = balance(i) - principal(i) ;
end
% Plot the principal and interest
plot(app.PrincipalInterestUIAxes, (1:nper)\', principal, ...
(1:nper)\', interest) ;
legend(app.PrincipalInterestUIAxes,{\'Principal\',\'Interest\'},\'Location\',\'Best\')
xlim(app.PrincipalInterestUIAxes,[0 nper]) ;
end
end
这部分是回调函数,内容相对较多,我们分两部分来看,我用不同颜色标识。
第一块的内容是调整界面大小:前文提到,定义了一个面板的宽度为固定值。当总界面的宽度比刚才一个面板的宽度还要小时,界面就变成了1×2 的布局,什么意思呢,看下图
相应的,当界面宽度大于一个面板宽度时,就是2×1的布局,也就是下面这种布局。而其他时候,则左面板宽度不变,右面板大小随界面变化。
第二大块是按钮的回调函数,也就是当运行时按下按钮希望执行的操作:
代码 amount = app.LoanAmountEditField.Value ; 执行的是读取LoanAmountEditField文本编辑框里的内容,赋值给amount;
代码:rate = app.InterestRateEditField.Value/12/100 ;执行的是读取InterestRateEditField并进行/12/100 的数值运算,最后赋值给rate;
代码:nper = 12*app.LoanPeriodYearsEditField.Value可类比上面两行。
由此看出,欲读取文本框(数值)内容,可采用 变量=app.XX.value的方式,同时,还可以进行数值运算,数值运算可以前置也可以后置,和一般的数值运算表达式一致。
代码:payment = (amount*rate)/(1-(1+rate)^-nper); 对读取的数值进行计算。
代码:app.MonthlyPaymentEditField.Value = payment;将上面计算的结果赋值给 MonthlyPaymentEditField 文本框。
由此可以看出,文本编辑框既可以作为数值输入,也可以作为数值输出。
接下来的代码是初始化变量,zeros(1,nper)是建立1行nper列的零矩阵。balance(1) = amount,即将amount赋值给balance的第一个数。
再下面是计算过程。采用的for循环,i从1到nper,这里的nper也就是上文文本框输入值进行计算后赋值的一个数字。对三个变量分别迭代计算求解,并且用向量矩阵的方式,将每一次迭代的值保存在矩阵中。
for循环计算结束后,是画图区,代码:
plot(app.PrincipalInterestUIAxes, (1:nper)\', principal, ...
(1:nper)\', interest) ; 这里的...是续行符,用于多行输入代码; plot 是绘图指令,括号第一个变量app.PrincipalInterestUIAxes是指绘图的结果在这个绘图区显示;后面的变量分别是横坐标、纵坐标、横坐标、纵坐标。
legend(app.PrincipalInterestUIAxes,{\'Principal\',\'Interest\'},\'Location\',\'Best\') 这和MATLAB的基本代码含义一样,定义图例名称
xlim(app.PrincipalInterestUIAxes,[0 nper]) ;定义横坐标范围
由此可以看到,欲在绘图区xxx里绘图,需要调用函数 plot (app.xxx, x,y,x2,y2.)
剩下的代码是对组件初始化的属性定义和APP创建/删除两部分,在之前设计界面是通过拖拽控件、在检查器里修改相应的属性参数,这部分会自动生成,所以一般不需要再修改。之后的学习中,为了篇幅,也不再对这部分内容进行分析,直接跳过。
% Component initialization methods (Access = private) % Create UIFigure and components function createComponents(app) % Create MortgageCalculatorUIFigure and hide until all components are created app.MortgageCalculatorUIFigure = uifigure(\'Visible\', \'off\'); app.MortgageCalculatorUIFigure.AutoResizeChildren = \'off\'; app.MortgageCalculatorUIFigure.Position = [100 100 653 316]; app.MortgageCalculatorUIFigure.Name = \'Mortgage Calculator\'; app.MortgageCalculatorUIFigure.SizeChangedFcn = createCallbackFcn(app, @updateAppLayout, true); % Create GridLayout app.GridLayout = uigridlayout(app.MortgageCalculatorUIFigure); app.GridLayout.ColumnWidth = {257, \'1x\'}; app.GridLayout.RowHeight = {\'1x\'}; app.GridLayout.ColumnSpacing = 0; app.GridLayout.RowSpacing = 0; app.GridLayout.Padding = [0 0 0 0]; app.GridLayout.Scrollable = \'on\'; % Create LeftPanel app.LeftPanel = uipanel(app.GridLayout); app.LeftPanel.Layout.Row = 1; app.LeftPanel.Layout.Column = 1; app.LeftPanel.Scrollable = \'on\'; % Create LoanAmountEditFieldLabel app.LoanAmountEditFieldLabel = uilabel(app.LeftPanel); app.LoanAmountEditFieldLabel.HorizontalAlignment = \'right\'; app.LoanAmountEditFieldLabel.Position = [50 230 77 22]; app.LoanAmountEditFieldLabel.Text = \'Loan Amount\'; % Create LoanAmountEditField app.LoanAmountEditField = uieditfield(app.LeftPanel, \'numeric\'); app.LoanAmountEditField.Limits = [0 10000000]; app.LoanAmountEditField.ValueDisplayFormat = \'%8.f\'; app.LoanAmountEditField.Position = [142 230 100 22]; app.LoanAmountEditField.Value = 300000; % Create InterestRateEditFieldLabel app.InterestRateEditFieldLabel = uilabel(app.LeftPanel); app.InterestRateEditFieldLabel.HorizontalAlignment = \'right\'; app.InterestRateEditFieldLabel.Position = [39 177 88 22]; app.InterestRateEditFieldLabel.Text = \'Interest Rate %\'; % Create InterestRateEditField app.InterestRateEditField = uieditfield(app.LeftPanel, \'numeric\'); app.InterestRateEditField.Limits = [0.001 100]; app.InterestRateEditField.Position = [142 177 100 22]; app.InterestRateEditField.Value = 4; % Create LoanPeriodYearsEditFieldLabel app.LoanPeriodYearsEditFieldLabel = uilabel(app.LeftPanel); app.LoanPeriodYearsEditFieldLabel.HorizontalAlignment = \'right\'; app.LoanPeriodYearsEditFieldLabel.Position = [15 124 112 22]; app.LoanPeriodYearsEditFieldLabel.Text = \'Loan Period (Years)\'; % Create LoanPeriodYearsEditField app.LoanPeriodYearsEditField = uieditfield(app.LeftPanel, \'numeric\'); app.LoanPeriodYearsEditField.Limits = [10 40]; app.LoanPeriodYearsEditField.ValueDisplayFormat = \'%.0f\'; app.LoanPeriodYearsEditField.Position = [142 124 100 22]; app.LoanPeriodYearsEditField.Value = 30; % Create MonthlyPaymentButton app.MonthlyPaymentButton = uibutton(app.LeftPanel, \'push\'); app.MonthlyPaymentButton.ButtonPushedFcn = createCallbackFcn(app, @MonthlyPaymentButtonPushed, true); app.MonthlyPaymentButton.Position = [19 71 108 22]; app.MonthlyPaymentButton.Text = \'Monthly Payment\'; % Create MonthlyPaymentEditField app.MonthlyPaymentEditField = uieditfield(app.LeftPanel, \'numeric\'); app.MonthlyPaymentEditField.ValueDisplayFormat = \'%7.2f\'; app.MonthlyPaymentEditField.Editable = \'off\'; app.MonthlyPaymentEditField.Position = [142 71 100 22]; % Create RightPanel app.RightPanel = uipanel(app.GridLayout); app.RightPanel.Layout.Row = 1; app.RightPanel.Layout.Column = 2; app.RightPanel.Scrollable = \'on\'; % Create PrincipalInterestUIAxes app.PrincipalInterestUIAxes = uiaxes(app.RightPanel); title(app.PrincipalInterestUIAxes, \'Principal and Interest\') xlabel(app.PrincipalInterestUIAxes, \'Time (Months)\') ylabel(app.PrincipalInterestUIAxes, \'Amount\') app.PrincipalInterestUIAxes.Position = [30 36 326 250]; % Show the figure after all components are created app.MortgageCalculatorUIFigure.Visible = \'on\'; end end % App creation and deletion methods (Access = public) % Construct app function app = Mortgage % Create UIFigure and components createComponents(app) % Register the app with App Designer registerApp(app, app.MortgageCalculatorUIFigure) if nargout == 0 clear app end end % Code that executes before app deletion function delete(app) % Delete UIFigure when app is deleted delete(app.MortgageCalculatorUIFigure) end end end
至此,我们了解了界面大小调整的程序含义,同时学习了如何 利用识别文本框的输入值、并且如何输出结果值在文本框中;另外还学习了如何在指定的绘图区中绘图。
下面我们学习第三个教程,我另起第三个文档,跟紧哦!