Error in callback function execution in App Designer when called programmatically

I am in the process of writing a code for an app in App Designer (rather re-writting an old code to bypass the javaframe issue). As I cannot find any drag and drop option for toobar in App Designer, I have added it programmatically using uitoolbar and added togglebuttons in the toolbar. Now I want to have an access of the properties of the app inside the callback function of the togglebutton. I have used {@myfunction, app} to pass the variable. I can print app from inside the function (to check the effectiveness, I have kept only app and return inside), but at the same time getting this error:
Unrecognized function or variable 'app'.
Error while evaluating Surface ButtonDownFcn.
Any help in this regard will be appreciated.

 Réponse acceptée

Adam Danz
Adam Danz le 28 Juil 2020
Modifié(e) : Adam Danz le 3 Août 2020
As of r2020a, the typical ToolBar is not (yet?) supported for UIFigures (eg, apps) but the property exists which usually means that support is coming soon.
This is how you would turn on the toolbar for UIFigures from your StartupFcn, if/when it becomes supported.
app.UIFigure.ToolBar = 'Figure'; % or 'auto'
% This will result in an error in the current release, r2020a.
So you're stuck with your current method for now. Alternatively, consider using a uimenu.
Set up the tool bar from with your StartupFcn function [how to add a startupFcn].
The first input to your startupFcn is the app variable which can be passed to your toobar callback functions.
% Example
function startupFcn(app)
tb = uitoolbar(app.UIFigure);
pt = uipushtool(tb);
pt.ClickedCallback = {@myfunc,app};
end
Then set up the callback function. In r2020a, an error occurs when the callback function is defined within app designer code, even if the callback function is public. So, the callback function must be defined in an external m-file until this problem is fixed. Update: Alternatively, seeSreerup Banerjee's comment below describing how the callback function can be hosted by the app.
function myfunc(scr, event, app)
% do stuff
end

17 commentaires

Hi Adam! Thanks for the reply.
It is good to know that the ToolBar feature will be added in App Designer in near future.
I have followed the steps to create the toolbar in startupfcn and added a local private file named myfcn. But I am encountering the follwing error:
Undefined function 'myfcn' for input arguments of type 'matlab.ui.container.toolbar.PushTool'.
May be I am missing something? Kindly let me know.
Mind sharing the relevant sections of your code? It sounds like your inputs are different than mine.
Also, "myfcn" is OK for quickly developing the code but you probably want to change that name to something more descriptive.
Yes, I completely agree that a more meaningful name than 'myfcn' should be used. Acutually, I have tried it in the main code, which is big with many functions. So, to pinpoint the error, I applied it in a test code which barely contains any other stuff than the callback. myfcn is the callback used in the test code. I have uploaded the relevant .mlapp file for the test code. Thanks!
The simplified app is helpful.
For whatever reason, toolbar callback functions result in an error when the callback function is defined within app designer code. I tried setting the callback function to public and it still didn't work. I also set the app's figure handle to visible in case that was the problem but that didn't work either. If you move the callback function to an external m-file, it will work in r2020a.
Also, the callback function has two mandatory inputs so the 'app' input must be the third input.
% from the app's startupFcn
pt.ClickedCallback= {@myfun,app};
% from an external m-file
function myfun(scr, event, app)
% do stuff
end
I'll update my answer to relfect these changes.
It would be cleaner and it's fully supported by AppDesigner.
Thanks for the reply.
The initial error:
Unrecognized function or variable 'app'.
Error while evaluating Surface ButtonDownFcn.
appreared when I have used the callback function in an external .m file for my app. But, it worked in a simplified test app and there was no error. I have used three inputs (source,event,app), rather added the app input to already used callback for older code.
Using local function, I have tested it making the function both private and public, and as you have experienced, it did not work.
It seems that as of now I have to shift those functions in menu, even though toolbar function was more convenient for me.
I didn't understand this part
I have used three inputs (source,event,app), rather added the app input to already used callback for older code.
Could you copy-paste the entire callback function and the single line that assigns the callback function in the StartupFcn?
I meant that basically I was re-writting older codes to dodge the javaframe issue and some other back-dated functions. In older code, the callback function (say, myfcn) already started with the line 'function myfcn(source,event)'. When I have used as callback in the App Designer as an external .m file, I have added the input app to the already existing fucntion to make it 'function myfcn(source,event,app)'.
There are several callback functions assigned to different pushbuttons and togglebuttons in the code. I am adding one of them that is used in the App Designer. This one flips x and y axis of an image loaded in the axis.
The callback function:
function flip_axis(app)
% Whichever image is diplayed in main display window, it will be flipped.
if strcmp(get(app.hdl.flipx,'state'),'off')
set(app.UIMainAxis,'xdir','normal');
else
set(app.UIMainAxis,'xdir','reverse');
end
if strcmp(get(app.hdl.flipy,'state'),'off')
set(app.UIMainAxis,'ydir','normal');
else
set(app.UIMainAxis,'ydir','reverse');
end
view(app.UIMainAxis,app.tmp.axis_angle,90);
The relevant portion in StartupFcn:
app.hdl.toolbar=uitoolbar(app.MediScopeUIFigure);
app.hdl.flipx=uitoggletool('Parent',app.hdl.toolbar,'CData',d, 'ClickedCallback',{@flip_axis,app},'Tooltip','Flip x-axis','Enable','on');
You're missing the first two manadory inputs to the callback function. When the callback function in invoked, those first two inputs are generated internally. All additional inputs must come after the first two.
function flip_axis(scr, event, app)
After making that change, explore those first two inputs to see what they have to offer. You may not need to use them but they must be included.
If you find that you don't need to use them, you could replace them with
function flip_axis(~, ~, app)
I have used the syntax "function flip_axis(app)" when I have used it inside App Designer as local function. When I have used it as an external .m file I have used the syntax "function flip_axis(~, ~, app)".
I see. I just re-read the previous comment you left and saw that you did mention that. But the single input syntax wouldn't work anyway since the first input to the callback function isn't the app handle. With that syntax, you're just using the variable name "app" to describe the first input. Additionally, the callback function would expect 3 inputs since you've inluded the app handle in the callback definition.
Yes. I get your point.
But if I use local funtion (private or public) as callback for the buttons in the toolbar, the effect of the change in syntax ((app) vs (~,~,app) vs (app,~)) is not apparent, as the function itself is not recognized. It's just showing an error:
Undefined function 'myfcn' for input arguments of type 'matlab.ui.container.toolbar.PushTool'.
Error using matlab.ui.internal.controller.WebPushToolController/fireActionEvent (line 116)
Error while evaluating PushTool ClickedCallback.
"But if I use local funtion (private or public) as callback for the buttons in the toolbar, the effect of the change in syntax ((app) vs (~,~,app) vs (app,~)) is not apparent, as the function itself is not recognized. It's just showing an error:"
Right. If/when the toolbar callback functions are supported in app designer, you'll use the same syntax as the one you've defined in the external m-file: myfunc(scr, event, app)
If you decide to use a UI Menu, the private callback function will look like,
function menuSelected(app, event)
% do stuff
end
That function will be automatically added when you add the callback within app designer.
Yes. For the time being, using uimenu (or drag-and-drop menubar) is the best alternative.
I have found out this discussion to find solution to another problem (link provided below). It gave a hint about how to solve this particulat issue. I have tried it. Introducing the callback function(s) of the toolbar(s) as a nested function inside the function in the App Designer that calls uitoobar solves the problem.
Thanks for following up. Nesting the callback function within the startupFcn in that way makes sense. I don't think I've ever used a nested function in AppDesigner; I didn't even know that was supported.
Yeah. At the end, it solved the problem. Learnt a new thing as well. I am happy. :)

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Develop Apps Using App Designer dans Centre d'aide et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by