6

I did an app designer GUI with two buttons and axes. The first one (LoadimageButton) is loading the pappers image and I can mark points until I press escape. The second button is printing out the point coordinates (PositionButton).

I have noticed that after pressing the two buttons I can move points in the axes and change their positions or delete them. The issue is that when I press the delete (in the context menu) I get this error after pressing the PositionButton:

Error using images.roi.Point/get
Invalid or deleted object.

Error in tempDrwPnt1/PositionButtonPushed (line 61)
positions = cell2mat(get(app.pointhandles, 'position'))

Error while evaluating Button PrivateButtonPushedFcn.

How can I refresh the app.pointhandles after deleting a point?

Code:

function LoadimageButtonPushed(app, event)
            imshow('peppers.png','Parent',app.ImageAxes); 
          
            userStopped = false; 
            app.pointhandles = gobjects(); 
                   while ~userStopped
                        roi = drawpoint(app.ImageAxes); 
                        if ~isvalid(roi) || isempty(roi.Position)
                            % End the loop
                            userStopped = true;
                        else
                            % store point object handle
                            app.pointhandles(end+1) = roi;
                        end
                   end 
            

            addlistener(roi,'MovingROI',@allevents);
            addlistener(roi,'ROIMoved',@allevents);
  
            app.pointhandles(1) = []; 
            
            function allevents(src,evt)
                evname = evt.EventName;
                switch(evname)
                    case{'MovingROI'}
                        disp(['ROI moving previous position: ' mat2str(evt.PreviousPosition)]);
                        disp(['ROI moving current position: ' mat2str(evt.CurrentPosition)]);
                    case{'ROIMoved'}
                        disp(['ROI moved previous position: ' mat2str(evt.PreviousPosition)]);
                        disp(['ROI moved current position: ' mat2str(evt.CurrentPosition)]);
                end
            end 
end


% Button pushed function: PositionButton
function PositionButtonPushed(app, event) 
positions = cell2mat(get(app.pointhandles, 'position'))
end
scotty3785
  • 6,763
  • 1
  • 25
  • 35
alirazi
  • 159
  • 8

1 Answers1

4

You could add a check within the PositionButtonPushed function for whether or not each pointhandles element is valid, report on it if so or remove it if not

Something like

function PositionButtonPushed(app, event)
    nPts = numel(app.pointhandles);
    positions = NaN(nPts,2); % array to hold positions
    for iPt = nPts:-1:1 % loop backwards so we can remove elements without issue
        if isvalid( app.pointhandles(iPt) )
            positions(iPt,:) = get(app.pointhandles(iPt),'position');
        else
            % No longer valid (been deleted), remove the reference
            app.pointhandles(iPt) = [];
            % Also remove from the positions output
            positions(iPt,:) = [];
        end
    end
end

I haven't got a compatible MATLAB version available right now to test this, but I am assuming the in-built function isvalid works for Point objects, otherwise you will have to add your own validity check. Alternatively you could try to get the position, and do the deletion (handled by else above) within a catch, but I usually recommend against try/catch if you can check for a specific (known) issue instead.

I've often used something similar (e.g. for axes), but bundled the cleanup functionality for invalid handles into its own function. In this case it would have let you add a single function call before getting the positions of the remaining valid points.

I've also made this more condensed by using arrayfun, but under the hood it's the same approach as the above loop:

function PositionButtonPushed(app, event )
    app.checkHandleValidity(); % cleanup handles just in case

    positions = cell2mat(get(app.pointhandles, 'position'));
end

function checkHandleValidity( app )
   bValid = arrayfun( @isvalid, app.pointhandles ); % Check validity
   app.pointhandles( ~bValid ) = [];                % Remove invalid elements
end
Wolfie
  • 27,562
  • 7
  • 28
  • 55