shashashamti2008
shashashamti2008

Reputation: 2327

MATLAB addlistener with additional arguments in a GUI

I am writing a MATLAB GUI which has an axes to show an image using a push button. I also use impixelinfoval to show the pixel coordinates of the location of the mouse as follows:

h = imshow('hestain.png', 'Parent', handles.axes1);
hp = impixelinfoval(gcf, h);

I can successfully add a listener to the handle of the impixelinfoval with no argument passed to the callback function by:

addlistener(hp, 'String', 'PostSet', @mycallback) % Works

However, I am trying to pass two arguments to the callback function as follows and I have not been successful to pass them to the function. I need handles to store a variable calculated in the callback function as well as hObject to be able to execute guidata(hObject, handles) so that I have access to the new variable in the entire GUI.

addlistener(hp, 'String', 'PostSet', @mycallback1(hObject, handles))  % Does not work

Could someone kindly help me with this problem?

The following is the entire MWE to test this issue:

function varargout = untitled(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @untitled_OpeningFcn, ...
                   'gui_OutputFcn',  @untitled_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end


function untitled_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);

function varargout = untitled_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
h = imshow('hestain.png', 'Parent', handles.axes1);
hp = impixelinfoval(gcf, h);
addlistener(hp, 'String', 'PostSet', @mycallback) % Works
% addlistener(hp, 'String', 'PostSet', @mycallback1(hObject, handles)) % Does not work. I would like to pass both hObject and handles to mycallback function.


function mycallback(src, evt)
disp(evt.AffectedObject.String)

function mycallback1(src, evt, hObject, handles)
disp(evt.AffectedObject.String)
% Create a variable and store it in the handles
handles.pixelcoord = evt.AffectedObject.String;
% Update handles
guidata(hObject, handles)

Upvotes: 0

Views: 1006

Answers (2)

Michael
Michael

Reputation: 21

I just ran into your post, since I am facing a similar problem. I am programming an instrument GUI, the instrument is defined as an object that can send notifiers. I want to have the GUI updated with the information on that particular notifier event. To put a long story short, what finally worked for me is the following:

  1. Definition of listener in GUI opening function: addlistener(handles.Stage, 'PID_changed', @(hObject, eventdata)updatePID_Callback(hObject, eventdata, handles));

  2. Definition of Callback function (regular function, not an object method): function updatePID_Callback(~,~,handles) ... (updating GUI, e.g., set(handles.editbox1, 'string', num2str(someValue)) .. end

That's all I can say, hope it helps ..

Upvotes: 2

matlabgui
matlabgui

Reputation: 5672

A listener will by default want to pass 2 default parameters as per your example that works:

addlistener(hp, 'String', 'PostSet', @mycallback() )

You should notice in your function you have 2 inputs:

function mycallback ( src, event )
   ...
end

What your trying to do is to either:

  1. Add 2 extra arguments
  2. Replace the 2 default arguments with a different 2.

You do this my controlling the callback function:

addlistener(hp, 'String', 'PostSet', @(src,evt)mycallback1(src, evt, hObject, handles))

or

addlistener(hp, 'String', 'PostSet', @(src,evt)mycallback1(hObject, handles))

The above lines are capturing the default callbacks src and evt and the first one is passing them to your callback with your additional variables, the other is not.

edit My answer was focusing on how to call a listener, I dont have the imageprocessing toolbox so cant create a code which uses the impixelinfoval function.

Since your code on its own doesn't run I have created a small example below which shows you how to add listeners which react when a (in this case axes title) string property has been set, it runs on its own so you should be able to run it and see how it works.

function untitled
 %%
 % create a figure
  h = figure;
  % create an axes
  ax = axes ( 'parent', h );
  % create a variable which we will plot
  p = peaks(50);
  % plot the variable
  imagesc ( p, 'parent', ax );
  % createa some initial title, x and y lables
  t = title ( ax, 'Title' );
  x = xlabel ( ax, 'X Label' );
  y = ylabel ( ax, 'Y Label' );
  %  add a callback to run when the mouse moves.
  h.WindowButtonMotionFcn = @(a,b)moveMouse (ax, t);
  % add listeners which are triggered after the title has been set
  %  this listener passes the standard callbacks and some extras, namely
  %    the handles of the title and the y label
  addlistener ( t, 'String', 'PostSet', @(h,evt)mycallback1(h,evt,t,y) )
  % this listener only passes the handle to the title and the x label
  addlistener ( t, 'String', 'PostSet', @(h,evt)mycallback(t,x) )
end
function moveMouse ( ax, t )
  % update the title of the axes for
  t.String = sprintf ( 'current point %.1f,%.1f', ax.CurrentPoint(1,1:2) );
end
function mycallback ( t, x )
  % udpate the x label string
  x.String = sprintf ( 'X Label -> title value: %s', t.String );
end
function mycallback1 ( h, event, t, y )
  % update the y label string
  y.String = sprintf ( 'Y Label -> title value: %s', t.String );
end

This GUI is created from code (not guide).

This works by updating the axes title when the mouse moves to provide the current point. I have added 2 listeners which update the X and Y label strings after the title has been set.

From knowing how to add listeners you should be able to use this theory in your own code, and that might highlight what any remaining errors you have are.

your error message in comment below

addlistener(hp, 'String', 'PostSet', @(source, event, hObject, handles)myImageMagnifier3(source, event, hObject, handles))

I suspect this should be:

addlistener(hp, 'String', 'PostSet', @(source, event)myImageMagnifier3(source, event, hObject, handles))

like in my original example.

Upvotes: -1

Related Questions