MATLAB 之 APP DESIGNER 学习

沉舟侧畔千帆进,病树前头万木春。这篇文章主要讲述MATLAB 之 APP DESIGNER 学习相关的知识,希望能为你提供帮助。
续学习(一)、学习(二)
三、示例学习 3.响应用户选择 

MATLAB 之 APP DESIGNER 学习

文章图片

有了学习(一)和学习(二)的基础,我直接开门见山,分析其中的核心部分。
(1)界面
相比之前两个的界面,这个界面要高级很多了。首先是整个界面分为两个面板,左面板和右面板。
左面板部分从上到下依次是控件:
标签Data Selection
三个小面板,第一个面板上的title  为location,放着下拉框; 
第二个面板的title是Gender,放着两个复选框Male  和  female;
第三个面板的title是smoker,放着两个复选框yes和no
MATLAB 之 APP DESIGNER 学习

文章图片

右面板部分上方有图窗工具菜单栏,在第一个子项plot中,从上到下依次是
仪器工具中的开关
绘图区
button组
滑块
菜单第二个子项data中,放的是

如下图。
MATLAB 之 APP DESIGNER 学习

文章图片

对控件进行相应的命名、属性的修改。
(2)代码
先把源代码贴过来,代码分析见后。
classdef PatientsDisplay < matlab.apps.AppBase% Properties that correspond to app components properties (Access = public) PatientsDisplayUIFigurematlab.ui.Figure GridLayoutmatlab.ui.container.GridLayout LeftPanelmatlab.ui.container.Panel Panel2matlab.ui.container.Panel FemaleCheckBoxmatlab.ui.control.CheckBox MaleCheckBoxmatlab.ui.control.CheckBox Panel2_2matlab.ui.container.Panel NoCheckBoxmatlab.ui.control.CheckBox YesCheckBoxmatlab.ui.control.CheckBox Panel2_4matlab.ui.container.Panel HospitalNameDropDownLabelmatlab.ui.control.Label HospitalNameDropDownmatlab.ui.control.DropDown DataSelectionLabelmatlab.ui.control.Label RightPanelmatlab.ui.container.Panel TabGroupmatlab.ui.container.TabGroup PlotTabmatlab.ui.container.Tab UIAxesmatlab.ui.control.UIAxes BinWidthSliderLabelmatlab.ui.control.Label BinWidthSlidermatlab.ui.control.Slider ButtonGroupmatlab.ui.container.ButtonGroup ScatterButtonmatlab.ui.control.RadioButton HistogramButtonmatlab.ui.control.RadioButton BloodPressureSwitchLabelmatlab.ui.control.Label BloodPressureSwitchmatlab.ui.control.Switch DataTabmatlab.ui.container.Tab UITablematlab.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 endmethods (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); endfunction 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\'; endfunction 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\'; endfunction 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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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.Textcase /'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 = https://www.songbingjia.com/android/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"]; endif 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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/'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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/'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是直方图每一个条形的宽度。
【MATLAB 之 APP DESIGNER 学习】  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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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.Textcase \'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 = https://www.songbingjia.com/android/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"]; endif 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,其他内容便比较容易理解了。
这部分学习的内容包括  下拉框、复选框、按钮组、滑块值、开关、菜单栏、表格、散点图和直方图的绘制等功能。另外对辅助功能如清空绘图区、刷线图窗更新等命令也做了学习。
但是这部分关于编程思想并没有学习透彻,我们之后会专门提到这个问题。因此,本节内容只要掌握这些控件的程序调用方式即可。
下一节我们学习其他的控件,我另起文档介绍,继续跟紧我!

    推荐阅读