Passing output from a ButtonDownFcn callback function
21 views (last 30 days)
Show older comments
Hello,
I am struggling with figuring out how to pass variables from a callback function (using ButtonDownFcn) to my main script.
Below is a simple example where I am trying to modify the example script from:
I simplified it below to just make the first function work and have two examples below:
- the original line (LINE A below), which doesn't pass my variable back and doesn't seem to allow me to define further output variables. Adding variables (double) to hIm also doesn't work (I guess because it is an image object?)
- the simple line (LINE B below) works to pass the output variable, but is not an option because it doesn't use the ButtonDownFcn anymore (which I need later).
clear all
close all
clc
im = imread('SENIAM_EMGEP1.jpeg');
% Gather data about the image, such as its size, and store the data in a structure that you can pass to callback functions.
sz = size(im);
myData.Units = 'pixels';
myData.MaxValue = hypot(sz(1),sz(2));
myData.Colormap = hot;
myData.ScaleFactor = 1;
% Display the image in an axes.
hIm = imshow(im);
% Specify a callback function for the ButtonDownFcn callback on the image. Pass the myData structure to the callback function. This callback function creates the line objects and starts drawing the ROIs.
hIm.ButtonDownFcn = @(~,~) startDrawing(hIm.Parent,myData); %% LINE A
myData = startDrawing(hIm.Parent,myData); %% LINE B
function myData = startDrawing(hAx,myData)
myData.test = 2;
% Create a line ROI object. Specify the initial color of the line and
% store the |myData| structure in the |UserData| property of the ROI.
h = images.roi.Line('Color',[0, 0, 0.5625],'UserData',myData);
end
I have had a similar issue with callback functions and thought it was time to seek help.
The answer provided here (https://nl.mathworks.com/matlabcentral/answers/563102-passing-a-variable-from-a-call-back-function-matlab-2020a) doesn't allow me to figure it out and I want to avoid using global variables.
Thanks for any advice.
1 Comment
Stephen23
on 11 Jun 2024
Edited: Stephen23
on 11 Jun 2024
"I am struggling with figuring out how to pass variables from a callback function (using ButtonDownFcn) to my main script."
If you want to write GUIs then you need to change how you think: call the script (much better: function) from the callback. Once you do that, then writing complex GUIs will make much more sense:
Your current approach is limited to using e.g. WAITFOR or UIWAIT, which limits how much your GUI can do.
Answers (2)
Adam Danz
on 11 Jun 2024
Callback functions do not have outputs or a clear workspace where the outputs would live. Instead, within a callback function you can store values within an object property that can be accessed outside of the callback function. If you're working with a custom app, add a private property to the app. If you're not working with app, you can store the property in an object's UserData property or use setappdata/getappdata. For example,
function startDrawing(hAx,myData)
% YOUR CODE THAT GENERATES h
h = ...
% APPEND LIST OF OBJECTS
existingLines = getappdata(hAx,'roiLines');
setappdata(hAx,'roiLine',[existingLines; h])
end
0 Comments
Steven Lord
on 11 Jun 2024
Callback functions for Handle Graphics objects don't return output arguments. [Where would it return those output arguments to? If the Handle Graphics object were created inside a function, there's no guarantee that function is still running when the callback gets executed. If another function (like another graphics object's callback) happened to be running at the time the callback returns, should it "poof" its outputs into that function's workspace? No.]
Rather than having your image object's ButtonDownFcn ignore its input arguments:
hIm.ButtonDownFcn = @(~,~) startDrawing(hIm.Parent,myData);
I'd have it accept at least the first argument (the graphics object whose callback is executing) and store whatever data you would have returned from the callback in a property of that object (or its Parent.) The UserData property for image objects is one way to do this. Then whatever needs that "output" argument can query the UserData property assuming it has access to the image object's handle. [And if it doesn't have access to the handle, is that an indication that it may not actually have "need to know" what's in the image's UserData property?]
0 Comments
See Also
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!