Saving a grid of lines to be recalled using findobj and assigning to an app property

68 views (last 30 days)
Hi, I have an image on uiaxes that I often draw a grid on and each region I perform some kind of analysis. For example in the picture below I just calculate the median of the intensites in the centre and at edges of the image - llustrated by the cyan dots
I want the ability to view or turn off the grid.
This is what I do once the grid is drawn (and analysis performed)
% Grid ines are always red and solid, so find them and assign to my app property "myGrid"
h1=findobj(app.UIAxes,'Color','red','LineStyle','-');
app.myGrid=h1;
and i have a check box where I can turn on or off via.
val = app.GridCheckBox.Value;
grid=app.myGrid
% Toggle visibility of the group of grid lines
switch val
case 1
set(grid, 'Visible', 'on'); % Hide all lines
case 0
set(grid, 'Visible', 'off'); % Show all lines
end
This works well, except, when i remove the cyan dots via my RemoveAnnotations function below and then try to turn the grid back on it says the object is deleted
function RemoveAnnotations(app,ax)
clc;
h1 = findall(ax, 'type', 'line');
h2 = findall(ax, 'type', 'text');
h3 = findall(ax, 'type', 'rectangle');
delete(findall(ax,'type', 'Marker')); %Delete markers
delete(findall(ax,'Type','images.roi.Line'));
h4 = findall(ax, 'type', 'ConstantLine');
delete(h1); delete(h2); delete(h3); delete(h4);
end
Now click the grid checkbox to turn back on the gridlines
Invalid or deleted object.
Error in HTS_TestSoftware/GridCheckBoxValueChanged (line 20679)
set(grid, 'Visible', 'on'); % Hide all lines in the group% and
How can this be as app.myGrid still contains the lines?
grid =
35×1 Line array:
Line
Line
.....

Answers (3)

Stephen23
Stephen23 on 30 Sep 2025 at 13:52
Edited: Stephen23 on 30 Sep 2025 at 14:41
"How can this be as app.myGrid still contains the lines?"
You might find these useful:
https://www.mathworks.com/help/matlab/ref/ishghandle.html <=== if you need to check hidden objects
Lets take a look at what those handles refer to:
lnh = line(rand(9,35),rand(9,35))
lnh =
35×1 Line array: Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line
lnh(1) % this is a handle to an existing graphics object
ans =
Line with properties: Color: [0.0660 0.4430 0.7450] LineStyle: '-' LineWidth: 0.5000 Marker: 'none' MarkerSize: 6 MarkerFaceColor: 'none' XData: [0.8982 0.6207 0.6890 0.4590 0.5190 0.9430 0.3435 0.8622 0.1851] YData: [0.3525 0.6628 0.1456 0.6103 0.0450 0.8534 0.5206 0.6489 0.5642] ZData: [1×0 double] Use GET to show all properties
[isgraphics(lnh),ishghandle(lnh),isvalid(lnh)]
ans = 35×3 logical array
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
delete(lnh)
lnh % the same ? !!! NO !!!
lnh =
35×1 Line array: Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line Line
lnh(1) % this is not a handle to anything!
ans =
handle to deleted Line
Handle arrays may contain both existing and deleted objects
[isgraphics(lnh),ishghandle(lnh),isvalid(lnh)]
ans = 35×3 logical array
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
"I want the ability to view or turn off the grid."
Then just turn the line visibility off and on:
Deleting and recreating those lines is hugely inefficient when all you want to do it toggle their visibility.
  6 Comments
Jason
Jason on 30 Sep 2025 at 15:14
Hi, Thankyou for your help / explanation. Regarding the "inefficient" deleting
So here's the thing. I create the grid lines representing regions I use with blockproc. I then do a tonne of stuff, add annotations, other lines etc. I then want to come back at some later time and load up just the grid again on the image.
I delete as I have all the other annotations. I don't necessarily require the visibility on or off, I just want a way where I can capture the grid lines, and at a later time (even after a remove annotations), splat the grid back on
Stephen23
Stephen23 on 30 Sep 2025 at 19:47
"I just want a way where I can capture the grid lines, and at a later time (even after a remove annotations), splat the grid back on"
That is exactly what the visibility is for.

Sign in to comment.


Steven Lord
Steven Lord on 30 Sep 2025 at 14:29
Just because the handles exist doesn't mean they're valid. They can hold handles to deleted objects. Let's make a figure handle. At first, it's valid because the figure exists.
f = figure
f =
Figure (1) with properties: Number: 1 Name: '' Color: [1 1 1] Position: [1628 1512 560 419.7599] Units: 'pixels' Use GET to show all properties
isvalid(f)
ans = logical
1
Now if we close the figure, the variable f doesn't disappear. But it's no longer a valid figure handle, and if you display it it doesn't show any information about the figure that used to exist.
close(f)
isvalid(f)
ans = logical
0
disp(f)
handle to deleted Figure
If you have a vector of multiple handles, some or all of them could be invalid while others aren't. MATLAB doesn't display some as deleted and some as valid in the vector. Note that the display of f2 before and after the close() call are very similar, but there is a difference: before it shows which figure number is stored in that element of the array, after it doesn't.
f2 = [figure; figure]
f2 =
2×1 Figure array: Figure (1) Figure (2)
isvalid(f2)
ans = 2×1 logical array
1 1
close(f2(1))
isvalid(f2)
ans = 2×1 logical array
0 1
close(f2(2))
isvalid(f2)
ans = 2×1 logical array
0 0
disp(f2)
2×1 Figure array: Figure Figure
The figure number thing is specific to figures. If you had handles of lines, the display before and after the clearing (and the invalidation of the handles stored in L) is the same.
L = [line(1:10, 1:10), line(1:10, 10:-1:1)]
L =
1×2 Line array: Line Line
isvalid(L)
ans = 1×2 logical array
1 1
cla % clear the axes, deleting the lines
isvalid(L)
ans = 1×2 logical array
0 0
disp(L)
1×2 Line array: Line Line
If you display each element of L separately, though, you can see they're deleted.
disp(L(1))
handle to deleted Line
disp(L(2))
handle to deleted Line
Rather than deleting the grid lines, you may want to simply turn their visibility off to "delete" them if you're likely going to recreate them soon after.
  3 Comments
Steven Lord
Steven Lord on 30 Sep 2025 at 16:41
Turning the visiblity of the lines in your graph off is like putting your Christmas decorations in a box in the attic in January and storing them for the rest of the year. When you want to decorate your next Christmas tree, you pull the box out (turning the visibility on) and the decorations should be ready to reuse.
Deleting the lines in your graph is like putting your Christmas decorations in a box in the trash or the recycling in January. When you want to decorate your next Christmas tree, you have to buy new decorations (create the lines anew.) While I suppose in this metaphor you could try to find the landfill where your Christmas decorations were taken and dig them out (difficult at best, and yuck!), you can't un-delete the lines.
The easiest way to "splat the grid back on" is to toggle the visibility. If you're worried about calls to findobj finding your grid lines, there are a couple possible solutions I can think of off the top of my head:
  1. Don't use findobj. Store vectors of handles in variables and/or object properties and refer to those known lists of handles rather than searching for them each time. In the Christmas decorations metaphor, put all your ornaments in a box labeled "ornaments" rather than searching through the larger box each time you're trimming the tree.
  2. Set the line handles' HandleVisibility property to 'off' or 'callback'. If you do this, findobj won't find them. The findall function would, but that's an even bigger hammer than findobj.
  3. I'm not sure if this would work for your application, but why draw the grid yourself? Why not let MATLAB draw the grid for you? Note the long list of grid-related properties listed for various types of axes on this documentation page.
Jason
Jason on 30 Sep 2025 at 16:47
Edited: Jason on 30 Sep 2025 at 16:48
I like the idea of using "grid", but I though that was only for plots where the x & y ticklabels and values are present. I dont have these as Im displaying images
and....
I think it will do the same as the xline and ylines below - i.e. fillt he wholeuiaxes even though the image doesnt fill the whole uiaxes

Sign in to comment.


Jason
Jason on 30 Sep 2025 at 16:14
Maybe I should back away from graphic object handles and just use XLine and Yline to create my grid and just save the vector values used for X & Y in a struct for example
  5 Comments
Walter Roberson
Walter Roberson on 1 Oct 2025 at 20:34
Just save the ticks to an app property.
Or to the UserData property of the uiaxes.
However if you are talking about resetting the uiaxes, then you need to be careful about how you reset it. The most convenient ways of resetting a uiaxes involve deleting and recreating the uiaxes, in which case any saved property would be lost.

Sign in to comment.

Products


Release

R2024b

Community Treasure Hunt

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

Start Hunting!