How to print text message in UI App in Matlab - matlab

I am working on a App in MATLAB and I use the app design to build it. I have added a text area element in which I display messages to the user (similar use as the command window). In the the app the user can press buttons, which trigger functions to be executed and within those functions, I would like to be able to display some messages in this text area element.
This is an example of the code I use to display the text in this text area. I use a counter to add text in the list and simulate display without overwriting the previous messages.
% display execution message
app.nb_Text_stock = app.nb_Text_stock + 1;
app.OutputStatusTextArea.Value(app.nb_Text_stock) = {'My test here'};
As you can see, I need the app element. I could then pass it to the function all the way to the level where I need to display the text but my real question is, can I access the app element from within the function without passing it as an argument? The reason I want to do that is I have also a non-GUI version of the script where I would not be able to pass app as argument. So to make things simpler, I would like to have a parameters GUI = 1 or 0, and then based on that display either in the command window if GUI = 0 or in the text area in the GUI if GUI = 1. But for that I need to access the app element from inside my function. Is there a proper way to do that? Or do you have any suggestion for another approach for this problem?

You can store app object using setappdata, and get the object using getappdata:
Store app in startupFcn function (Code that executes after component creation):
Add startupFcn by adding callback in "Code View".
% Code that executes after component creation
function startupFcn(app)
% Store app in the root object (setappdata(groot, 'my_app', app) also works).
setappdata(0, 'my_app', app)
end
Read app object from any function:
app = getappdata(0, 'my_app');
Note:
This is not a good coding practice.
What you supposed to do:
function NonGuiFun()
app = app1();
app.func();
What you are asking to do:
function NonGuiFun()
% Get app object (assuming `app` GUI is already open)
app = getappdata(0, 'my_app');
if ~isempty(app)
app.func();
end
Here is the entire code of app1 class, that I used for testing (most of it is automatically generated):
classdef app1 < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
Button matlab.ui.control.StateButton
TextAreaLabel matlab.ui.control.Label
OutputStatusTextArea matlab.ui.control.TextArea
end
properties (Access = private)
nb_Text_stock = 0; % Description
end
methods (Access = public)
function results = func(app)
app.nb_Text_stock = app.nb_Text_stock + 1;
app.OutputStatusTextArea.Value(app.nb_Text_stock) = {num2str(app.nb_Text_stock)};
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
setappdata(0, 'my_app', app)
end
% Value changed function: Button
function ButtonValueChanged(app, event)
value = app.Button.Value;
func(app);
end
% Close request function: UIFigure
function UIFigureCloseRequest(app, event)
setappdata(0, 'my_app', [])
delete(app)
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 640 480];
app.UIFigure.Name = 'UI Figure';
app.UIFigure.CloseRequestFcn = createCallbackFcn(app, #UIFigureCloseRequest, true);
% Create Button
app.Button = uibutton(app.UIFigure, 'state');
app.Button.ValueChangedFcn = createCallbackFcn(app, #ButtonValueChanged, true);
app.Button.Text = 'Button';
app.Button.Position = [214 295 214 85];
% Create TextAreaLabel
app.TextAreaLabel = uilabel(app.UIFigure);
app.TextAreaLabel.HorizontalAlignment = 'right';
app.TextAreaLabel.Position = [210 211 56 22];
app.TextAreaLabel.Text = 'Text Area';
% Create OutputStatusTextArea
app.OutputStatusTextArea = uitextarea(app.UIFigure);
app.OutputStatusTextArea.Position = [281 175 150 60];
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = app1
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% 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.UIFigure)
end
end
end
Note that UIFigureCloseRequest executes: setappdata(0, 'my_app', []).

If you have the handle of any graphical object, you can find pretty much any other object in the same figure using the .Parent and .Children fields (e.g. hObject.Parent.Parent.Children(3).String = 'foo'), optionally using ancestor. If you don't have any object handles, you can use findall, but this would require some means of identifying the correct figures/controls. This can be done using their Tag field, but it would require specifying it beforehand.

Related

Set limits for values in the cells of an uitable

I am creating a GUI using Matlab's App Designer (2019b). One of the nice features for NumericEditField is that you can define value limits so that users can't enter a value outside the desired range. For example, the following would limit the edit field values between -100 and 100.
app.numericEditField1.Limits = [-100 100];
I also have a uitable object in my GUI - is it possible to set value limits for cells in the data table, like with the edit fields? I didn't see a property that was obviously equivalent. My best thought for a workaround is to edit the CellEditCallback to manually check the values every time one is changed.
Below is a sample app that has a value edit field with limits, and a regular uitable. I would like the to put value limits on certain columns of the table as well.
Sample code
classdef sampleLimitedValApp < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
LimitedEditValueEditFieldLabel matlab.ui.control.Label
LimitedEditValueEditField matlab.ui.control.NumericEditField
UITable matlab.ui.control.Table
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
app.UITable.Data = zeros(3,4);
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 383 331];
app.UIFigure.Name = 'UI Figure';
% Create LimitedEditValueEditFieldLabel
app.LimitedEditValueEditFieldLabel = uilabel(app.UIFigure);
app.LimitedEditValueEditFieldLabel.HorizontalAlignment = 'right';
app.LimitedEditValueEditFieldLabel.Position = [31 280 101 22];
app.LimitedEditValueEditFieldLabel.Text = 'Limited Edit Value';
% Create LimitedEditValueEditField
app.LimitedEditValueEditField = uieditfield(app.UIFigure, 'numeric');
app.LimitedEditValueEditField.Limits = [-100 100];
app.LimitedEditValueEditField.Position = [147 280 100 22];
% Create UITable
app.UITable = uitable(app.UIFigure);
app.UITable.ColumnName = {'Column 1'; 'Column 2'; 'Column 3'; 'Column 4'};
app.UITable.RowName = {''};
app.UITable.ColumnEditable = true;
app.UITable.Position = [31 67 302 185];
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = sampleLimitedValApp
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% 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.UIFigure)
end
end
end
Your idea of using the CellEditCallback was the right one. I have to admit, that I am not really an expert in creating and using classes in Matlab and always create my GUIs from scratch without using the AppDesigner, thats why I don't know if there is maybe a better organization of functions and methods possible.
However, the following does what you want:
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% original code
% added code
app.UITable.CellEditCallback = #limitCellVal;
function limitCellVal(src,evt)
CellLimits = [-100 100];
idx = evt.Indices; % indices of selected cell
belowLowerLimit = src.Data(idx(1),idx(2)) < CellLimits(1);
aboveUpperLimit = src.Data(idx(1),idx(2)) > CellLimits(2);
if belowLowerLimit, src.Data(idx(1),idx(2)) = CellLimits(1); end
if aboveUpperLimit, src.Data(idx(1),idx(2)) = CellLimits(2); end
end
end
end
If you want to edit multiple cells at once, than a little tweaking of the callback function is necessary, but I think you can manage that.

How to display a matlab table in a Matlab App?

I am building an app where the user can select some parameters and press a button "update", which trigger a table to be create. Let's say a table named A.
Now I would like to display this table in a excel like window on my app so the user can see the results of the data update. I can not find which element and how to set it up so that my table A is display in my app in a excel like window where the user could scroll up and down, left and right.
Is that something possible to do and if yes how?
I actually have found a satisfactory answer, which builds on the answer of Rotem above:
In the button pushed callback, simply add:
% Button pushed function: UpdateButton
function UpdateButtonPushed(app, event)
app.UITable.Data = app.T;
app.UITable.ColumnName = app.T.Properties.VariableNames;
end
This works fine for multiple data type. (i actually did not display the rowName property as I do not have any in this case).
You can use the table component.
My example is based on the following example, which displays MATLAB table in a uitable (user interface table component).
You can start by adding a table to the application main figure in App Designer design view.
You can also add the update button in design view.
Add a private property to the app class for storing the table data (I named it T):
properties (Access = private)
T % Table
end
You may initialize table T in the startupFcn like in the following example:
% Code that executes after component creation
function startupFcn(app)
LastName = {'Smith'; 'Johnson'; 'Williams'; 'Jones'; 'Brown'};
Age = [38; 43; 38; 40; 49];
Height = [71; 69; 64; 67; 64];
Weight = [176; 163; 131; 133; 119];
app.T = table(Age, Height, Weight, 'RowNames', LastName);
end
In the button pushed callback, you can update the table like in the following example:
% Button pushed function: UpdateButton
function UpdateButtonPushed(app, event)
app.UITable.Data = app.T{:,:};
app.UITable.ColumnName = app.T.Properties.VariableNames;
app.UITable.RowName = app.T.Properties.RowNames;
end
Here is how the user interface looks like (after pressing update button):
Here is the complete code (include automatically generated code):
classdef app1 < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
UITable matlab.ui.control.Table
UpdateButton matlab.ui.control.Button
end
properties (Access = public)
children = app1.empty % Description
end
properties (Access = private)
T % Table
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
LastName = {'Smith'; 'Johnson'; 'Williams'; 'Jones'; 'Brown'};
Age = [38; 43; 38; 40; 49];
Height = [71; 69; 64; 67; 64];
Weight = [176; 163; 131; 133; 119];
app.T = table(Age, Height, Weight, 'RowNames', LastName);
end
% Button pushed function: UpdateButton
function UpdateButtonPushed(app, event)
app.UITable.Data = app.T{:,:};
app.UITable.ColumnName = app.T.Properties.VariableNames;
app.UITable.RowName = app.T.Properties.RowNames;
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 322 233];
app.UIFigure.Name = 'UI Figure';
% Create UITable
app.UITable = uitable(app.UIFigure);
app.UITable.ColumnName = {'Column 1'; 'Column 2'; 'Column 3'; 'Column 4'};
app.UITable.RowName = {};
app.UITable.Position = [36 57 251 163];
% Create UpdateButton
app.UpdateButton = uibutton(app.UIFigure, 'push');
app.UpdateButton.ButtonPushedFcn = createCallbackFcn(app, #UpdateButtonPushed, true);
app.UpdateButton.Position = [36 14 100 22];
app.UpdateButton.Text = 'Update';
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = app1
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% 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.UIFigure)
end
end
end
You can copy an paste the code to app1.m file, just to see how it works (without using App Designer).

Operating on while loop outside the loop matlab

i've got problems with my Nucleo.
Im using Matlab to cooperate with my Nucleo board.
I want to build programmatically GUI with buttons, figures etc. I'm going to put whole functionality in while loop. And now there's my question.
Is there any posibility to put whole code in while loop and operate it through callback functions outside the loop?
For example: Im my loop i want to send some data to Nucleo on btn1 press, and i want to stop it on btn2 press(Of course if statements for btns). Is there possibility to do it by changing the button values or something like that(Flags etc.)?
I don't want use global variables.
Yes it's possible...
It's not the best programming pattern, but it's very convenient approach for small software projects.
I recommend you to use MATLAB App Designer.
App Designer uses OOP programming model, that makes it simpler to pass data (without using global variables, and without complicated solutions that are used with GUIDE).
Here is a sample instructions:
Start App Designer - execute appdesigner from command line.
Add two buttons, and two labels (add anything else later).
Add callbacks: for start button set flag to true and in stop button to false.
The syntax is app.is_sending = true (when is_sending is a property of app).
Change from Design View to Code View.
Add private properties: loop_counter = 0;, sending_counter = 0;, is_sending = false;.
Add callback - select startupFcn callback function.
Put your while loop in the startupFcn callback.
Use while isvalid(app)
Place your while loop functionality inside the while loop.
Place your sending code with if (app.is_sending)...
Very important: at the end of the loop call pause function.
You must execute pause or drawnow to allow callbacks to be responsive.
When using App Designer, some code is generated automatically, and cannot be modified in Code View.
The following code sample includes both generated code, and customized code:
classdef app1 < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
StartSendingButton matlab.ui.control.Button
StopSendingButton matlab.ui.control.Button
Sending0Label matlab.ui.control.Label
LoopCounter0Label matlab.ui.control.Label
end
properties (Access = private)
loop_counter = 0 % Count while loop iteration
sending_counter = 0; %Count only while "sending data"
is_sending = false; %Flag: if value is true, assume "sending"
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
%While loop: loop until app is not valid.
while isvalid(app)
%Place your while loop functionality here:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
app.loop_counter = app.loop_counter + 1; %Increase loop counter
app.LoopCounter0Label.Text = ['Loop Counter: ', num2str(app.loop_counter)]; %Update loop coouner text lable.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Place your sending code here:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (app.is_sending)
app.sending_counter = app.sending_counter + 1; %Increase sending counter
app.Sending0Label.Text = ['Sending: ', num2str(app.sending_counter)]; %Update sending coouner text lable.
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% Important %%%%
%Short pause must be used in order to allow buttons callbacks to be responsive (you can also call drawnow).
pause(0.01)
%%%% Important %%%%
end
end
% Button pushed function: StartSendingButton
function StartSendingButtonPushed(app, event)
app.is_sending = true; %Set flag to true when button is pressed.
end
% Button pushed function: StopSendingButton
function StopSendingButtonPushed(app, event)
app.is_sending = false; %Set flag to false when button is pressed.
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 440 304];
app.UIFigure.Name = 'UI Figure';
% Create StartSendingButton
app.StartSendingButton = uibutton(app.UIFigure, 'push');
app.StartSendingButton.ButtonPushedFcn = createCallbackFcn(app, #StartSendingButtonPushed, true);
app.StartSendingButton.BackgroundColor = [0.3922 0.8314 0.0745];
app.StartSendingButton.FontSize = 16;
app.StartSendingButton.Position = [33 197 130 49];
app.StartSendingButton.Text = 'Start Sending';
% Create StopSendingButton
app.StopSendingButton = uibutton(app.UIFigure, 'push');
app.StopSendingButton.ButtonPushedFcn = createCallbackFcn(app, #StopSendingButtonPushed, true);
app.StopSendingButton.BackgroundColor = [0.851 0.3255 0.098];
app.StopSendingButton.FontSize = 16;
app.StopSendingButton.Position = [33 129 130 49];
app.StopSendingButton.Text = 'Stop Sending';
% Create Sending0Label
app.Sending0Label = uilabel(app.UIFigure);
app.Sending0Label.FontSize = 16;
app.Sending0Label.Position = [229 203 151 37];
app.Sending0Label.Text = 'Sending: 0';
% Create LoopCounter0Label
app.LoopCounter0Label = uilabel(app.UIFigure);
app.LoopCounter0Label.FontSize = 16;
app.LoopCounter0Label.Position = [37 44 193 37];
app.LoopCounter0Label.Text = 'Loop Counter: 0';
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = app1
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% 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.UIFigure)
end
end
end
You can copy and paste the entire code into an m file, to see how it works.
The code sample is not sending any data (and not related to Nucleo board), it's just advancing counters.
Here is how the sample application interface looks like:

Right-align values in UITable in App Designer

I already asked about this on Matlab Answers but did not get a response there, so I try it here.
I have some numbers I want to show in a UITable. Since I need a specific formatting of the values (three digits after comma, no scientific notation), I converted the values to strings. The problem is that these strings are by default left-aligned which looks not very nice.
When using UITable in GUIDE, I was able to pad strings with leading spaces to get them right aligned like in the following
data = {'1532.000'; ' 5.543'; ' 26.457'};
Using a mono space font, the values are shown like this in the table:
1532.000
5.543
26.457
Currently I am considering switching to App Designer. I am using the same space-padded strings but here the uitable seems to strip them off. That is the result looks like the following:
1532.000
5.543
26.457
Is there a way to make uitable in App Designer keep the spaces like it did in GUIDE?
Of course it would be even better to directly right-align the strings without the need of padding, but as far as I know this is not possible.
In case it matters: I am using Matlab R2016b.
Edit:
Minimal example for generating and filling a UITable. This is a simple AppDesigner GUI where I added only a table and a button (without modifying any attributes). The click callback of the button is used to add the data to the table.
classdef test < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
UITable matlab.ui.control.Table
Button matlab.ui.control.Button
end
methods (Access = private)
% Button pushed function: Button
function ButtonPushed(app, event)
data = {'1532.000'; ' 5.543'; ' 26.457'};
app.UITable.Data = data;
end
end
% App initialization and construction
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure
app.UIFigure = uifigure;
app.UIFigure.Position = [100 100 640 480];
app.UIFigure.Name = 'UI Figure';
setAutoResize(app, app.UIFigure, true)
% Create UITable
app.UITable = uitable(app.UIFigure);
app.UITable.ColumnName = {'Column 1'; 'Column 2'; 'Column 3'; 'Column 4'};
app.UITable.RowName = {};
app.UITable.Position = [127 180 302 185];
% Create Button
app.Button = uibutton(app.UIFigure, 'push');
app.Button.ButtonPushedFcn = createCallbackFcn(app, #ButtonPushed, true);
app.Button.Position = [220 104 100 22];
end
end
methods (Access = public)
% Construct app
function app = test()
% Create and configure components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
if nargout == 0
clear app
end
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure)
end
end
end
After pushing the button the table looks as follows:
Note that AppDesigner only allows me to modify the code inside the ButtonPushed function.
After investigating this for a while, I found that the reason for the "special" behavior when it comes to a uitable is because it's actually a Java object! (I have no idea how they managed to pull this off or why). In any case, right-aligning the data can be done by inserting one line to your script:
data = {'1532.000'; ' 5.543'; ' 26.457'};
app.UITable.Data = data;
setColumnFormat(java(app.UITable),{'numeric'}); % < Add this
if there's more than one column that you would like to right-align this way, simply replicate {'numeric'} as many times as needed:
setColumnFormat(java(app.UITable), repmat( {'numeric'}, 1, size(data,2) ) );
There's also a slightly shorter notation possible for the styling commands above (thanks #luator for pointing this out):
app.UITable.ColumnFormat = {'numeric'};
app.UITable.ColumnFormat = repmat( {'numeric'}, 1, size(data,2) );
The result:
If I understood Yair's blog correctly, you can find more information about the customization of these table objects by looking for "JIDE Table", or SortableTable.

How to customize App Designer figures in more ways than officially documented?

A recently published article in UndocumentedMatlab, mentions that App Designer figures are actually web pages using the Dojo Toolkit. This means we could theoretically manipulate the HTML DOM directly to achieve certain UI customizations that are otherwise unavailable.
Below is an example of an App Designer figure definition, as appears in the .m file generated by the App Designer (on MATLAB R2016a):
classdef domDemo < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure % UI Figure
LabelListBox matlab.ui.control.Label % List Box
ListBox matlab.ui.control.ListBox % Item 1, Item 2, Item 3, It...
end
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
end
end
% App initialization and construction
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure
app.UIFigure = uifigure;
app.UIFigure.Position = [100 100 260 147];
app.UIFigure.Name = 'UI Figure';
setAutoResize(app, app.UIFigure, true)
% Create LabelListBox
app.LabelListBox = uilabel(app.UIFigure);
app.LabelListBox.HorizontalAlignment = 'right';
app.LabelListBox.Position = [50 93 44 15];
app.LabelListBox.Text = 'List Box';
% Create ListBox
app.ListBox = uilistbox(app.UIFigure);
app.ListBox.Position = [109 36 100 74];
end
end
methods (Access = public)
% Construct app
function app = domDemo()
% Create and configure components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% 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.UIFigure)
end
end
end
...which looks like this:
According to the documentation of uilistbox (which redirects us to the page on Check Box Properties for the full property list), there exists no way to manipulate e.g. the text alignment of list items. If so,
Question: How do we manipulate the ListBox in the example app such that its contents become center-aligned, even though such a setting is not available to us?
In order to succeed in this task, we need several things:
Find where the HTML/CSS are located (so we can manipulate them).
Find which element of the DOM we want to edit.
Find what is the change we need to make.
Find a way to manipulate the element using MATLAB.
Working step by step:
1. Find where the figure's HTML/CSS are stored/located
win = struct(struct(struct(app).UIFigure).Controller).Container.CEF;
URL = win.URL; % Needed only for testing in browser
2. Find which element of the DOM we need to edit
data_tag = char(struct(app.ListBox).Controller.ProxyView.PeerNode.getId);
Validation using a browser:
3. Find what is the change we need to make
Since we want to manipulate text alignment, we google some relevant keywords and find the CSS text-align property. Then we try it manually to see if it really works:
4. Find a way to manipulate the element using MATLAB
Using dojo.style and dojo.query:
win.executeJS(['dojo.style(dojo.query("[data-tag^=''' data_tag ''']")[0],"textAlign","center")']);
Complete code for this answer:
classdef domDemo < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure % UI Figure
LabelListBox matlab.ui.control.Label % List Box
ListBox matlab.ui.control.ListBox % Item 1, Item 2, Item 3, It...
end
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
% Customizations (aka "MAGIC GOES HERE"):
drawnow; rez = [];
warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame
warning off MATLAB:structOnObject
while ~strcmp(rez,'"center"')
try
% 1. Get a handle to the webwindow:
win = struct(struct(struct(app).UIFigure).Controller).Container.CEF;
% 2. Find which element of the DOM we want to edit (as before):
data_tag = char(struct(app.ListBox).Controller.ProxyView.PeerNode.getId);
% 3. Manipulate the DOM via a JS command
rez = win.executeJS(['dojo.style(dojo.query("[data-tag^=''' ...
data_tag ''']")[0],"textAlign","center")']);
catch
pause(1); % Give the figure (webpage) some more time to load
end
end
end
end
% App initialization and construction
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure
app.UIFigure = uifigure;
app.UIFigure.Position = [100 100 260 147];
app.UIFigure.Name = 'UI Figure';
setAutoResize(app, app.UIFigure, true)
% Create LabelListBox
app.LabelListBox = uilabel(app.UIFigure);
app.LabelListBox.HorizontalAlignment = 'right';
app.LabelListBox.Position = [50 93 44 15];
app.LabelListBox.Text = 'List Box';
% Create ListBox
app.ListBox = uilistbox(app.UIFigure);
app.ListBox.Position = [109 36 100 74];
end
end
methods (Access = public)
% Construct app
function app = domDemo()
% Create and configure components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% 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.UIFigure)
end
end
end