Search code examples
matlabmatlab-guidematlab-gui

Matlab WindowButtonMotion callback stops working when image is changed


In my GUIDE generated gui I have an axes object into which I imshow() a bitmap when the gui initializes. I have a WindowButtonMotion callback defined as:

function theGui_WindowButtonMotionFcn(hObject, eventdata, handles)
  % handles.mode_manager is initialized in the gui startup code
  if (isempty(handles.mode_manager.CurrentMode))
    obj_han=overobj('axes');
    if ~isempty(obj_han)
      set(handles.theGui, 'Pointer','cross');
    else
      set(handles.theGui, 'Pointer','arrow');
    end
  end
end

I have a callback on the open file button on the toolbar that does this:

function openFile_ClickedCallback(hObject, eventdata, handles)
  % handles.image_handle received the handle from the imshow that 
  % opened the initial image
  tmp_handle = handles.image_handle;
  [name, path] = uigetfile({'*.bmp'; '*.jpg'});
  if (path == 0)
    return
  else
    filename = strcat(path, name);
  end

  % read the image into the axes panel
  hold on
  handles.image_handle = imshow(filename);
  set(handles.image_handle, 'ButtonDownFcn', @imageMouseDown);
  handles.mode_manager = uigetmodemanager();
  delete(tmp_handle);
  guidata(hObject, handles);
end

After the new image is displayed in the axes object of the gui, the pointer no longer changes to a cross over the axes object. The problem has something to do with the newly displayed image, because if I comment out the part of the code that actually displays the new image, the pointer appears as a cross after calling the openFile callback.


Solution

  • The callback stops working, because using imshow replaces the axes object.

    The following code demonstrates the problem:

    imshow(zeros(100));
    h = gca;
    h.UserData = 123;  %Set UserData property value to 123
    imshow(ones(100)); %Use imshow again.
    h2 = gca;
    

    Now:

    h2.UserData
    
    ans =
    
         []
    
    h.UserData
    Invalid or deleted object.
    

    As you can see, using imshow again replaced the axes object, with new axes object.


    The following example, modifies only the image data, without modifying the axes:

    image_handle = imshow(zeros(100));
    h = gca;
    h.UserData = 123;  %Set UserData property value to 123
    %imshow(ones(100), 'Parent', h); %Use imshow again.
    image_handle.CData = ones(100); %Modify only image data, without modifying the axes. 
    h2 = gca;
    

    Now:

    h2.UserData
    
    ans =
    
       123
    

    Modify your handles.image_handle = imshow(filename); code to:

    I = imread(filename);
    handles.image_handle.CData = I;