Prev: rescaling for fmincon
Next: Minutes past Midnight
From: JoeyB on 28 Jul 2010 17:01 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 3 Aug 2010 11:01 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 3 Aug 2010 13:21 "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 4 Aug 2010 17:36 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 5 Aug 2010 08:06
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. |