What would cause Matlab to lose track of gcf()?

12 views (last 30 days)
I'm trying to reproduce a bug/reduce it to something I can report, but so far it only happens when I call a particular 150-line function. I can put the offending code, up to and including the line that causes the error, in a new function and it runs fine, so I imagine there's something going on behind the scenes with the other 140 lines. T̶h̶i̶s̶ ̶c̶o̶d̶e̶ ̶r̶u̶n̶s̶ ̶f̶i̶n̶e̶ ̶o̶n̶ ̶W̶i̶n̶d̶o̶w̶s̶.̶
If I pause inside the function and type
which gcf
I get: built-in (/Applications/MATLAB_R2024a.app/toolbox/matlab/graphics/gcf)
Which is correct. But when I call gcf immediately after, I get:
Unrecognized function or variable 'gcf'.
Sorry I don't have an example to upload. I'm just looking for troubleshooting ideas.
  5 Comments
dpb
dpb on 7 Sep 2024
Edited: dpb on 7 Sep 2024
I figured it would be something of the sort where somehow you would have redefined gcf or got bad syntax with it...glad you did find it.
But,
gcf().Children.Title % To demonstrate there's a figure
I would strongly recommend against writing code of such nature where you call either gcf or gca repeatedly to refer to the same figure/axes; besides such syntax errors as the above, since MATLAB is event driven, it is possible an external event such as user interaction can change focus and instead of the desired figure/axis being returned, you get what that new focus is.
Much more reliable coding is to save the handles of the objects when you create them, or if it is necessary to call gcf; then do it like
hF=gcf;
...
and then use hF consistently in the function -- you'll avoid such issues as writing such bad syntax and also be assured of using/referring to the correct figure later on. If you do have multiple figures/axes, create an array of grapics objects handles to hold them.
% gcf().Children.Title.String = "I AM ERROR"
and certainly, trying to assign to a property of an inderect reference to the property of the secondary graphic object is not surprising to have confused the parser even if it isn't specifically written to prohibit such.
axes
gcf().Children
ans =
Axes with properties: XLim: [0 1] YLim: [0 1] XScale: 'linear' YScale: 'linear' GridLineStyle: '-' Position: [0.1300 0.1100 0.7750 0.8150] Units: 'normalized' Use GET to show all properties
gcf().Children.Title
ans =
Text with properties: String: '' FontSize: 11 FontWeight: 'bold' FontName: 'Helvetica' Color: [0 0 0] HorizontalAlignment: 'center' Position: [0.5000 1.0077 0.5000] Units: 'data' Use GET to show all properties
does return the handle to the title, but trying to do an assignment in that syntax is just expecting too much.
But, consider
figure
axes;
colorbar;
gcf().Children
ans =
2x1 graphics array: ColorBar Axes
and now you've got an array of children and what is
gcf().Children.Title
Unrecognized method, property, or field 'Title' for class 'matlab.graphics.primitive.world.Group'.
to try to do now?
It is far better to save handles to the objects when you create them and use those, but if you find you simply must find a particular object such as the title in an axes, then use findobj to do so by 'Type' or 'Tag' or similarly.
Chris
Chris on 7 Sep 2024
> I would strongly recommend against writing code of such nature where you call either gcf or gca repeatedly to refer to the same figure/axes;
In the original code I was calling functions (created for another purpose) that generate figures I either didn't want here, or wanted to modify. The first problem line was close(gcf), getting rid of one of those figures.
The final problem line was immediately after another function call, to change the titles in a tiledarray it had generated.
But yeah, saving the handles at least causes the correct error to be thrown. And of course, cleaner code would have made this much easier to trace.

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 7 Sep 2024
Unrecognized function or variable 'gcf'.
You can get that error if you had previously defined gcf as a variable in your code, but then you cleared the variable. When you create a variable then MATLAB removes the name from the list of available functions; when you then clear the variable it no longer knows it as a variable and does not add it back in as a function.
  6 Comments
dpb
dpb on 12 Sep 2024
Edited: dpb on 12 Sep 2024
figure;
close(gcf)
% nongraphics code here...
tmp=gcf;
tmp.Children
ans =
0x0 empty GraphicsPlaceholder array.
If there were only one figure when closed gcf(), then the gcf() call subsequently will create a new one; but that's all it will have done at that point.
Still is very unsafe code construction using implicit handles; there's no guarantee about what the Children of gcf() will be; is not necessarily even a single object, nor any, the latter of which is the case here because creating the default figure only results in the figure handle itself; there are no children until put an axes or other allowable child of a figure graphics object into it...referring to an empty figure's children does return the placeholder without error, but then trying to address a property of an as yet uncreated child object rightfully errors.
dpb
dpb on 12 Sep 2024
figure; axes;
figure;
close(gcf)
% nongraphics code here...
tmp=gcf;
tmp.Children
ans =
Axes with properties: XLim: [0 1] YLim: [0 1] XScale: 'linear' YScale: 'linear' GridLineStyle: '-' Position: [0.1300 0.1100 0.7750 0.8150] Units: 'normalized' Use GET to show all properties
Alternatively, if there were multiple figures extant and an earlier one did have something inside it; then the result would be the previous....
Again, can't emphasize enough how unsafe/undpredictable such coding practice is and should be strictly avoided.

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 7 Sep 2024
Edited: Image Analyst on 7 Sep 2024
Don't do it like that: gcf().something. Assign something to gcf, like g:
g = gcf; % No parentheses after gcf. I think a figure must have already been created before doing this.
then you can set properties of g to change the gcf properties:
g.WindowState = 'maximized' % Maximize the figure window.
When you do
gcf().Children.Title % To demonstrate there's a figure
it assumes gcf is a variable and is a vector. But it is NOT. But since you put parentheses, it assumes it is and it wants an index inside the parentheses, which you didn't provide. That's why it's giving you the error "At least one index is required." As far as I know gcf just refers to the current figure and therefore is never an array and so won't take parenthese or an index. If you need a bunch of figures up simultaneously and need to manipulate their properties, you need to save their handles, which can be an array of handles, or just simply separate variables, like
g1 = figure('Name', 'This is figure 1');
g2 = figure('Name', 'This is figure 2');
g3 = figure('Name', 'This is figure 3');
Then you can manipulate whichever one you want individually, as long as that figure window still exists (you haven't closed it).
  1 Comment
Chris
Chris on 11 Sep 2024
Edited: Chris on 11 Sep 2024
> As far as I know gcf just refers to the current figure and therefore is never an array and so won't take parenthese or an index.
The function gcf offers dot notation for accessing the properties of the figure. If I try gcf.Children, I get an error:
gcf.Children
Dot indexing into the result of a function call requires parentheses after the function name. The supported syntax is 'gcf().Children'.
So gcf().Children is correct.
Clearly, it's not advisable to attempt this inside a function, however.

Sign in to comment.

Categories

Find more on Graphics Object Identification in Help Center and File Exchange

Tags

Products


Release

R2024a

Community Treasure Hunt

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

Start Hunting!