MATLAB: GUIDATA does not trasfer data in GUIDE with subfunctions.

guidataguide gui handles transmit draggable

I have a simple GUIDE with 2 pushbuttons. Button #1 plots a sine graph and button #2 adds a "draggable" vertical line to the graph. Idea is based on the link bellow [1]
I'm using guidata to transfer data between subfunctions and callbacks in the `GUIDE`. But one of the shared variables (mousedown) does not transmit between the callbacks. What causes the loss of data transfer between the subfunctions in GUIDE?
Here are the callbacks with their subfunctions (the entire code is attached):
% ######### Callbacl 1: Graph SIN function
function pushbutton_plot_Callback(hObject, eventdata, handles)
clc;
open_figs_h = get(0,'children');
close(open_figs_h(2:end));
x = -pi:0.01:pi;
y = sin(x);
fig_h = figure('units','normalized','outerposition',[0.2 0.2 .5 .5],'WindowButtonMotionFcn', @MouseMove, 'WindowButtonUpFcn', @MouseUp );
axis_h = axes('parent',fig_h,'position',[0.1 0.1 .8 .8]);
line('parent',axis_h,'xdata',x,'ydata',y);
handles.axis_h = axis_h;
guidata(hObject,handles);
% MouseUp and MouseMove subfunctions in callback 1
function MouseUp(h,event) %#ok<*INUSD>
mousedown = false;
end
function MouseMove(h,event)
if isfield(handles,mousedown)
mousedown = handles.mousedown;
else
mousedown = false;
end
if mousedown
cp = get ( axis_h, 'CurrentPoint' );
vertline_h = handles.vertline_h;
set ( vertline_h, 'XData', [cp(1,1) cp(1,1)] );
end
end
end
%######### Callbacl 2: Graph movables vertical line
function pushbutton_vertline_Callback(h, eventdata,handles)
axis_h = handles.axis_h;
vertline_h = line('parent',axis_h,'xdata',[1 1],'ydata',[-1 1], 'ButtonDownFcn', @mouseDown );
handles.vertline_h = vertline_h;
guidata(h,handles)
% MouseMove subfunction in callback 2
function mouseDown(hObject,event)
mousedown = true;
handles.mousedown = mousedown;
guidata(hObject,handles)
end
end

Best Answer

Alborz - your code has interesting approach by assigning the ButtonDownFcn to the line object so that when the user presses down on the line (and only the line), this event will fire. Though instead of calling guidata with hObject which is the handle to the line object, you probably want to call it with the handle to the button, h, since it is a child of the GUI and the handles structure is "associated" with that. So the pushbutton_vertline_Callback code would change to
function pushbutton_vertline_Callback_Callback(hButton, eventdata,handles)
axis_h = handles.axis_h;
vertline_h = line('parent',axis_h,'xdata',[1 1],'ydata',[-1 1], 'ButtonDownFcn', @mouseDown );
handles.vertline_h = vertline_h;
guidata(h,handles)
% MouseMove subfunction in callback 2

function mouseDown(hObject,event)
mousedown = true;
handles.mousedown = mousedown;
guidata(hButton,handles)
end
end
Like Walter has indicated, your mousedown variable is local to the MouseUp function and so setting it to true won't affect the field within the handles structure. So this function should change to
function MouseUp(h,event) %#ok<*INUSD>

handles = guidata(hObject);
handles.mousedown = false;
guidata(hObject,handles);
end
Note how in the above code, we use hObject (the handle to the pushbutton_plot) to get the latest updated version of handles rather than the older copy from the pushbutton_plot_Callback callback. So we get the latest version, change the mousedown field, and then save the updated handles structure.
And the MouseMove is almost correct with the only problem being that the handles of copy being used rather than the latest version. Again, we just need to call guidata as
function MouseMove(h,event)
handles = guidata(hObject);
if isfield(handles,'mousedown')
mousedown = handles.mousedown;
else
mousedown = false;
end
if mousedown
cp = get ( axis_h, 'CurrentPoint' );
vertline_h = handles.vertline_h;
set ( vertline_h, 'XData', [cp(1,1) cp(1,1)] );
end
end
See below for the full code which should work.
% Callbacl 1: Graph SIN function
function pushbutton_plot_Callback(hObject, eventdata, handles)
clc;
open_figs_h = get(0,'children');
close(open_figs_h(2:end));
x = -pi:0.01:pi;
y = sin(x);
fig_h = figure('units','normalized','outerposition',[0.2 0.2 .5 .5],...
'WindowButtonMotionFcn', @MouseMove, 'WindowButtonUpFcn', @MouseUp );
axis_h = axes('parent',fig_h,'position',[0.1 0.1 .8 .8]);
line('parent',axis_h,'xdata',x,'ydata',y);
handles.axis_h = axis_h;
guidata(hObject,handles);
% MouseUp and MouseMove subfunctions in callback 1
function MouseUp(h,event) %#ok<*INUSD>
handles = guidata(hObject);
handles.mousedown = false;
guidata(hObject,handles);
end
function MouseMove(h,event)
handles = guidata(hObject);
if isfield(handles,'mousedown')
mousedown = handles.mousedown;
else
mousedown = false;
end
if mousedown
cp = get ( axis_h, 'CurrentPoint' );
vertline_h = handles.vertline_h;
set ( vertline_h, 'XData', [cp(1,1) cp(1,1)] );
end
end
end
% Callbacl 2: Graph movables vertical line
function pushbutton_vertline_Callback(hButton, eventdata,handles)
axis_h = handles.axis_h;
vertline_h = line('parent',axis_h,'xdata',[1 1],'ydata',[-1 1], 'ButtonDownFcn', @mouseDown );
handles.vertline_h = vertline_h;
guidata(h,handles)
% MouseMove subfunction in callback 2
function mouseDown(hObject,event)
mousedown = true;
handles.mousedown = mousedown;
guidata(hButton,handles)
end
end