From: JoeyB on
Ok, Long time ML coder, first time ML OO coder. After about 3 hours of
messing around with Matlab's OO syntax, I've discovered that any
callback function being assigned as an event listener must be declared
as a static method? Where in the doc's does it talk about this? Why?
Here's the Matlab help example classes:

The Event Creator:

classdef ToggleButton < handle
properties
State = false
end
events
ToggledState
end
methods
...
function OnStateChange(obj,newState)
% Call this method to check for state change
if newState ~= obj.State
obj.State = newState;
notify(obj,'ToggledState'); % Broadcast notice of event
end
end
end
end

And the Event Consumer:

classdef RespondToToggle < handle
methods
function obj = RespondToToggle(toggle_button_obj)

addlistener(toggle_button_obj,'ToggledState',@RespondToToggle.handleEvnt);
end
end
methods (Static)
function handleEvnt(src,evtdata)
disp(nargin)
if src.State
disp('ToggledState is true') % Respond to true
ToggleState here
else
disp('ToggledState is false') % Respond to false
ToggleState here
end
end
end
end


Then, by typing the following on the command line:

>> clear all
>> tb = ToggleButton;
>> rtt = RespondToToggle(tb)
>> tb.OnStateChage(true)

You get:

ToggledState is true

Great. No problem. BUT...if you change the callback's method attribute
in RespondToToggle so that it's not static:
....

methods
function handleEvnt(src,evtdata)
disp(nargin)
if src.State
disp('ToggledState is true') % Respond to true
ToggleState here
else
disp('ToggledState is false') % Respond to false
ToggleState here
end
end
end
....

You get:

tb.OnStateChange(true)
Warning: Error occurred while executing callback:
Undefined function or method 'RespondToToggle.handleEvnt'
for input arguments of type 'ToggleButton'.

What doc did I miss where this is described? Why do I need to do
this? Also, don't believe that 'clear' will reset you workspace by
believing this warning:
What's with these nebulous warnings? The doc seems to go over the same
trivial description of use about 15 different ways but doesn't
describe what you need
to know to make this stuff work.

Warning: The class file for 'RespondToToggle' has been
changed; but the change cannot be applied because objects
based on the old class file still exist. If you use those
objects, you might get unexpected results. You can use
the 'clear' command to remove those objects. See 'help
clear' for information on how to remove those objects.

You need to type 'clear all' for the workspace to recognize your
changes.

Just needed to vent. Any comments welcome.

From: per isakson on
JoeyB <joseph.burgel(a)gm.com> wrote in message <b48aa8df-ed2d-4a6a-8f06-d68846ffa013(a)z10g2000yqb.googlegroups.com>...
> Ok, Long time ML coder, first time ML OO coder. After about 3 hours of
> messing around with Matlab's OO syntax, I've discovered that any
> callback function being assigned as an event listener must be declared
> as a static method? Where in the doc's does it talk about this? Why?
> Here's the Matlab help example classes:
>
> The Event Creator:
>
> classdef ToggleButton < handle
> properties
> State = false
> end
> events
> ToggledState
> end
> methods
> ...
> function OnStateChange(obj,newState)
> % Call this method to check for state change
> if newState ~= obj.State
> obj.State = newState;
> notify(obj,'ToggledState'); % Broadcast notice of event
> end
> end
> end
> end
>
> And the Event Consumer:
>
> classdef RespondToToggle < handle
> methods
> function obj = RespondToToggle(toggle_button_obj)
>
> addlistener(toggle_button_obj,'ToggledState',@RespondToToggle.handleEvnt);
> end
> end
> methods (Static)
> function handleEvnt(src,evtdata)
> disp(nargin)
> if src.State
> disp('ToggledState is true') % Respond to true
> ToggleState here
> else
> disp('ToggledState is false') % Respond to false
> ToggleState here
> end
> end
> end
> end
>
>
> Then, by typing the following on the command line:
>
> >> clear all
> >> tb = ToggleButton;
> >> rtt = RespondToToggle(tb)
> >> tb.OnStateChage(true)
>
> You get:
>
> ToggledState is true
>
> Great. No problem. BUT...if you change the callback's method attribute
> in RespondToToggle so that it's not static:
> ...
>
> methods
> function handleEvnt(src,evtdata)
> disp(nargin)
> if src.State
> disp('ToggledState is true') % Respond to true
> ToggleState here
> else
> disp('ToggledState is false') % Respond to false
> ToggleState here
> end
> end
> end
> ...
>
> You get:
>
> tb.OnStateChange(true)
> Warning: Error occurred while executing callback:
> Undefined function or method 'RespondToToggle.handleEvnt'
> for input arguments of type 'ToggleButton'.
>
> What doc did I miss where this is described? Why do I need to do
> this? Also, don't believe that 'clear' will reset you workspace by
> believing this warning:
> What's with these nebulous warnings? The doc seems to go over the same
> trivial description of use about 15 different ways but doesn't
> describe what you need
> to know to make this stuff work.
>
> Warning: The class file for 'RespondToToggle' has been
> changed; but the change cannot be applied because objects
> based on the old class file still exist. If you use those
> objects, you might get unexpected results. You can use
> the 'clear' command to remove those objects. See 'help
> clear' for information on how to remove those objects.
>
> You need to type 'clear all' for the workspace to recognize your
> changes.
>
> Just needed to vent. Any comments welcome.

I made may first serious experiments with event the other day. Here is a line from one of the examples in the Matlab OOP book.

addlistener( this.FcnObject, 'Lm', ...
'PostSet', @( src, evnt ) listenLm( this, src, evnt ) );

listenLm is an ordinary method (-not static). My "guess" is that the callback is invoked in the base workspace. Thus, your example works with the static method. In "my" case the "scope of the object" is stored in the anynonous function.

IMO this matter could have been better described in the documentation.

/ per
From: Steven_Lord on


"per isakson" <poi.nospam(a)bimDOTkthDOT.se> wrote in message
news:i39avj$hk9$1(a)fred.mathworks.com...
> JoeyB <joseph.burgel(a)gm.com> wrote in message
> <b48aa8df-ed2d-4a6a-8f06-d68846ffa013(a)z10g2000yqb.googlegroups.com>...
>> Ok, Long time ML coder, first time ML OO coder. After about 3 hours of
>> messing around with Matlab's OO syntax, I've discovered that any
>> callback function being assigned as an event listener must be declared
>> as a static method? Where in the doc's does it talk about this? Why?
>> Here's the Matlab help example classes:
>>
>> The Event Creator:
>>
>> classdef ToggleButton < handle
>> properties
>> State = false
>> end
>> events
>> ToggledState
>> end
>> methods
>> ...
>> function OnStateChange(obj,newState)
>> % Call this method to check for state change
>> if newState ~= obj.State
>> obj.State = newState;
>> notify(obj,'ToggledState'); % Broadcast notice of event
>> end
>> end
>> end
>> end
>>
>> And the Event Consumer:
>>
>> classdef RespondToToggle < handle
>> methods
>> function obj = RespondToToggle(toggle_button_obj)
>>
>> addlistener(toggle_button_obj,'ToggledState',@RespondToToggle.handleEvnt);

What does the documentation say the callback should expect as inputs?

http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brb6gnc.html#brqorok

So RespondToToggle.handleEvnt receives a ToggleButton as its first input and
an event.EventData object as its second input. If handleEvnt is a static
method in the RespondToToggle class, that's fine -- you can call a static
method without an instance of the object as one of the inputs. If it was
not a static method, then handleEvnt MUST receive a RespondToToggle object
as one of its inputs in order for the handleEvnt method of the
RespondToToggle class to be invoked. Since it doesn't in this scenario,
MATLAB checks in several places to see if it can resolve what handleEvnt
could be:

http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_prog/f7-58170.html#bresuvu-3

and when it can't determine what handleEvnt could be, it throws an error.

>> You get:
>>
>> tb.OnStateChange(true)
>> Warning: Error occurred while executing callback:
>> Undefined function or method 'RespondToToggle.handleEvnt'
>> for input arguments of type 'ToggleButton'.

Yes, this error message.

>> What doc did I miss where this is described? Why do I need to do
>> this? Also, don't believe that 'clear' will reset you workspace by
>> believing this warning:
>> What's with these nebulous warnings? The doc seems to go over the same
>> trivial description of use about 15 different ways but doesn't
>> describe what you need
>> to know to make this stuff work.
>>
>> Warning: The class file for 'RespondToToggle' has been
>> changed; but the change cannot be applied because objects
>> based on the old class file still exist. If you use those
>> objects, you might get unexpected results. You can use
>> the 'clear' command to remove those objects. See 'help
>> clear' for information on how to remove those objects.

If there is an instance of an object when you try to change the class
definition, MATLAB will not update the class definition in memory to reflect
the changes. If it did, the class definition could become incompatible with
the already existing instance of the object, and that would be a Bad Thing.
This warning is telling you that you're in this situation, and that if you
really want the changes to be recognized you should clear the existing
instances.

To use an analogy (albeit not a great one), suppose you've bake a cake.
It's a very good cake, and someone asks you for the recipe. If you haven't
changed the recipe since you baked the cake, "the recipe" is unambiguous.
But if you've changed the recipe since you baked the cake, then "the recipe"
could be referring to the recipe you used to bake the cake or the recipe
with whatever changes/improvements you've added based on how the cake came
out this time. If you felt that the cake could use some extra flavor and
modified the recipe to include walnuts (for example) then giving the person
who asked for the recipe the with-walnuts version when they can taste the
cake and don't taste any walnuts could confuse them.

[I'm glad I just ate lunch :]

>> You need to type 'clear all' for the workspace to recognize your
>> changes.
>>
>> Just needed to vent. Any comments welcome.
>
> I made may first serious experiments with event the other day. Here is a
> line from one of the examples in the Matlab OOP book.
> addlistener( this.FcnObject, 'Lm', ...
> 'PostSet', @( src, evnt ) listenLm( this, src, evnt ) );
>
> listenLm is an ordinary method (-not static). My "guess" is that the
> callback is invoked in the base workspace. Thus, your example works with
> the static method. In "my" case the "scope of the object" is stored in the
> anynonous function.

If you're referring to the example in this section of the documentation:

http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/bq8bnrm.html#brc1wp2

The reason this works is because listenLm is being called with an object of
class fcnview as its first input, where listenLm is a method of the class
fcnview. To do the equivalent of this with the OP's example, they would
need to have handleEvnt accept a RespondToToggle object as its first input,
something like:

% assume RTTobj is a RespondToToggle object
addlistener(toggle_button_obj,'ToggledState',@(h, event) handleEvnt(RTTobj,
h, event));

> IMO this matter could have been better described in the documentation.

I'll ask the documentation staff to review this thread for ideas on how to
improve this section of the documentation.

--
Steve Lord
slord(a)mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
To contact Technical Support use the Contact Us link on
http://www.mathworks.com

From: JoeyB on
Thanks for the comments. I found these few lines in the help doc
solved a lot of problems:

* addlistener(eventObject,'EventName',@functionName) — for an
ordinary function.
* addlistener(eventObject,'EventName',@Obj.methodName) — for a
method of Obj.
* addlistener(eventObject,'EventName',@ClassName.methodName) —
for a static method of the class ClassName.

When I switched my syntax for declaring the addlistener to the
'@Obj.methodName' form,(row two), I no longer needed to have my
listener ftn
declared static. So I'm good. I can declare methods of objects as
handlers. What's messing me up is the syntax for ftn handles. Is it
fully
written up somewhere? There seems to be several ways to do it (not to
mention inline aproaches like ,@(h, event) handleEvnt(RTTobj,h,
event));

New Problem:

My next effort. Now, I'd like to add a listener to an object that has
events defined but I want the handler function to simply be a function
defined in a .m file.
NOT a classes' member function. Is this possible? For example:

function Mfile() % Top function in a .m file

cls AClassWithEvents(); %This class declares 'EventName' as an event
addlistener(cls,'EventName',@AnotherFtnInAnMfile);

function AnotherFtnInAnMfile(varargin) %--I'd like this function to be
called when 'EventName' is fired from AClassWithEvents

Is this possible? Doesn't seem to be. I can fire the event but
AnotherFtnInAnMfile is never called.

Any help is appreciated.
From: JoeyB on
Just a comment. These function signatures that have different numbers
of arguments depending on context is very confusing. Is this explained
somewhere? I've already found the comment that ML object methods don't
implicitly have a reference to 'this' (the object) but I'd like to see
more examples on how to deal with this. For example:
addlistener(toggle_button_obj,'ToggledState',@(h, event)
handleEvnt(RTTobj,h, event));
Using an inline ftn handle to translate the method signature from
(RTTobj,h,event) to (h,event) ?? I'd like to know more about why when
and where I need to do such things.

 |  Next  |  Last
Pages: 1 2
Prev: rescaling for fmincon
Next: Minutes past Midnight