GUI element update strategies in App Designer

24 visualizzazioni (ultimi 30 giorni)
Pieter
Pieter il 6 Ott 2021
Risposto: Reshma Nerella il 3 Feb 2022
Hi all,
Long term Matlab user here but building my first GUI apps with App Designer.
I am struggling with the strategy to update the UIcontrols.
In the tutorial examples, UIcontrols are updated whenever and wherever needed. However, these are very simple examples.
In my GUI, I have UIcontrols which interact closely, eg disabling/enabling elements in case of valid/invalid input of another UIcontrol, updating the value, updating a statusbar, etc which is more complex than the basic examples.
If I would do the UIcontrol updates as in these examples (mostly within the callbacks), a lot of code would be repeated and I would loose oversight and ease of maintenance.
So what I do now is whenever I need an update of the UIcontrols:
  1. Set a boolean for each UIcontrol (eg app.StatusCode = true) which might need an update after running the callback
  2. Call a function app.updateUIcontrols() at the end of the running function
function EditFieldCalculateValueChangedFcn(app, event)
val = event.Value;
if val > 0
app.StatusCodeValue = 'Good';
else
app.StatusCodeValue = 'Bad';
end
app.StatusCode = true;
% set boolean value of other UIcontrols to update
app.updateUIcontrols();
end
The function updateUIcontrols() checks all UIcontrols and performs an update if needed.
function updateUIcontrols(app)
...
if app.StatusCode = true
app.EditFieldStatusCode.Value = app.StatusCodeValue;
app.StatusCode = false;
end
...
end
This has also some drawbacks
  1. A lot of extra variables are needed (a boolean and eventually a value variable for each UIcontrol)
  2. A lot of unnecessary checking (if I have 50 UIcontrols and only need 1 to be update, it will still check the others too)
  3. The UIcontrols are updated sequentially so I must make sure that an update of one UIcontrol does not influence the state of an UIcontrol checked earlier
  4. The UIcontrols are only updated at discrete timepoints, not necessarily immediately
  5. Fill in yourself ;-)
Are there any strategies to tackle this problem?
Are there examples of good GUI coding practices in Matlab?

Risposte (2)

Mario Malic
Mario Malic il 12 Ott 2021
Modificato: Mario Malic il 19 Ott 2021
Hey Pieter,
I did recently, something similar. You can create and use the same callback for multiple components. If you can group up your components that interact with each other either by some logic it would make it easier. Let's say you have multiple different components that operate (and interact with each other) in one tab, then the same group of components in the other tab etc. - this could be good example of grouping up.
Then, you would "collect" this group of components in array for graphic objects gobjects, and assign the same callback to each component. So, once you enter into callback, you first identify which object has fired the event and according to it, execute some code.
This code would be an idea of what I meant. I hope it's clear enough, even though I am afraid it may not be.
properties(Access = public)
groupObjs = gobjects(10, 1); % assign objects to array
groupBool = false(10,1);
end
% some callback gets executed
function callback(source, event)
objIdx = find(source == app.groupObjs); % get index in the groupObjs, isequal might also work
app.groupBool(objIdx) = true;
% call a function that updates component based on groupBool property
updatesomedata
end
Edit 1: I have made an example, so you can check the idea. I do not know whether this is the best way to do things, I am up for some brainstorming.
Read first the interactions on the GUI, then see how things are implemented. In the code, there is some text regarding the boolean array and function that only updates particular components.
This example would be useful if we would have multiple tabs with same/similar components. Apologies if I haven't made myself clear (which, unfortunately, might be true).
  6 Commenti
Pieter
Pieter il 21 Ott 2021
Hi Mario,
Thanks for the demo!
I used a similar approach by using boolean values for each component and check these in an updateUIcontrols function. But instead of using an array for updateCompsBool I use a struct with each fieldname the same name as a component and the value a boolean.
The advantage is that it is very easy to visually read which components are need to be updated in a function. The drawback is that it can take some extra lines of code when a lot of components need an update
Just to be curious, but could you elaborate on the drawbacks of this technique?
  • A lot of extra variables are needed (a boolean and eventually a value variable for each UIcontrol)
This is partially solved by using an array containing the update status of the components
  • A lot of unnecessary checking (if I have 50 UIcontrols and only need 1 to be update, it will still check the others too)
  • The UIcontrols are updated sequentially so I must make sure that an update of one UIcontrol does not influence the state of an UIcontrol checked earlier
  • The UIcontrols are only updated at discrete timepoints, not necessarily immediately so updateUIControls should be called often
Mario Malic
Mario Malic il 21 Ott 2021
  • The drawback is that it can take some extra lines of code when a lot of components need an update. What do you mean by this? Does it mean that for each component you have property such as app.StatusCode so it makes code lengthy?
  • The UIcontrols are only updated at discrete timepoints, not necessarily immediately so updateUIControls should be called often. For this you could maybe create a "update queue", once the UI is set to update, update only components in the queue, don't check any others. This solves last three bullets I think. Unless, some components need updating randomly.
In your struct you have already field that contains information if the particular component requires an update. In the callback as you've done already, set the corresponding bool field to true. Once it is time to update things, loop over the structure to find out which components need updating and do so. Once done, set bool to false.
This is an example for your struct with the fieldnames of components. Alternatively, you can put components themselves into cell array (need to verify this) and identify their row number using the event.Source.
% If your struct is named compstruct with fields named after each component
% and inside of each field there is updateBool field
fName = fieldname(compstruct);
updCell = cell(numel(fName), 2);
for ii = 1 : numel(fName)
updCell{ii, 1} = fName{ii};
updCell{ii, 2} = compstruct.(fNames).updateBool;
end
Please share more details about the app, like, what do you mean with UIControls, which components? How the particular value is changed etc.?

Accedi per commentare.


Reshma Nerella
Reshma Nerella il 3 Feb 2022
Hi,
Instead of having many unnecessary boolean variables or many callbacks with similar code, you can add a single callback to multiple app designer components.

Categorie

Scopri di più su Migrate GUIDE Apps in Help Center e File Exchange

Prodotti


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by