MATLAB Answers

Can't reach line object from callback function - 'Invalid or deleted object.'

2 views (last 30 days)
Hello!
Let me begin by saying that I'm not used to this part of Matlab so I apologize for any trauma that may occur. I am trying to plot a bunch of lines, and toggle their 'visible' property on/off using check boxes. What adds a bit of complexity is that my plot data is extracted from a logfile using regex, and so the number of lines to plot may vary (so I can't hard code). By reading on this forum I managed to find how to generate the checkboxes with a loop. I've also managed to plot the desired lines in the same figure. The callback function seems to work as intended, with the exception that I can't actually seem to reach the line object, and instead get the error 'Error using matlab.graphics.chart.primitive.Line/set. Invalid or deleted object.'
I've scavenged a bunch of code that I found on this forum without managing to do it. My code below is attempt #354, so if you're wondering "Why is X there?", the answer might be "giraffe". I've made up some random data so that it's executable and it seems to reproduce my issue. Thanks in advance!
clc
guiobj.f = figure;
guiobj.ax = axes;
guiobj.ax.Parent = guiobj.f;
hold on
% Mock data
Names = ['A'; 'B'];
obj{2,1} = rand(100, 4); % replicates annoying format of my logfile read
%----------
posFig = get(guiobj.f,'Position');
hFig = posFig(4); % height of the figure
for k=1:length(Names)
hold on
% Create checkboxes
guiobj.chkbox(k) = uicontrol('Parent',guiobj.f,'Style','checkbox','String',Names(k), ...
'Value',0,'Position',[30 hFig - 30 - 20*(k-1) 160 20], ...
'Callback',{@checkBoxCallback,k, guiobj});
% Create lines
guiobj.line(k) = plot(guiobj.ax, obj{2,1}(:,2*k)); % skip every other column because they contain Names (regex junk)
set(guiobj.line(k),'visible','off') % 'Visible off' at creation in loop
guidata(guiobj.f, guiobj.line(k));
end
% 'Visible on' as proof that all lines are reachable after loop.
% Try changing to off and executing the line (and back again) to see that toggle works.
set(guiobj.line(:),'visible','on')
function checkBoxCallback(source, data, k, guiobj)
fprintf('Check box %s is %d\n',get(source,'String'),get(source,'Value'));
if get(source,'Value') == 1
disp('true'); % Confirmation of entering
set(guiobj.line(k),'visible','on')
else
disp('false') % Confirmation of entering
set(guiobj.line(k),'visible','off')
end
end
%%

  0 Comments

Sign in to comment.

Accepted Answer

Geoff Hayes
Geoff Hayes on 20 Nov 2020
Fredrik - I suspect the problem is here
guiobj.chkbox(k) = uicontrol('Parent',guiobj.f,'Style','checkbox','String',Names(k), ...
'Value',0,'Position',[30 hFig - 30 - 20*(k-1) 160 20], ...
'Callback',{@checkBoxCallback,k, guiobj});
The guiobj that you are passing as the fourth parameter to the callback will be a copy of this object as it is now. By that I mean that it will have all the properites/attributes of the guiobj at the time this line of code is executed and so won't have the line object that you create on the next line of code. You could pass a different object instead (say the figure) then use guidata in a slightly different way, but I recommend using nested functions where your callbacks have access to the variables declared in your parent function so that you won't have to pass data into the callback like you are doing above. You could do something like
function parentFunction % <-- function name also used for m-file name
clc
close all;
guiobj.f = figure;
guiobj.ax = axes;
guiobj.ax.Parent = guiobj.f;
hold on
% Mock data
Names = ['A'; 'B'];
obj{2,1} = rand(100, 4); % replicates annoying format of my logfile read
%----------
posFig = get(guiobj.f,'Position');
hFig = posFig(4); % height of the figure
for k=1:length(Names)
hold on
% Create checkboxes
guiobj.chkbox(k) = uicontrol('Parent',guiobj.f,'Style','checkbox','String',Names(k), ...
'Value',0,'Position',[30 hFig - 30 - 20*(k-1) 160 20], ...
'Callback',{@checkBoxCallback,k});
% Create lines
guiobj.line(k) = plot(guiobj.ax, obj{2,1}(:,2*k)); % skip every other column because they contain Names (regex junk)
set(guiobj.line(k),'visible','off') % 'Visible off' at creation in loop
end
% 'Visible on' as proof that all lines are reachable after loop.
% Try changing to off and executing the line (and back again) to see that toggle works.
set(guiobj.line(:),'visible','off')
% nested function so has access to guiobj
function checkBoxCallback(source, data, k)
fprintf('Check box %s is %d\n',get(source,'String'),get(source,'Value'));
if get(source,'Value') == 1
disp('true'); % Confirmation of entering
set(guiobj.line(k),'visible','on')
else
disp('false') % Confirmation of entering
set(guiobj.line(k),'visible','off')
end
end
end

More Answers (0)

Products


Release

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by