Using the matlab app designer, I want to somehow run a function that can modify data within the app without specifically calling it.

I have a complicated program that includes hundreds of sub functions -- all of which are managed through a GUI made using the Matlab APP designer. One of the things I want to do is to call a standard function in my directory ("status.m"), and using this status function, edit properties within the app. However, even if app is in the working space, to edit any properties in the app, I need to call the app ("app.propertyIWantToEdit"). The only solution I know of so far would be to call the app as an input function through every function I have, which would be very inefficient and tedious.
Is there a way I could make a function that, in a sub function, independently calls up the app so it can modify data/change variables, so I don't need to manually call the app in the outer function?

9 Comments

I can't really understand what you are trying to do. Can you please give a simple, concrete, example that illustrates what you are trying to accomplish.
Nor I, but the only way to modify anything will be to have whatever it is to be modified in scope at the time the function is running. Using argument lists is the clean way to do this.
As @Jon says, show us a smaller version of the architecture you have to visualize the problem; you can illustrate with just a couple functions outlined as well as with a hundred...
Looking back my description was very confusing. Sorry about that.
It's proprietary code so I'll make an example of exactly what is happening.
This is an example of what currently exists
function output(a,b)
if a<b
disp("a<b")
end
end
The "output" function is deep within the code, so a random functions will call it if certain things occur.
Now we have a GUI that currently operates a case structure system to display information onto a "label" on the GUI. For many things in the code, the outputs will occur in a nested function on local variables to the app, so using "app" as an input is not a problem.
function libArray = libGenerator(app)
app.x = "a";
app.y = "b";
%And now if we can use our status system
if app.a ~= app.b
status(app,4) %"4" being a predefined status we use in the GUI.
end
end
function status(app,statusVal)
switch statusVal
case 1
statusString = "Case 1";
case 4
statusString = "A not equal to B";
end
app.StatusLabelBox.Text = statusString;
end
Ok, so now that's how both parts work. Currently, most of the systems we use can be done using the function shown just above, using the status function. In essence, you call app as an arugment into the function, and then that function updates the label text.
The problem is, the GUI is being built on top of older code, which utilizes the command line to output much of the data -- part of the goal with the GUI is to move that data away from the command line and into tables that can be saved into files (also happens within the status function).
But the issue is, with the code that is very deep in the older program, the GUI app is no longer included as a function argument.
It is NOT:
function f1(app,a)
function f2(app,b)
function f3(app,c)
end
end
end
But rather
function f1(a)
function f2(b)
function f3(c)
end
end
end
For compatability purposes, we cannot add app as an arugment to the function, but the goal is to call status within the function f3, for example, and have it work without needing to call the app.
I've tried looking at using global variables (global app) and getters and setters, but global app seems very insecure, and getters and setters still require the need to call "app" at one time or another.
Will have to digest this, but certainly a lot clearer now - thanks, won't get back to it though until after the weekend
The same still holds -- unless app is in context during the execution of f3(), then there's simply no way to access any of the application controls; all wishes aside.
The other way besides global that might work (I've not tried it so don't know if can be done or not for sure) would be to place the app struc in a <public property>. That's essentially the same as making it global (if it is allowed to be done).
The slightly cleaner way to do it would be to create another struc that contains the necessary components of app that need to be accessed; the problem there would possibly keeping it updated as requirements change; one might be able to automate that some what with the ability to dynamically add names programmatically; that would all depend upon what it actually is that need access to; I'm not sure if there's a retrievable list of controls/objects in the app that could be parsed or not; never looked.
Why is it not possible to add app as an argument everywhere? It will be very tedious, and you might miss a handful, but simply using the replace tools might get you there.
@Rik, agree wholeheartedly. My first response that I subsequently changed into the current was that OP's organization needs to decide how important the GUI app is and, if is deemed important as a result, then commit the resources to make the necessary modifications.
You can use findall to find handle of the app and do whatever you need. However, you might need to specify something aditionally that you can identify your app with such as Name or Tag.
This will return handle of all opened figures, and will try to get the RunningAppInstance property.
% Get app handle
app = get(findall(groot, 'type', 'figure'), 'RunningAppInstance');
Thank you all for the responses. A few things got in the way meaning I'll be away from this project for a bit but I'll give these all a try and I'll let you know which method I went with. Thanks again!

Sign in to comment.

Answers (1)

function status(varargin)
persistent app
switch nargin
case 1
assert(~isempty(app), 'status must be called with app before it can be called without app');
statusValue = varargin{1};
case 2
app = varargin{1};
statusValue = varargin{2};
otherwise
error('status() must be called with 1 or 2 parameters');
end
switch statusVal
case 1
statusString = "Case 1";
case 4
statusString = "A not equal to B";
end
app.StatusLabelBox.Text = statusString;
end
status() must be called with app provided at least once before it is called without app provided. If called with a single parameter and this is not the first call then it uses the remembered app.
This code relies upon app being a handle class.

Categories

Find more on Develop Apps Using App Designer in Help Center and File Exchange

Products

Release

R2023a

Community Treasure Hunt

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

Start Hunting!