'WindowButtonDownFcn' cant detect handles data from other callbacks

7 views (last 30 days)
James Ang
James Ang on 28 Mar 2016
Commented: Geoff Hayes on 22 Apr 2016
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));
% 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
set(gcf, 'WindowButtonMotionFcn', @dragFcn)
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));
set(hText(idx), 'Position', [NaN NaN]);
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!
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
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)

Community Treasure Hunt

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

Start Hunting!