MATLAB 之 App designer 小白学习(二) - 挽年_Sonny

时间:2024-03-10 16:07:11

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

  

  至此,我们了解了界面大小调整的程序含义,同时学习了如何 利用识别文本框的输入值、并且如何输出结果值在文本框中;另外还学习了如何在指定的绘图区中绘图。

  下面我们学习第三个教程,我另起第三个文档,跟紧哦!