How do I exactly pass function handles for MATLAB callbacks?

조회 수: 25(최근 30일)
I'm getting problems trying to use the ButtonDownFcn in a MATLAB plot. The documentation seems to be a bit contradictive in this sense, so it's hard to understand exactly what I should do. What I want to do is assign a function to lines in a plot. When the user clicks on any given line with that "ButtonDownFcn" callback function assigned, my program is meant to take both the line object and a variable called "selectionObj", copy the line object into "selectionObj" (which is a class specifically written for that), and return the new version of "selectionObj" so the user can keep selecting more lines and compose a selection set. My problem, specifically, is with passing inputs and outputs to this Handle correctly, as I'm getting insecure about how I should work with the syntax in this case.
I will attach an MWE (Minimal Working Example) below so you can reproduce the same problem I am having. My problem specifically is with this line:
set(lineInPlot{i}, 'ButtonDownFcn', @(linehandle)mouseLineSelectMWE(linehandle), 'PickableParts', 'all')
Specially at
@(linehandle)mouseLineSelectMWE(linehandle)
MATLAB documentation says that, in general, I can work with handles in the form of
hand = @(s) s.^2 + 1;
result = hand(2); % Which produces result = 5.
However, I have no means to specify a left-hand argument here in this case. If you would think of a language like C and its derivatives, usually that would mean that you have to pass pointers into the function. MATLAB's way of doing that is specifying "global" variables that can be called literally anywhere and will point to the same place in memory. Therefore, in the MWE, selectionObj is global and called in the mouseLineSelectMWE as a global.
Also, going back to the snippet @(linehandle)mouseLineSelectMWE(linehandle)", I've seen people working with these handles as @(~,~)function, @function(aRandomVariableHere), and so on and so forth. I'm not so sure, then, how exactly I will specify inputs and outputs here, especially when I need to pass that exact line into the code.
So, in the end of the day, all I really need a fix on is the (~,~)fun() part, which I'm not really understanding how it works.
MWE:
close all % Clear current plots
clear all
global selectionObj
% selectionObj = BCselectionMWE; % Creation
selectionObj = BCselection; % Creation
%% Starting the BC selection figure
fig1 = figure(1);
ax1 = axes;
hold on
% Plotting lines
for i = 1:4
lineInPlot{i} = plot3(...
rand(2,1), ...
rand(2,1), ...
rand(2,1),...
'Color',[.5 .5 .5],...
'LineWidth',1.2...
);
linehandle = lineInPlot{i}; % Perhaps this is unnecessary
set(lineInPlot{i}, 'ButtonDownFcn', @(linehandle)mouseLineSelectMWE(linehandle), 'PickableParts', 'all')
end
% Figure formatting
grid on
view([50 25]) % Initial POV ([45 30] is also good)
daspect([1 1 1]) % Constraints the data aspect ratio. The geometry won't
% be distorted as you pan around.
%% Class
%
% classdef BCselectionMWE
% %BCSELECTION Summary of this class goes here
% % Detailed explanation goes here
%
% properties (SetAccess = private)
% % Every clicked line will be, first, placed in 'kids'
% kids % ...'kids' because all the 'children' lines will be here
% end
%
% methods
% function obj = BCselection
% %BCSELECTION Construct an instance of this class
% % This class creates objects that make easier the process of
% % organising the selected child lines, their created patches,
% % and the different BC groups created
%
% % We want all properties being created as empty cell arrays.
% kids = cell(0,0);
% end
%
% function obj = addLine(obj,lineChildren)
% %ADDLINE This method adds a line to the current selection
%
% % Doing the stuff necessary if this is a line being added to
% % the selection
% % Highlighting in blue the selected line
% lineChildren.Color(3) = 1;
% % Adding the kid to the kindergarten
% obj.kids{n+1} = lineChildren;
% end
% end
% end
%% Function for callbacks
function selectionObj = mouseLineSelectMWE(lineObj,~)
%MOUSELINESELECT Passes the line object clicked to the addline command of
%the BCselection class. Important since the output can be redirected to the
%class, and not the line object itself.
% THE GLOBAL VARIABLE selectionObj MUST EXIST! selectionObj is an instance
% of the BCselection class
global selectionObj
% Adds (or removes) the line
selectionObj = selectionObj.addLine(lineObj);
% selectionObj.addLine(lineObj);
% This is necessary since the output of the class function must still point
% to the selectionObj variable
end
Current error messages are:
*Error using lineSelectionMWE>@(linehandle)mouseLineSelectMWE(linehandle)
Too many input arguments.
Error while evaluating Line ButtonDownFcn.*
EDIT:
Funny how things work exactly when you give up and ask the community. I did this and it worked exactly like I wanted, but why?
(~,~)mouseLineSelect(linehandle)
  댓글 수: 3
Alexandre Piccini
Alexandre Piccini 2019년 7월 13일
Also,
this line
set(lineInPlot{i}, 'ButtonDownFcn', @(linehandle)mouseLineSelectMWE(linehandle), 'PickableParts', 'all')
became
set(lineInPlot{i}, 'ButtonDownFcn', @(~,~)mouseLineSelect(linehandle), 'PickableParts', 'all')
in order to properly work.

댓글을 달려면 로그인하십시오.

채택된 답변

Walter Roberson
Walter Roberson 2019년 7월 14일
MATLAB automatically passes callbacks handle of the current object, and event data (typically empty or a struct, sometimes an object). You were allowing for the object handle but not for the event data.
  댓글 수: 11
Alexandre Piccini
Alexandre Piccini 2019년 7월 16일
I see Stephen. I thought what you mentioned was specific to GUIDE's implementation way-of-things (I just assumed that), so I didn't pay much attention. I'll try what you suggested.

댓글을 달려면 로그인하십시오.

추가 답변(0개)

Community Treasure Hunt

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

Start Hunting!

Translated by