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,其他內容便比較容易理解了。

  這部分學習的內容包括 下拉框、復選框、按鈕組、滑塊值、開關、菜單欄、表格、散點圖和直方圖的繪制等功能。另外對輔助功能如清空繪圖區、刷線圖窗更新等命令也做了學習。

  但是這部分關於編程思想並沒有學習透徹,我們之后會專門提到這個問題。因此,本節內容只要掌握這些控件的程序調用方式即可。

  下一節我們學習其他的控件,我另起文檔介紹,繼續跟緊我!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM