Passing arguments to UIcontrol callback function - matlab

I am making an app to track my finances and I am confused as how to pass a string to a callback function in a uicontrol pushbutton object.
For instance:
classdef moneyapp < handle
methods (Access = public)
function app = moneyApp
% uicontrol object example
app.NewSymbolGLMC = uicontrol(app.FigureGLMC,...
'Style','pushbutton','Position',[300 60 200 20],...
'String','New Stock',...
'Callback', {#app.newStock,'Account Name'});
end
function newStock(src,eventData,account)
% Do something with the string, 'Account Name'
end
end
end
end
I am confused as to how to get the string, 'Account Name', to the newStock function. This is an essential part to my code and I just think my syntax is not correct; more examples of the code can be provided if needed. Any help would be greatly appreciated!

Since newStock is a method of your class, the first input must be the object itself. Because of this you need four input arguments in your function definition:
the instance, the source and event data (the default inputs), and the account name.
function newStock(obj, src, eventData, account)
As a side note, the capitalization of your constructor (moneyApp) must match the capitalization of the class (moneyapp) to be treated as a constructor.

Related

User-Defined Option Argument for Custom Function in Matlab

Thanks in advance,
I want to write a new Matlab function code with different options for sub-algorithms for two distinct steps dealing the input argument/s. An example of one solution can be illustrated by use of switch-case statement such as:
function Return = Calculator(input,option1,option2)
switch option1
case 'Algorithm1_Opt1'
sub=f_Algorithm1_Opt1(input)
case 'Algorithm2_Opt1'
sub=f_Algorithm2_Opt1(input)
end
switch option2
case 'Algorithm1_Opt2'
Return=f_Algorithm1_Opt2(sub)
case 'Algorithm2_Opt2'
Return=f_Algorithm2_Opt2(sub)
end
My question: is there a way to specify custom options structure for an user-defined function as in optimset like;
options = optimset('param1',value1,'param2',value2,...)
such as;
options = optimset('Display','iter','TolX',1e-8)
So at last, I want to call my function as;
Return_exp=Calculator(input_exp,'option1','Algorithm1_Opt1','option2','Algorithm2_Opt2')
Regards.
As others have pointed out you can use the inputParser class or varargin. The inputParser implementation is sometimes too simplistic for coding complex problems. I usually prefer using varargin in these circumstances. Below are some templates I used.
For parameter parsing in functions:
function output=myfunc(requiredArg1,requiredArg2,varargin)
%% Parse Param-Value Inputs
PARAM_NAMES={'name1','name2'};
PARAM_VALUES={value1_default,value2_default};
n=1;
N=numel(varargin);
while n<N
% Read parameter name.
if ischar(varargin{n}) && isrow(varargin{n})
tf=strcmpi(varargin{n},PARAM_NAMES);
if any(tf)
% Set parameter value.
PARAM_VALUES{tf}=varargin{n+1};
else
error('Unrecognized parameter name.');
end
else
error('Unrecognized input. Parameter name must be a string.');
end
n=n+2;
end
if n<=N
warning('An extra input argument was provided, but is ignored.');
end
%% Program
end
For parameter parsing in constructors for handle classes:
methods
function obj=ObjectName(requiredArg1,requiredArg2,varargin)
%% Set Object Properties Using Param-Value Inputs
n=1;
N=numel(varargin);
while n<N
% Read property name.
if ischar(varargin{n}) && isrow(varargin{n})
mp=findprop(obj,varargin{n});
if isempty(mp)
error('''%s'' is not a property of the %s class.',varargin{n},class(obj));
elseif strcmpi(mp.SetAccess,'public')
obj.(varargin{n})=varargin{n+1};
else
error('Denied access to set the ''%s'' property.',varargin{n});
end
n=n+2;
end
end
if n<=N
warning('An extra input argument was provided, but is ignored.');
end
%% Program
end
end
The first template can be also be used for parameter parsing in constructors for value classes by setting PARAM_NAMES=properties(obj).

uicontrol callback function too many input arguments

My goal is to get the user's input from a uicontrol text box, do operations on the input and then display the output to another text box. MATLAB gives me the error:
Error using
UnitConverter/lbs2kg
Too many input arguments.
Error in
UnitConverter>#(varargin)app.lbs2kg(varargin{:})
(line 22)
'Callback',#app.lbs2kg,'String',app.inputMass);
Error while evaluating UIControl Callback
Here is my code:
classdef UnitConverter < handle
properties
Figure % Graphics handles
DispInputMass
DispOutputMass
inputMass %Variables/Class Properties
outputMass
end
methods
function app = UnitConverter
% This is the "constructor" for the class
% It runs when an object of this class is created
app.Figure = figure('Name','Unit Converter') ;
app.DispInputMass = uicontrol('Style','edit',...
'Callback',#app.lbs2kg,'String',app.inputMass);
app.DispOutputMass = uicontrol(app.Figure,'Style','edit','Position'...
,[168 100 47 26],'String','kg');
end
function lbs2kg(app,evt)
app.inputMass = get(app.DispInputMass,'string');
app.outputMass = app.inputMass*.453;
set(app.DispOutputMass,'string',app.outputMass);
end
end
end
The callback method actually has 3 inputs - MATLAB is throwing this error because it is trying to send three inputs to your callback which is written to only accept 2. The 3 inputs are (in order): the main object (app), the object sending the event (uicontrol) and the event (matlab.ui.eventdata.ActionData).
You can change the code to the following to get it to work:
function lbs2kg(app, obj, evt)
app.inputMass = get(app.DispInputMass,'string');
app.outputMass = app.inputMass*.453;
set(app.DispOutputMass,'string',app.outputMass);
end
Additionally you can change the first line of the function to the following:
function lbs2kg(varargin)
Breakpoint the code at the first line of the callback and investigate the contents of varargin. For more help about varargin see here (http://www.mathworks.com/help/matlab/ref/varargin.html)

custom class calling function - too many input arguments

I'm learning about MATLAB classes they certainly seem different to what I'm used to. Below is an example class I'm using.
I initialise my class with the line below,
myClass = ClassTest(3);
This is fine. The issue I have is calling the RunMain function.
First call
myClass.RunMain(myClass)
I get the error message too many inputs.
Second call
myClass.RunMain(myClass, anything)
This call works. However, I find it strange I need to supply a second parameter which is never used - just seem messy. Sure I'm missing something here.
classdef ClassTest < handle
properties
myNum;
myDate = datenum(date);
end
methods
function ct = ClassTest(someNum)
ct.myNum = someNum;
end
% this function does not work when called
%function RunMain(obj)
% obj.myNum = obj.myNum * 2;
% disp(obj.myNum);
%end
% this works
function RunMain(obj, anything)
obj.myNum = obj.myNum * 2;
disp(obj.myNum);
end
end
Update
I can see when I debug that the anything parameter is exactly the same as obj even obj.myNum has changed value.
Correct syntax for calling a method where myClass is an object of the class defining the method RunMain is:
In case of function RunMain(obj) it is one of these:
myClass.RunMain()
RunMain(myClass)
In case of function RunMain(obj, anything) it is one of these:
myClass.RunMain(anything)
RunMain(myClass, anything)
You can find more details regarding syntax here:
http://de.mathworks.com/help/matlab/matlab_oop/ordinary-methods.html

Matlab slider pass value to event handler

I am new of Matlab GUI and i have the following problem.
I have declared a slider control and his properties, and i have added a listerner to the callback and to the PostSet event handler (i think that it is tecnically called event handler) as you can see below:
function [] = HandlerSlide()
%HANDLERSLIDE Summary of this function goes here
% Detailed explanation goes here
clf;
due = '2';
hSlider = uicontrol( ...
'Style','slider', ...
'Callback',#(s,e) disp(['hello ',num2str(due),' asdad']),...
'Position', [400 30 200 20] ... %[x,y, widht, height]
);
hListener = addlistener(hSlider,'Value','PostSet',#pippo);
end
function [] = pippo(s,e)
disp('ciao');
end
As you can see i have used parameter "due" in the Callback handler (the anonymous function). Now i would like to pass parameter to use in the "pippo" function without declare it as anonymous function. Is it possible?
In other words i would like to declare "hListerner" like this:
hListener = addlistener(hSlider,'Value','PostSet',#pippo{parameter1,parameter2, etc ...});
function[] = pippo(s,e, parameter1, parameter2, etc ...)
Beside how can i use in the main the value returned by "pippo"?
thank you in advance :D
Inputs in handle functions are added like that:
hListener = addlistener(hSlider,'Value','PostSet',{#pippo,parameter1,parameter2});
You have to be careful then in the function, as "parameter1" won't be the first input but the third (after source and eventdata).

MATLAB nested event notifications?

It seems MATLAB handles will not respond to more than one notification from the same source at a time. Unfortunately this is a big problem for me. Here's an example of what I'm talking about:
classdef testClass < handle
events
testevent
end
methods
function obj = testClass
obj.addlistener('testevent', #obj.respond);
end
function raise(obj)
obj.notify('testevent');
end
function respond(obj, varargin)
fprintf('Responded!\n');
obj.raise();
end
end
end
when I execute the code
c = testClass;
c.raise();
The result is
Responded!
But I really want the recursion to work, though obviously in this simple example it would recurse infinitely. Is there any way to get this behavior?
You can make the listener recursive by setting the listener handle's Recursive property to true. Listener handle properties are in the event.listener help page. You just need to specify an output argument to obj.addlistener to retrieve the handle.
Here's the code I used to make it work:
classdef testClass < handle
events
testevent
end
methods
function obj = testClass
lh = obj.addlistener('testevent', #obj.respond);
lh.Recursive = true;
end
function raise(obj)
notify(obj,'testevent');
end
function respond(obj, varargin)
fprintf('Responded!\n');
obj.raise();
end
end
end
Also note that there is a default recursion limit of 500 calls, so naively the code won't infinitely recur; use set(0, 'RecursionLimit', N) to change that. I would think setting N=inf is a bad idea.