MATLAB 之 APP DESIGNER 学习(三) - 挽年_Sonny

时间:2024-02-18 15:41:02

MATLAB 之 APP DESIGNER 学习(三)

学习(一)学习(二)

三、示例学习

3.响应用户选择

 

  有了学习(一)和学习(二)的基础,我直接开门见山,分析其中的核心部分。

(1)界面

  相比之前两个的界面,这个界面要高级很多了。首先是整个界面分为两个面板,左面板和右面板。

左面板部分从上到下依次是控件:

  标签Data Selection

  三个小面板,第一个面板上的title 为location,放着下拉框; 

  第二个面板的title是Gender,放着两个复选框Male 和 female;

  第三个面板的title是smoker,放着两个复选框yes和no

右面板部分上方有图窗工具菜单栏,在第一个子项plot中,从上到下依次是

  仪器工具中的开关

  绘图区

  button组

  滑块

菜单第二个子项data中,放的是

  表

  如下图。

    对控件进行相应的命名、属性的修改。

(2)代码

  先把源代码贴过来,代码分析见后。

classdef PatientsDisplay < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        PatientsDisplayUIFigure    matlab.ui.Figure
        GridLayout                 matlab.ui.container.GridLayout
        LeftPanel                  matlab.ui.container.Panel
        Panel2                     matlab.ui.container.Panel
        FemaleCheckBox             matlab.ui.control.CheckBox
        MaleCheckBox               matlab.ui.control.CheckBox
        Panel2_2                   matlab.ui.container.Panel
        NoCheckBox                 matlab.ui.control.CheckBox
        YesCheckBox                matlab.ui.control.CheckBox
        Panel2_4                   matlab.ui.container.Panel
        HospitalNameDropDownLabel  matlab.ui.control.Label
        HospitalNameDropDown       matlab.ui.control.DropDown
        DataSelectionLabel         matlab.ui.control.Label
        RightPanel                 matlab.ui.container.Panel
        TabGroup                   matlab.ui.container.TabGroup
        PlotTab                    matlab.ui.container.Tab
        UIAxes                     matlab.ui.control.UIAxes
        BinWidthSliderLabel        matlab.ui.control.Label
        BinWidthSlider             matlab.ui.control.Slider
        ButtonGroup                matlab.ui.container.ButtonGroup
        ScatterButton              matlab.ui.control.RadioButton
        HistogramButton            matlab.ui.control.RadioButton
        BloodPressureSwitchLabel   matlab.ui.control.Label
        BloodPressureSwitch        matlab.ui.control.Switch
        DataTab                    matlab.ui.container.Tab
        UITable                    matlab.ui.control.Table
    end

    % Properties that correspond to apps with auto-reflow
    properties (Access = private)
        onePanelWidth = 576;
    end

    % The app displays the data by using the scatter plot, histogram, and table.
    % It makes use of tabs to separate the ploting options output from the table display of the data.
    % There are several graphical elements used such as checkboxes, slider, switch, dropdown, and radiobutton group.
    % The data used in the app is shiped with the product.
    
    properties (Access = private)
        % Declare properties of the PatientsDisplay class.
        Data
        SelectedGenders
        SelectedColors
        BinWidth
        Histogram = gobjects(0)
        displayedIndices
    end
    
    methods (Access = private)
        
        function NBins = numhistbins(app,data)
            % Utility function to compute the number of histogram bins
            binwidth = app.BinWidth;
            range2plot =  floor(min(data)):binwidth:ceil(max(data));
            NBins = size(range2plot,2);
        end
        
        function annotateScatterPlot(app)
            % Update X and Y Labels
            app.UIAxes.XLabel.String = \'Weight\';
            app.UIAxes.YLabel.String = app.BloodPressureSwitch.Value;
            % Dont show the histogram slider
            app.BinWidthSliderLabel.Visible = \'off\';
            app.BinWidthSlider.Visible = \'off\';
        end
        
        function annotateHistogram(app)
           
            % Update X and Y Labels
            app.UIAxes.XLabel.String = app.BloodPressureSwitch.Value;
            app.UIAxes.YLabel.String = \'# of Patients\';
            
            % Show histogram slider
            app.BinWidthSliderLabel.Visible = \'on\';
            app.BinWidthSlider.Visible = \'on\';
        end
        
        function filterData(app)
            % Utility function to filter the data according to the controls
            
            % Initially assume that all data will be displayed and then, subsequently, filter the data
            % based on the controls
            tempIndices = ones([size(app.Data,1),1]);
            
            % Append a column to tempIndices to indicate data that satisfies the smoker control
            if app.NoCheckBox.Value && ~app.YesCheckBox.Value
                tempIndices = [tempIndices, app.Data.Smoker == 0];
            elseif app.YesCheckBox.Value && ~app.NoCheckBox.Value
                tempIndices = [tempIndices, app.Data.Smoker == 1];
            elseif  ~app.YesCheckBox.Value && ~app.NoCheckBox.Value
                tempIndices = [tempIndices, zeros([size(app.Data,1),1])];
            end
            
            % Append a column to tempIndices to indicate data that satisfies the gender control
            if app.MaleCheckBox.Value && ~app.FemaleCheckBox.Value
                tempIndices = [tempIndices, app.Data.Gender == "Male"];
            elseif app.FemaleCheckBox.Value && ~app.MaleCheckBox.Value
                tempIndices = [tempIndices, app.Data.Gender == "Female"];
            elseif  ~app.FemaleCheckBox.Value && ~app.MaleCheckBox.Value
                tempIndices = [tempIndices, zeros([size(app.Data,1),1])];
            end
            
            % Append a column to tempIndices to indicate data that satisfies the location control
            if app.HospitalNameDropDown.Value ~= "All"
                tempIndices = [tempIndices, app.Data.Location == string(app.HospitalNameDropDown.Value)];
            end
            
            % Determine which data points satisfy all requirements
            app.displayedIndices = (sum(tempIndices,2)/size(tempIndices,2) == 1);
        end
    end

    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
            % Load the data.
            load(\'patients.mat\',\'LastName\',\'Gender\',\'Smoker\',\'Age\',\'Height\',\'Weight\',\'Diastolic\',\'Systolic\',\'Location\');
            
            % Store the data in a table and display it in one of the App\'s tabs.
            app.Data = table(LastName,Gender,Smoker,Age,Height,Weight,Diastolic,Systolic,Location);
            app.UITable.Data = app.Data;
            app.BinWidth = app.BinWidthSlider.Value;
            
            % Update the axes with the corresponding data.
            updateSelectedGenders(app)
            refreshplot(app)
        end

        % Changes arrangement of the app based on UIFigure width
        function updateAppLayout(app, event)
            currentFigureWidth = app.PatientsDisplayUIFigure.Position(3);
            if(currentFigureWidth <= app.onePanelWidth)
                % Change to a 2x1 grid
                app.GridLayout.RowHeight = {400, 400};
                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 = {282, \'1x\'};
                app.RightPanel.Layout.Row = 1;
                app.RightPanel.Layout.Column = 2;
            end
        end

        % Value changing function: BinWidthSlider
        function SliderValueChanging(app, event)
            % Update the histogram as the slider value for bindwidth changes.
            app.BinWidth = event.Value;
            for ii=1:length(app.Histogram)
                app.Histogram(ii).NumBins = numhistbins(app,app.Histogram(ii).Data);
            end
        end

        % Callback function: BinWidthSlider, BloodPressureSwitch, 
        % ButtonGroup, UITable
        function refreshplot(app, event)
            Genders = app.SelectedGenders;
            Colors = app.SelectedColors;
            
            % Start with a fresh plot
            cla(app.UIAxes)
            hold(app.UIAxes,\'on\')
            app.Histogram = gobjects(0);
            
            % Select relevant segment of data
            xdata = app.Data.Weight;
            ydata = app.Data.(app.BloodPressureSwitch.Value);
            
            % Filter the data according to the controls
            filterData(app);
            
            % Create either a scatter plot or histogram, based on selection
            switch app.ButtonGroup.SelectedObject.Text
                
                case \'Scatter\'
                    % Build a scatter plot for each selected gender
                    for ii = 1:length(Genders)
                        selectedpatients = ((app.Data.Gender == Genders(ii)) & (app.displayedIndices));
                        scatter(app.UIAxes,xdata((selectedpatients)),ydata(selectedpatients),Colors{ii});
                    end
                    annotateScatterPlot(app)
                    
                case \'Histogram\'
                    % Build a histogram for each selected gender
                    for ii = 1:length(Genders)
                        selectedpatients = ((app.Data.Gender == Genders(ii)) & (app.displayedIndices));
                        NBins = numhistbins(app,ydata(selectedpatients));
                        h = histogram(app.UIAxes,ydata(selectedpatients),NBins,\'BinLimits\',[floor(min(ydata)) ceil(max(ydata))]);
                        h.EdgeColor = Colors{ii};
                        h.FaceColor = Colors{ii};
                        app.Histogram = [app.Histogram h];
                    end
                    annotateHistogram(app)
                    
            end
            
            % Update the table to show only the data that satisfies the controls
            app.UITable.Data = app.Data(app.displayedIndices,:);
            drawnow;
        end

        % Value changed function: FemaleCheckBox, 
        % HospitalNameDropDown, MaleCheckBox, NoCheckBox, 
        % YesCheckBox
        function updateSelectedGenders(app, event)
            % List which genders and colors to use
            Genders = [];
            Colors = [];
            Smoker = [];
            
            if app.MaleCheckBox.Value
                Genders = "Male";
                Colors = "blue";
            end
            if app.FemaleCheckBox.Value
                Genders = [Genders "Female"];
                Colors = [Colors "red"];
            end
            if app.YesCheckBox.Value
                Smoker = "Yes";
            end
            if app.NoCheckBox.Value
                Smoker = [Smoker "No"];
            end
            
            if isempty(Genders) || isempty(Smoker)
                % Disable the switches and buttons if they were on
                app.BloodPressureSwitch.Enable = \'off\';
                app.ScatterButton.Enable = \'off\';
                app.HistogramButton.Enable = \'off\';
                app.BinWidthSliderLabel.Enable = \'off\';
                app.BinWidthSlider.Enable = \'off\';
            else
                % Enable the switches and buttons if they were off
                app.BloodPressureSwitch.Enable = \'on\';
                app.ScatterButton.Enable = \'on\';
                app.HistogramButton.Enable = \'on\';
                app.BinWidthSliderLabel.Enable = \'on\';
                app.BinWidthSlider.Enable = \'on\';
            end
            app.SelectedGenders = Genders;
            app.SelectedColors = Colors;
            
            refreshplot(app)
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create PatientsDisplayUIFigure and hide until all components are created
            app.PatientsDisplayUIFigure = uifigure(\'Visible\', \'off\');
            app.PatientsDisplayUIFigure.AutoResizeChildren = \'off\';
            app.PatientsDisplayUIFigure.Position = [100 100 703 400];
            app.PatientsDisplayUIFigure.Name = \'Patients Display\';
            app.PatientsDisplayUIFigure.SizeChangedFcn = createCallbackFcn(app, @updateAppLayout, true);

            % Create GridLayout
            app.GridLayout = uigridlayout(app.PatientsDisplayUIFigure);
            app.GridLayout.ColumnWidth = {282, \'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 Panel2
            app.Panel2 = uipanel(app.LeftPanel);
            app.Panel2.AutoResizeChildren = \'off\';
            app.Panel2.Title = \'Gender\';
            app.Panel2.Position = [9 123 269 97];

            % Create FemaleCheckBox
            app.FemaleCheckBox = uicheckbox(app.Panel2);
            app.FemaleCheckBox.ValueChangedFcn = createCallbackFcn(app, @updateSelectedGenders, true);
            app.FemaleCheckBox.Text = \'Female\';
            app.FemaleCheckBox.Position = [12 14 60 16];

            % Create MaleCheckBox
            app.MaleCheckBox = uicheckbox(app.Panel2);
            app.MaleCheckBox.ValueChangedFcn = createCallbackFcn(app, @updateSelectedGenders, true);
            app.MaleCheckBox.Text = \'Male\';
            app.MaleCheckBox.Position = [12 44 46 16];
            app.MaleCheckBox.Value = true;

            % Create Panel2_2
            app.Panel2_2 = uipanel(app.LeftPanel);
            app.Panel2_2.AutoResizeChildren = \'off\';
            app.Panel2_2.Title = \'Smoker\';
            app.Panel2_2.Position = [9 7 268 97];

            % Create NoCheckBox
            app.NoCheckBox = uicheckbox(app.Panel2_2);
            app.NoCheckBox.ValueChangedFcn = createCallbackFcn(app, @updateSelectedGenders, true);
            app.NoCheckBox.Text = \'No\';
            app.NoCheckBox.Position = [12 12 60 22];
            app.NoCheckBox.Value = true;

            % Create YesCheckBox
            app.YesCheckBox = uicheckbox(app.Panel2_2);
            app.YesCheckBox.ValueChangedFcn = createCallbackFcn(app, @updateSelectedGenders, true);
            app.YesCheckBox.Text = \'Yes\';
            app.YesCheckBox.Position = [12 42 46 22];
            app.YesCheckBox.Value = true;

            % Create Panel2_4
            app.Panel2_4 = uipanel(app.LeftPanel);
            app.Panel2_4.AutoResizeChildren = \'off\';
            app.Panel2_4.Title = \'Location\';
            app.Panel2_4.Position = [9 242 269 97];

            % Create HospitalNameDropDownLabel
            app.HospitalNameDropDownLabel = uilabel(app.Panel2_4);
            app.HospitalNameDropDownLabel.HorizontalAlignment = \'right\';
            app.HospitalNameDropDownLabel.Position = [8 27 84 22];
            app.HospitalNameDropDownLabel.Text = \'Hospital Name\';

            % Create HospitalNameDropDown
            app.HospitalNameDropDown = uidropdown(app.Panel2_4);
            app.HospitalNameDropDown.Items = {\'County General Hospital\', \'St. Mary\'\'s Medical Center\', \'VA Hospital\', \'All\'};
            app.HospitalNameDropDown.ValueChangedFcn = createCallbackFcn(app, @updateSelectedGenders, true);
            app.HospitalNameDropDown.Position = [107 27 153 22];
            app.HospitalNameDropDown.Value = \'All\';

            % Create DataSelectionLabel
            app.DataSelectionLabel = uilabel(app.LeftPanel);
            app.DataSelectionLabel.HorizontalAlignment = \'center\';
            app.DataSelectionLabel.FontSize = 15;
            app.DataSelectionLabel.FontWeight = \'bold\';
            app.DataSelectionLabel.Position = [9 356 267 22];
            app.DataSelectionLabel.Text = \'Data Selection\';

            % Create RightPanel
            app.RightPanel = uipanel(app.GridLayout);
            app.RightPanel.Layout.Row = 1;
            app.RightPanel.Layout.Column = 2;
            app.RightPanel.Scrollable = \'on\';

            % Create TabGroup
            app.TabGroup = uitabgroup(app.RightPanel);
            app.TabGroup.Position = [7 6 408 387];

            % Create PlotTab
            app.PlotTab = uitab(app.TabGroup);
            app.PlotTab.Title = \'Plot\';

            % Create UIAxes
            app.UIAxes = uiaxes(app.PlotTab);
            xlabel(app.UIAxes, \'Weight\')
            ylabel(app.UIAxes, \'Diastolic\')
            app.UIAxes.GridAlpha = 0.15;
            app.UIAxes.MinorGridAlpha = 0.25;
            app.UIAxes.Box = \'on\';
            app.UIAxes.Position = [19 89 376 215];

            % Create BinWidthSliderLabel
            app.BinWidthSliderLabel = uilabel(app.PlotTab);
            app.BinWidthSliderLabel.HorizontalAlignment = \'center\';
            app.BinWidthSliderLabel.VerticalAlignment = \'top\';
            app.BinWidthSliderLabel.Position = [241 63 76 15];
            app.BinWidthSliderLabel.Text = \'Bin Width\';

            % Create BinWidthSlider
            app.BinWidthSlider = uislider(app.PlotTab);
            app.BinWidthSlider.Limits = [1 11];
            app.BinWidthSlider.MajorTicks = [1 2 3 4 5 6 7 8 9 10 11];
            app.BinWidthSlider.ValueChangedFcn = createCallbackFcn(app, @refreshplot, true);
            app.BinWidthSlider.ValueChangingFcn = createCallbackFcn(app, @SliderValueChanging, true);
            app.BinWidthSlider.MinorTicks = [];
            app.BinWidthSlider.Position = [183 46 192 3];
            app.BinWidthSlider.Value = 5;

            % Create ButtonGroup
            app.ButtonGroup = uibuttongroup(app.PlotTab);
            app.ButtonGroup.AutoResizeChildren = \'off\';
            app.ButtonGroup.SelectionChangedFcn = createCallbackFcn(app, @refreshplot, true);
            app.ButtonGroup.Title = \'Plotting Options\';
            app.ButtonGroup.Position = [18 4 148 79];

            % Create ScatterButton
            app.ScatterButton = uiradiobutton(app.ButtonGroup);
            app.ScatterButton.Text = \'Scatter\';
            app.ScatterButton.Position = [11 34 103 15];
            app.ScatterButton.Value = true;

            % Create HistogramButton
            app.HistogramButton = uiradiobutton(app.ButtonGroup);
            app.HistogramButton.Text = \'Histogram\';
            app.HistogramButton.Position = [11 12 103 15];

            % Create BloodPressureSwitchLabel
            app.BloodPressureSwitchLabel = uilabel(app.PlotTab);
            app.BloodPressureSwitchLabel.HorizontalAlignment = \'center\';
            app.BloodPressureSwitchLabel.VerticalAlignment = \'top\';
            app.BloodPressureSwitchLabel.Position = [132 340 151 15];
            app.BloodPressureSwitchLabel.Text = \'Blood Pressure\';

            % Create BloodPressureSwitch
            app.BloodPressureSwitch = uiswitch(app.PlotTab, \'slider\');
            app.BloodPressureSwitch.Items = {\'Systolic\', \'Diastolic\'};
            app.BloodPressureSwitch.ValueChangedFcn = createCallbackFcn(app, @refreshplot, true);
            app.BloodPressureSwitch.Position = [190 309 34 15];
            app.BloodPressureSwitch.Value = \'Systolic\';

            % Create DataTab
            app.DataTab = uitab(app.TabGroup);
            app.DataTab.Title = \'Data\';

            % Create UITable
            app.UITable = uitable(app.DataTab);
            app.UITable.ColumnName = {\'Last Name\'; \'Gender\'; \'Smoker\'; \'Age\'; \'Height\'; \'Weight\'; \'Diastolic\'; \'Systolic\'; \'Location\'};
            app.UITable.RowName = {};
            app.UITable.ColumnSortable = true;
            app.UITable.RowStriping = \'off\';
            app.UITable.CellSelectionCallback = createCallbackFcn(app, @refreshplot, true);
            app.UITable.Position = [1 1 407 358];

            % Show the figure after all components are created
            app.PatientsDisplayUIFigure.Visible = \'on\';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = PatientsDisplay

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.PatientsDisplayUIFigure)

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.PatientsDisplayUIFigure)
        end
    end
end

(3)知识点分析

  略去之前已经分析过的部分,在Properties部分,我们看到,除了前面提及的控件属性、窗口宽度外,增加了很大一部分内容,这部分是关于数据载入、直方图/散点图/表格等内容的辅助程序。

 properties (Access = private)
        % Declare properties of the PatientsDisplay class.
        Data
        SelectedGenders
        SelectedColors
        BinWidth
        Histogram = gobjects(0)
        displayedIndices
    end

  这个app类叫做PatientsDisplay,这部分声明这个类里私有成分,包括Data、SelectedGenders、SelectedColors、BinWidth、Histogram = gobjects(0)、displayedIndices。

 function NBins = numhistbins(app,data)
            % Utility function to compute the number of histogram bins
            binwidth = app.BinWidth;
            range2plot =  floor(min(data)):binwidth:ceil(max(data));
            NBins = size(range2plot,2);
        end

  这个函数是用于计算 直方图 每一条柱的数据: 将滑块读取的BinWidth的值赋值给binwidth,range2plot是最小值到最大值的范围的向量,NBins是直方图每一个条形的宽度。

  floor()这个函数是向下取整。

function annotateScatterPlot(app)
            % Update X and Y Labels
            app.UIAxes.XLabel.String = \'Weight\';
            app.UIAxes.YLabel.String = app.BloodPressureSwitch.Value;
            % Dont show the histogram slider
            app.BinWidthSliderLabel.Visible = \'off\';
            app.BinWidthSlider.Visible = \'off\';
        end

  绘制散点图时,坐标区的x的名称为Weight,Y坐标的名称根据控件开关的状态更新;滑块及其标签隐藏。

function annotateHistogram(app)
           
            % Update X and Y Labels
            app.UIAxes.XLabel.String = app.BloodPressureSwitch.Value;
            app.UIAxes.YLabel.String = \'# of Patients\';
            
            % Show histogram slider
            app.BinWidthSliderLabel.Visible = \'on\';
            app.BinWidthSlider.Visible = \'on\';
        end

  绘制直方图时,坐标区的x的名称根据控件状态变化,Y坐标的名称为# of Patients滑块及其标签显示。

  重点: 控制某个控件是否可见,采用:app.XXX.Visible=\'on\'或者 \'off\';坐标区的X、Y坐标名称也可以根据控件的状态进行更改,方式为app.XXX.XLabel.String = \'Weight\'

  读取开关控件的值采用的程序语句为:XXX= app.xxx.Value。

function filterData(app)
            % Utility function to filter the data according to the controls
            
            % Initially assume that all data will be displayed and then, subsequently, filter the data
            % based on the controls
            tempIndices = ones([size(app.Data,1),1]);
            
            % Append a column to tempIndices to indicate data that satisfies the smoker control
            if app.NoCheckBox.Value && ~app.YesCheckBox.Value
                tempIndices = [tempIndices, app.Data.Smoker == 0];
            elseif app.YesCheckBox.Value && ~app.NoCheckBox.Value
                tempIndices = [tempIndices, app.Data.Smoker == 1];
            elseif  ~app.YesCheckBox.Value && ~app.NoCheckBox.Value
                tempIndices = [tempIndices, zeros([size(app.Data,1),1])];
            end
            
            % Append a column to tempIndices to indicate data that satisfies the gender control
            if app.MaleCheckBox.Value && ~app.FemaleCheckBox.Value
                tempIndices = [tempIndices, app.Data.Gender == "Male"];
            elseif app.FemaleCheckBox.Value && ~app.MaleCheckBox.Value
                tempIndices = [tempIndices, app.Data.Gender == "Female"];
            elseif  ~app.FemaleCheckBox.Value && ~app.MaleCheckBox.Value
                tempIndices = [tempIndices, zeros([size(app.Data,1),1])];
            end
            
            % Append a column to tempIndices to indicate data that satisfies the location control
            if app.HospitalNameDropDown.Value ~= "All"
                tempIndices = [tempIndices, app.Data.Location == string(app.HospitalNameDropDown.Value)];
            end
            
            % Determine which data points satisfy all requirements
            app.displayedIndices = (sum(tempIndices,2)/size(tempIndices,2) == 1);
        end
    end

  这部分程序的功能是数据选用。ones(x,y)定义x行y列的单元向量。

  接下来的if语句是判别复选框状态的语句。其中,~ app.YesCheckBox.Value中前面的~是非的意思。

  其余部分自行理解,这里需要重点说明:

  复选框的程序调用方法:

 if app.A.Value && ~app.B.Value
                xxxx;
elseif app.B.Value && ~app.A.Value YYYY; elseif ~app.A.Value && ~app.B.Value 0000; end

  下拉框的程序调用方法:

  XXX == string(app.DropDown.Value)

  % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
            % Load the data.
            load(\'patients.mat\',\'LastName\',\'Gender\',\'Smoker\',\'Age\',\'Height\',\'Weight\',\'Diastolic\',\'Systolic\',\'Location\');
            
            % Store the data in a table and display it in one of the App\'s tabs.
            app.Data = table(LastName,Gender,Smoker,Age,Height,Weight,Diastolic,Systolic,Location);
            app.UITable.Data = app.Data;
            app.BinWidth = app.BinWidthSlider.Value;
            
            % Update the axes with the corresponding data.
            updateSelectedGenders(app)
            refreshplot(app)
        end

  加载数据:load(‘文件名’,‘XXX’);

  现将数据赋值给app.Data,再导入table中。

 

  更新数据:updateSelectedGenders(app)
  刷新绘图:refreshplot(app)
% Changes arrangement of the app based on UIFigure width
        function updateAppLayout(app, event)
            currentFigureWidth = app.PatientsDisplayUIFigure.Position(3);
            if(currentFigureWidth <= app.onePanelWidth)
                % Change to a 2x1 grid
                app.GridLayout.RowHeight = {400, 400};
                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 = {282, \'1x\'};
                app.RightPanel.Layout.Row = 1;
                app.RightPanel.Layout.Column = 2;
            end
        end

  根据界面调整布局,之前在学习(二)中已经详细讲解。

  % Value changing function: BinWidthSlider
        function SliderValueChanging(app, event)
            % Update the histogram as the slider value for bindwidth changes.
            app.BinWidth = event.Value;
            for ii=1:length(app.Histogram)
                app.Histogram(ii).NumBins = numhistbins(app,app.Histogram(ii).Data);
            end
        end

  根据滑块的值变动直方图的宽度。

% Callback function: BinWidthSlider, BloodPressureSwitch, 
        % ButtonGroup, UITable
        function refreshplot(app, event)
            Genders = app.SelectedGenders;
            Colors = app.SelectedColors;
            
            % Start with a fresh plot
            cla(app.UIAxes)
            hold(app.UIAxes,\'on\')
            app.Histogram = gobjects(0);
            
            % Select relevant segment of data
            xdata = app.Data.Weight;
            ydata = app.Data.(app.BloodPressureSwitch.Value);
            
            % Filter the data according to the controls
            filterData(app);

  重点内容:

  清空坐标区内的绘图数据:cla(app.UIAxes)

% Create either a scatter plot or histogram, based on selection
            switch app.ButtonGroup.SelectedObject.Text
                
                case \'Scatter\'
                    % Build a scatter plot for each selected gender
                    for ii = 1:length(Genders)
                        selectedpatients = ((app.Data.Gender == Genders(ii)) & (app.displayedIndices));
                        scatter(app.UIAxes,xdata((selectedpatients)),ydata(selectedpatients),Colors{ii});
                    end
                    annotateScatterPlot(app)
                    
                case \'Histogram\'
                    % Build a histogram for each selected gender
                    for ii = 1:length(Genders)
                        selectedpatients = ((app.Data.Gender == Genders(ii)) & (app.displayedIndices));
                        NBins = numhistbins(app,ydata(selectedpatients));
                        h = histogram(app.UIAxes,ydata(selectedpatients),NBins,\'BinLimits\',[floor(min(ydata)) ceil(max(ydata))]);
                        h.EdgeColor = Colors{ii};
                        h.FaceColor = Colors{ii};
                        app.Histogram = [app.Histogram h];
                    end
                    annotateHistogram(app)
                    
            end

  重点:按钮组的程序调用方法:

  采用switch语句,对按钮组进行程序操作

 % Update the table to show only the data that satisfies the controls
            app.UITable.Data = app.Data(app.displayedIndices,:);
            drawnow;
        end

  drawnow; 更新图窗并处理回调

% Value changed function: FemaleCheckBox, 
        % HospitalNameDropDown, MaleCheckBox, NoCheckBox, 
        % YesCheckBox
        function updateSelectedGenders(app, event)
            % List which genders and colors to use
            Genders = [];
            Colors = [];
            Smoker = [];
            
            if app.MaleCheckBox.Value
                Genders = "Male";
                Colors = "blue";
            end
            if app.FemaleCheckBox.Value
                Genders = [Genders "Female"];
                Colors = [Colors "red"];
            end
            if app.YesCheckBox.Value
                Smoker = "Yes";
            end
            if app.NoCheckBox.Value
                Smoker = [Smoker "No"];
            end
            
            if isempty(Genders) || isempty(Smoker)
                % Disable the switches and buttons if they were on
                app.BloodPressureSwitch.Enable = \'off\';
                app.ScatterButton.Enable = \'off\';
                app.HistogramButton.Enable = \'off\';
                app.BinWidthSliderLabel.Enable = \'off\';
                app.BinWidthSlider.Enable = \'off\';
            else
                % Enable the switches and buttons if they were off
                app.BloodPressureSwitch.Enable = \'on\';
                app.ScatterButton.Enable = \'on\';
                app.HistogramButton.Enable = \'on\';
                app.BinWidthSliderLabel.Enable = \'on\';
                app.BinWidthSlider.Enable = \'on\';
            end
            app.SelectedGenders = Genders;
            app.SelectedColors = Colors;
            
            refreshplot(app)
        end
    end

  isempty()函数是判断数组是否为空,如果为空,返回逻辑真,值为1,如果数组不为空,返回逻辑假,值为0,其他内容便比较容易理解了。

  这部分学习的内容包括 下拉框、复选框、按钮组、滑块值、开关、菜单栏、表格、散点图和直方图的绘制等功能。另外对辅助功能如清空绘图区、刷线图窗更新等命令也做了学习。

  但是这部分关于编程思想并没有学习透彻,我们之后会专门提到这个问题。因此,本节内容只要掌握这些控件的程序调用方式即可。

  下一节我们学习其他的控件,我另起文档介绍,继续跟紧我!