Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intermittent bug in levelsplot() #352

Open
katarkon opened this issue Nov 7, 2024 · 2 comments
Open

Intermittent bug in levelsplot() #352

katarkon opened this issue Nov 7, 2024 · 2 comments

Comments

@katarkon
Copy link

katarkon commented Nov 7, 2024

Sometimes levelsplot() throws the follow errors when mouse is moved over figure window:

Invalid or deleted object.
Error in levelsplot
Error while evaluating Figure WindowButtonMotionFcn

No lines are highlited, of course.
The bug does not seem to be reproducible. I cannot find unambiguous conditions when it occurs, but such behaviour is kept until MATLAB rebooting.

@stestoll
Copy link
Member

This is likely due to the persistent variable hPrevLine in the function windowButtonMotionFcn. There might be situations where the object referenced by hPrevLine is no longer valid.

Can you find a way to reproduce this error?

@cerium1925
Copy link

cerium1925 commented Jan 17, 2025

     The issue arises from a timing mismatch between the WindowButtonMotionFcn callback and the lifecycle of MATLAB graphic objects. Closing the figure or clearing objects while the callback runs causes an "Invalid or deleted object" error when accessing deleted objects.

   The root cause is a persistent variable storing a handle to a deleted object. Eliminating the persistent variable and using findobj to dynamically retrieve objects during each callback ensures operations are performed only on existing objects, preventing errors and improving robustness.   MATLAB strongly discourages the use of persistent variables due to risks of unintended global modifications or leaks into other functions. Passing parameters between functions is generally safer and more convenient.

Here is an example of the fixed code:

%-------------------------------------------------------------------------------
function windowButtonMotionFcn(,,~)

% Line width settings
hoverLineWidth = 2;
defaultLineWidth = 0.5;

% Get object under mouse pointer
hObj = hittest();
if isempty(hObj), return; end

% Get parent axes
hParent = ancestor(hObj,'axes');
if isempty(hParent), return; end

% Reset all previously highlighted lines to default width
hFig = ancestor(hObj,'figure');
allLines = findobj(hFig,'-property','LineWidth','-and',{'Tag','level','-or','Tag','transition'});
set(allLines,'LineWidth',defaultLineWidth);

% Generate information string based on object type
switch hObj.Tag
case 'level'
infostr = sprintf(' level %d',hObj.UserData);
hObj.LineWidth = hoverLineWidth;
case 'transition'
infostr = sprintf(' transition %d-%d: %0.2f mT, relative intensity %0.4f ',...
hObj.UserData(1),hObj.UserData(2),hObj.UserData(3),hObj.UserData(4));
hObj.LineWidth = hoverLineWidth;
case 'line'
infostr = sprintf(' transition %d-%d: %0.2f mT, relative intensity %0.4f ',...
hObj.UserData(1),hObj.UserData(2),hObj.UserData(3),hObj.UserData(4));
hObj.LineWidth = hoverLineWidth;
otherwise
infostr = '';
end

% Display information text
hText = findobj(hParent,'Tag','infotext');
if ~isempty(hText)
set(hText,'String',infostr);
% Update text position to keep it visible after zooming
if ~isempty(infostr)
hText.Position(1:2) = [hParent.XLim(1) hParent.YLim(1)];
end
end

end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants