'WindowButtonDownFcn' cant detect handles data from other callbacks

7 views (last 30 days)
Hi,
I've set the 'WindowButtonDownFcn' in my GUI opening function as below:
set(gcf, ...
'WindowButtonDownFcn', @clickFcn, ...
'WindowButtonUpFcn', @unclickFcn);
The @clickFcn looks like that below, with a Drag function within it:
function clickFcn(hObject, eventdata, handles)
allAxes = findobj(gcf, 'Type', 'axes');
hCur = nan(1, length(allAxes));
for id = 1:length(allAxes)
hCur(id) = line([NaN NaN], ylim(allAxes(id)), ...
'Color', 'black', 'Parent', allAxes(id));
end
% Initiate cursor if clicked anywhere but the figure
if strcmpi(get(gco, 'type'), 'figure')
set(hCur, 'XData', [NaN NaN]); % <-- EDIT
set(hText, 'Position', [NaN NaN]); % <-- EDIT
else
set(gcf, 'WindowButtonMotionFcn', @dragFcn)
dragFcn();
end
The drag function is:
function dragFcn(varargin)
% Get mouse location
pt = get(gca, 'CurrentPoint');
% Update cursor line position
set(hCur, 'XData', [pt(1), pt(1)]);
% Update cursor text
for idx = 1:length(allLines)
xdata = get(allLines(idx), 'XData');
ydata = get(allLines(idx), 'YData');
if pt(1) >= xdata(1) && pt(1) <= xdata(end)
y = interp1(xdata, ydata, pt(1));
set(hText(idx), 'Position', [pt(1), y], ...
'String', sprintf('(%0.2f, %0.2f)', pt(1), y));
else
set(hText(idx), 'Position', [NaN NaN]);
end
end
When I click on the plot, I realized the clickfunction could not detect them. I've handles from other callbacks as below:
K>> handles
handles =
figure1: [1x1 Figure]
clear_all: [1x1 UIControl]
uipanel1: [1x1 Panel]
uipanel2: [1x1 Panel]
uipanel4: [1x1 Panel]
uipanel5: [1x1 Panel]
LoadFile: [1x1 UIControl]
pop_filelist: [1x1 UIControl]
var_list: [1x1 UIControl]
togglepan: [1x1 UIControl]
togglezoom: [1x1 UIControl]
selected_varlist2: [1x1 UIControl]
add_var2: [1x1 UIControl]
plot2_push: [1x1 UIControl]
selected_varlist1: [1x1 UIControl]
add_var1: [1x1 UIControl]
plot1_push: [1x1 UIControl]
axes2: [1x1 Axes]
axes1: [1x1 Axes]
text6: [1x1 UIControl]
select_folder: [1x1 UIControl]
text5: [1x1 UIControl]
output: [1x1 Figure]
b: 0
folder: 'C:\Users\r14ang\Documents\MATLAB'
count: 1
count2: 1
files: [9x1 struct]
selected_file: 'C:\Users\r14ang\Documents\MATLAB\TZ24SKE_SCOP_F_Cut3.csv'
selected_file_table: [3930x33 table]
variable_list: {1x33 cell}
sel_list_temp: {'ODPIPESENSOR'}
sel_list_temp2: {'COMPTEMP'}
time_sec2: [1x3930 double]
What have I done incorrectly?
Thanks in advance.

Accepted Answer

Geoff Hayes
Geoff Hayes on 29 Mar 2016
James - it isn't clear where in your clickFcn you are trying to access the handles structure, unless you are assuming that it will be there due to the function signature of
function clickFcn(hObject, eventdata, handles)
In the above, handles will always be an empty matrix because you are not explicitly passing it when you assign the callback as
set(gcf, ...
'WindowButtonDownFcn', @clickFcn, ...
By default, there will only be two input parameters for clickFcn: hObject and eventdata. If you want to pass a third (or fourth or fifth) parameter, you would need to modify the above to
set(gcf, ...
'WindowButtonDownFcn', {@clickFcn, param3},..
where param3 is a variable that you have defined previously. However, if you were to try and pass handles in as the third parameter, it would only be a copy of handles at the time that you assigned the callback. So if handles changes over time (due to being updated in another callback) your clickFcn will not see these changes because it is using an out-dated copy of handles.
To get around this, you can use the guidata function to get the most recent handles structure. So we will leave the callback assignment as
set(hObject, ...
'WindowButtonDownFcn', @clickFcn, ...
'WindowButtonUpFcn', @unclickFcn);
(Note that I changed gcf to hObject. These should be identical since you are doing the above in the _OpeningFcn of your GUI.) In the callback, we will use hObject to get handles
function clickFcn(hObject, eventdata)
handles = guidata(hObject);
% etc.
Try the above and see what happens!
  6 Comments
James Ang
James Ang on 21 Apr 2016
Geoff, I'm trying to pass the handles structure between 2 functions:
the first is:
function add_var1_Callback(hObject, eventdata, handles)
% hObject handle to add_var1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%set(handles.hCur, 'XData', [NaN NaN]); % <-- EDIT
%set(handles.hText, 'Position', [NaN NaN]);
%%Plotting
handles.time_sec1 = 1:size(handles.selected_file_table(:,'t'));
for i = 1:handles.count;
handles.al1(i) = ...
plot(handles.axes1, handles.time_sec1, ...
table2array(handles.selected_file_table(:,handles.selected_varlist1.String(i)))...
,'LineWidth',2);
axes(handles.axes1); hold on
end
grid(handles.axes1,'on');
handles.axes1.XMinorGrid = 'on';
handles.axes1.YMinorGrid = 'on';
hold off
set(handles.axes1,'Color',[0.87058824300766 0.921568632125854 0.980392158031464],...
'XColor',[0 0 0],'YColor',[0 0 0],'ZColor',[0 0 0]);
% axes(handles.axes1)
legend(handles.selected_varlist1.String,'Location','northoutside','Orientation','horizontal')
linkaxes([handles.axes1,handles.axes2],'x');
handles.diff_table.Data=[];
if handles.count2 == 0
cla(handles.axes2)
else
end
vertical_cursor_pana(hObject, eventdata, handles);
guidata(hObject, handles);
The second function is:
function vertical_cursor_pana(hObject, eventdata, handles)
% What does this function do?
% 1) Prepare handles for All lines plotted on all axes
% 2) Prepare text handles - same number as number of lines
% 3) Prepare axes handles
% 4) Prepare verticle line handles - same number as number of axes
% 5) Set 'WindowButtonDownFcn' and 'WindowButtonUpFcn' functions
% set(gcf, ...
% 'WindowButtonDownFcn', {@clickFcn,handles},
% 'WindowButtonUpFcn', @unclickFcn);
handles.allLines = [handles.al1 handles.al2];
% handles.allLines = findobj(gcf, 'type', 'line');
handles.hText = nan(1, length(handles.allLines));
for id = 1:length(handles.allLines)
handles.hText(id) = text(NaN, NaN, '', ...
'Parent', get(handles.allLines(id), 'Parent'), ...
'BackgroundColor', 'yellow', ...
'Color', get(handles.allLines(id), 'Color'));
end
handles.allAxes = findobj(gcf, 'Type', 'axes');
handles.hCur = nan(1, length(handles.allAxes));
for id = 1:length(handles.allAxes)
handles.hCur(id) = line([NaN NaN], ylim(handles.allAxes(id)), ... % Set y-limits for both axes
'Color', 'black', 'Parent', handles.allAxes(id));
end
% set(gcf, ...
% 'WindowButtonDownFcn', {@clickFcn, handles}, ...
% 'WindowButtonUpFcn', {@unclickFcn, handles});
handles = guidata(hObject);
I'm trying to pass handles.hCur to the first function. However, after the line
handles = guidata(hObject);
I noticed the handles.hCur object vanishes.
How can I pass the handles.hCur to the first function?
Geoff Hayes
Geoff Hayes on 22 Apr 2016
James - why would you be calling the line
handles = guidata(hObject);
when handles is already being passed in to this function?
The reason this is happening is because while the new hCur fields has been set in the handles structure it hasn't yet been saved to it using
guidata(hObject,handles);
So you are passing in an updated copy of handles (into the vertical_cursor_pana before you save the new field to this structure with the call to guidata). So when you call the
handles = guidata(hObject);
you are requesting a copy of the object at its last "saved" state i.e. what it was at the last time we called guidata(hObject,handles) which is a copy without the hCur field.

Sign in to comment.

More Answers (0)

Categories

Find more on Interactive Control and Callbacks in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!