GUIDATA does not trasfer data in GUIDE with subfunctions.

4 Ansichten (letzte 30 Tage)
Alborz Sakhaei
Alborz Sakhaei am 26 Okt. 2016
Kommentiert: Geoff Hayes am 30 Okt. 2016
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

Akzeptierte Antwort

Geoff Hayes
Geoff Hayes am 29 Okt. 2016
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
  2 Kommentare
Alborz Sakhaei
Alborz Sakhaei am 29 Okt. 2016
Thank you very much Geoff. Appreciate your time. That completely resolved my issue. Just one minor comment: In pushbutton_vertline_Callback the line guidata(h,handles) should be guidata(hButton,handles). Please correct me if I'm mistaken. Thanks again, Alborz
Geoff Hayes
Geoff Hayes am 30 Okt. 2016
For sure, Alborz. Yes, you are correct - the line should read
guidata(hButton,handles)

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Walter Roberson
Walter Roberson am 28 Okt. 2016
In order for a variable to be shared it must be initialized in the containing routine before the declaration of the subfunctions that share it. It then becomes shared only with the containing and contained routines.
You are not using the mousedown variable in a shared way. Even if you had initialized it before the subfunctions, in the second subfunction you test whether handles has a field with that name and if so then you grab that value and if not then you force the variable to false. Any shared value would be overwritten. No other routines read the shared value so that is not for the benefit of some other routine.
Consider too that you do not delete out of handles when you poll in the nested function so the next time through you would pull from the handles again. You have no code that sets the handles version to false or removes it, so once set the handles version is going to remain true.

Kategorien

Mehr zu Tables finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by