0

I'm trying to save brushed data to a variable on button click. I've read other questions but can't find the method to do it.

Inside a script the following code works:

t=0:0.2:25;
x=sin(t);
n=plot(t,x,'s');
brush on
pause
brushedData = find(get(n,'BrushData'));

However, calling the function selectBrush does not work:

function selectBrush()
% Create data
t=0:0.2:25;
x=sin(t);

% Create figure with points
fig=figure();
n=plot(t,x,'s');
brush on;
addBP = uicontrol(1,'Style', 'pushbutton',...
        'String', 'Get selected points index',...
        'Position',[5, 5, 200, 30],...
        'Units','pixel',...
        'Callback',@()assignin('caller','selectedPoints',get(n,'BrushData')));

% ---> Now the user should select the points and click the button 'Get
% selected points index'
waitfor(fig)

% Display index of selected points once the figure is closed
disp(selectedPoints);
end

The error message I become is

Error using selectBrush>@()assignin('caller','selectedPoints',get(n,'BrushData'))
Too many input arguments.

I've tried other things like using eval('selectedPoints=,get(n,''BrushData'')') as callback-function, using handles or defining separately a new callback function, everything without success.

How should I do it?

EDIT 1

excaza's method seems to work, but the callback function is only executed on the original value of the variable I'm redefining and not on the updated value.

With the following code,

function testcode()
% Create data
t = 0:0.2:25;
x = sin(t);

% Create figure with points
myfig = figure();
n = plot(t, x, 's');
brush on;
pointslist=[];
uicontrol('Parent', myfig, ...
          'Style', 'pushbutton',...
          'String', 'Get selected points index',...
          'Position', [5, 5, 200, 30],...
          'Units', 'pixels',...
          'Callback', {@mycallback, n, pointslist} ...
           );

% ---> Now the user should select the points and click the button 'Get
% selected points index'
waitfor(myfig)

% Display index of selected points once the figure is closed
disp(pointslist);
end

function mycallback(~, ~, mylineseries, pointslist)
% Ignore the first 2 function inputs: handle of invoking object & event
% data

assignin('caller', 'pointslist', [pointslist find(get(mylineseries,'BrushData'))])
end

if I push the button more than once before closing I'd expect having saved the points as many times as I pushed the button, not only the last button push.

Community
  • 1
  • 1
Gypaets
  • 125
  • 5
  • Callback inputs are static, every time your callback is executed it's with the values of `n` and `pointslist` as they were when you defined the callback (which makes sense, how does MATLAB know to change it?). See [share data between callbacks](http://www.mathworks.com/help/matlab/creating_guis/share-data-among-callbacks.html) for methods to store and access the data. – sco1 Jun 08 '16 at 11:06

1 Answers1

1

From the documentation, MATLAB's callbacks are always sent 2 variables by default:

  • The handle of the object whose callback is executing. Use this handle within your callback function to refer to the callback object.

  • The event data structure, which can be empty for some callbacks or contain specific information that is described in the property description for that object.

So what's happening here is that the assignin call is being passed 2 more variables than it can handle, which is why it throws the error (I'd recommend including error messages with your questions).

For an immediate fix, you can use the cell array notation mentioned in the documentation to create a local callback function:

function testcode()
% Create data
t = 0:0.2:25;
x = sin(t);

% Create figure with points
myfig = figure();
n = plot(t, x, 's');
brush on;
uicontrol('Parent', myfig, ...
          'Style', 'pushbutton',...
          'String', 'Get selected points index',...
          'Position', [5, 5, 200, 30],...
          'Units', 'pixels',...
          'Callback', {@mycallback, n} ...
           );

% ---> Now the user should select the points and click the button 'Get
% selected points index'
waitfor(myfig)

% Display index of selected points once the figure is closed
disp(selectedPoints);
end

function mycallback(~, ~, mylineseries)
% Ignore the first 2 function inputs: handle of invoking object & event
% data

assignin('caller', 'selectedPoints', get(mylineseries,'BrushData'))
end

Which should function as desired. Also note the appropriate assignin syntax, it's incorrect in your example.

sco1
  • 12,154
  • 5
  • 26
  • 48
  • It works, thanks for the nice RTFM. I'll later update the question with the error message. – Gypaets Jun 06 '16 at 15:00
  • I've edited the question with another issue: the callback function is only executed on the original value of the variable, and not the updated one. – Gypaets Jun 08 '16 at 08:42
  • @excaza This code is working fine for a single plot. But what if I have multiple plots in single figure (plotted using hold on) – The_Learner Feb 01 '20 at 10:44