How to use subroutines inside subroutins in GUI functions?

2 views (last 30 days)
If I make a function in a GUI function, it can access the global variables of the GUI, so I can use it like a subroutine. But how can I use the same function in another function? Because if I embed it in another function, it already says "Unrecognized function or variable". For shortcuts I would like to use subroutines even within subroutines. How can I do that?

Answers (2)

Walter Roberson
Walter Roberson on 28 May 2023
A different one of your questions implies that you are using GUIDE, or hand-building your code -- that in particular you are not using App Designer. If you had been using App Designer then it would have been mandatory to pass in a parent when building the uicontrol()
If you are using GUIDE, then GUIDE always builds the .m file in the form
function NAMEOFPROJECT(varargin)
%lots of comments
some initialization code
function NAMEOFCALLBACK(hObject, event, handles)
%lots of comments
some code
and so on. Notice there are no end statements matching the function lines when GUIDE builds code.
You can only build functions inside of other functions (nested functions) when you have functions that have end lines matching the function lines. For example if the code structure had been
function NAMEOFPROJECT(varargin)
%lots of comments
some initialization code
end
function NAMEOFCALLBACK(hObject, event, handles)
%lots of comments
some code
outputs = NESTEDFUNCTION(parameters)
function NESTEDFUNCTION(parameters here)
%this is inside of NAMEOFCALLBACK
nested code
end
end
If you hand-convert each function inside a GUIDE-produced .m file to have a matching end then you can add nested functions to it. However, GUIDE is not able to manage code with that design, so you would not be able to use GUIDE to develop the code after that time.
When you define a nested function, the nested function can only be called from inside the outer function -- unless, that is, something outside manages to get a handle to the nested function (and there are reasons to sometimes design with that pattern.)
If you create a function file that defines multiple functions, such as the initial code I outlined above, then only the first function in the function file can be directly called from any other function file, unless somehow the other function has been given a handle to the additional functions. This can be a bit of a limitation at times, so GUIDE works around the problem by having the first function (NAMEOFPROJECT in this example) expect a character vector as the first parameter, and when it gets it, calls the function with that name from inside the .m file. Because it is called from inside the defining file, MATLAB is able to find the function. This design pattern is sometimes called "switchyard"
If you create a .m file that does not start with function or classdef then that .m file is considered a "script" file. Since R2015b, script files have been able to define functions after the script, provided that the functions have a matching end statement. Those functions have the same limitation as additional functions in a function file, in that they can only be called from within the same file (unless something outside manages to get a handle to the function.)
So... if you want to define a bunch of utility routines that can be called from multiple .m files, then create one function .m file for each utility routine.
... And don't use global unless you are interfacing with some code that needs global variables and cannot reasonably be modified to stop using global variables. global is the slowest way to access variables, and it has the highest risk of making mistakes that are hard to find.
  1 Comment
Merse Gaspar
Merse Gaspar on 28 May 2023
I try to write my code by hand.
I basically looked at this tutorial:
And this is what the code skeleton looks like:
function mygui
% general and global initializations, data loading, etc.
gui_element1 = uicontrol();
gui_element2 = uicontrol();
% callback functions:
end

Sign in to comment.


jinhu
jinhu on 28 May 2023
To add, when calling s=SerialDataRead (hObject, eventdata, handles, SerialPort); When using functions, you can also modify axes in the GUI, such as setting the coordinate axis range and opening the grid, all of which are fine.
When I draw in the callback function of the serial port, it cannot affect the GUI
The handle was not passed to the serial callback function, so the current question is how to pass parameters to the serial callback function?
  1 Comment
Walter Roberson
Walter Roberson on 28 May 2023
When I draw in the callback function of the serial port, it cannot affect the GUI
In order for the callback of a serial function to affect the GUI, the following is true:
  • the graphic operations in the callback must be executing in the same process as the display is running -- so the graphic operations must not be executing inside parfor or parfeval or batch or spmd
  • the graphic operations in the callback must not be executing in a background pool
  • graphic updates will not appear until the next time the code uses pause() or drawnow() or one of a small number of other functions
You should be especially careful doing graphic operations inside callbacks, as the "current" figure or "current" axes might not be what you are expecting.
Note: one way to associate a handle with a serial port is to set the UserData of the serial port object to the desired handle. The handle to the serial port object will always be passed as the first parameter to the serial port callback.

Sign in to comment.

Categories

Find more on Migrate GUIDE Apps in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!