- Undocumented Matlab - https://undocumentedmatlab.com -

UDD Events and Listeners

Posted By Yair Altman On March 16, 2011 | 32 Comments

Donn Shull continues his exploration of the undocumented UDD mechanism, today discussing the important and extremely useful topic of UDD events

The UDD event model

The UDD event model is very similar to the MCOS event model. There is an excellent discussion [1] of the MCOS event model in Matlab’s official documentation. Most of the MCOS information also applies to UDD if you make the following substitutions:

MCOS Event Model UDD Event Model
notify send
event.EventData handle.EventData
events block schema.event
event.listener handle.listener
PreGet, PreSet PropertyPreGet, PropertPreSet
PostGet, PostSet PropertyPostGet, PropertyPostSet

Event handler functions

To begin the UDD event model discussion we will start at the end, with the event handler. The event handler function requires at least two input arguments: the source object which triggered the event, and an object of type handle.EventData or a subclass of handle.EventData.
To demonstrate how this works, let’s write a simple event handler function. This event handler will display the class of the source event and the class of the event data:

function displayEventInfo(source, eventData)
%DISPLAYEVENTINFO display the classes of source, data objects
%
%   DISPLAYEVENTINFO(SOURCE, EVENTDATA) returns the classes
%   of the source object and the event data object
%
%   INPUTS:
%       SOURCE    : the event source
%       EVENTDATA : the event data
  if ~isempty(source)
    fprintf(1, 'The source object class is: %s',class(source));
  end
  if ~isempty(eventData)
    fprintf(1, 'The event data class is: %s',class(eventData));
  end
end

Creating a listener

In the section on Creating a Simple UDD Class [2] we used schema.event in our simple.object class definition file to create a simpleEvent event. We now create an instance of simple.object, then use handle.listener to wait (“listen”) for the simpleEvent event to occur and call the displayEventInfo event handler function:

a = simple.object('a', 1);
hListener = handle.listener(a,'simpleEvent',@displayEventInfo);
setappdata(a, 'listeners', hListener);

Important: The hListener handle must remain stored somewhere in Matlab memory, or the listener will not be used. For this reason, it is good practice to attach the listener handle to the listened object, using the setappdata function, as was done above. The listener will then be alive for exactly as long as its target object is alive.

Creating an EventData object

Next, create the handle.EventData object. The handle.EventData object constructor requires two arguments: an instance of the events source object, and the name of the event:

evtData = handle.EventData(a, 'simpleEvent')

Generating an event

The last step is actually triggering an event. This is done by issuing the send command for the specified object, event name and event data:

>> a.send('simpleEvent', evtData)
The source object class is: simple.object
The event data class is: handle.EventData

If there is other information that you wish to pass to the callback function you can create a subclass of the handle.EventData. Add properties to hold your additional information and use your subclass as the second argument of the send method.

Builtin UDD events

The builtin handle package has six event data classes which are subclasses of the base handle.EventData class. Each of these classes is paired with specific UDD events that Matlab generates. Actions that trigger these events include creating/destroying an object, adding/removing objects from a hierarchy, and getting/setting property values. The following table lists the event names and handle.*EventData data types returned for these events:

event data type event trigger
handle.ClassEventData ClassInstanceCreated
handle.EventData ObjectBeingDestroyed
handle.ChildEventData ObjectChildAdded, ObjectChildRemoved
handle.ParentEventData ObjectParentChanged
handle.PropertyEventData PropertyPreGet, PropertyPostGet
handle.PropertySetEventData PropertyPreSet, PropertyPostSet

As an example of some of these events let’s look at a question [3] recently asked on the CSSM newsgroup. The basic idea is that we want to monitor an axis, automatically make any added lines to be green in color, and prevent patches from being added.
The solution is to monitor the ObjectChildAdded event for an axis. We will write an event handler which checks the handle.ChildEventData to see what type of child was added. In the case of lines we will set their color to green; patch objects will be deleted from the axis. Here is our event handler function:

function modifyAxesChildren(~, eventData)
%MODIFYAXESCHILDREN monitor and axis and modify added children
%
%   MODIFYAXESCHILDREN(SOURCE,EVENTDATA) is an event handler to
%   change newly-added lines to green and remove added patches
%
%   INPUTS:
%       EVENTDATA : handle.ChildEventData object
   switch eventData.Child.classhandle.Name
      case 'line'
         eventData.Child.set('Color', 'green');
         disp('Color changed to green.')
      case 'patch'
         eventData.Child.delete;
         disp('Patch removed.')
   end
end

Next create an axis, and a listener which is triggered when children are added:

% create a new axes and get its handle
a = hg.axes;
% create the listener
listen = handle.listener(a, 'ObjectChildAdded', @modifyAxesChildren);
% add a line
>> hg.line;
Color changed to green.
% try to add a patch
>> hg.patch;
Patch removed.

Removing a child with either the delete or the disconnect method generates an ObjectChildRemoved event. The delete method also generates the ObjectBeingDestroyed event. Changing a child’s parent with the up method generates an ObjectParentChanged event.
Reading an object’s properties with either dot notation or with the get method generates PropertyPreGet and PropertyPostGet events.
Changing the value of a property generates the PropertyPreSet and PropertyPostSet events. As we saw in the section on UDD properties [4], when the AbortSet access flag is ‘on’, property set events are only generated when a set operation actually changes the value of the property (as opposed to leaving it unchanged).
Note that the handle.listener syntax is slightly different for property events:

hProp = findprop(a, 'Value');
hListener = handle.listener(a,hProp,'PropertyPreGet',@displayEventInfo);

Java events

The final specialized event data object in the handle package is handle.JavaEventData. In Matlab, Java classes are not UDD classes, but each Java instance can have a UDD peer. The peer is created using the handle function. The Java peers are created in either UDD’s javahandle package or the javahandle_withcallbacks package. As their names imply, the latter enables listening to Java-triggered events using a Matlab callback.
To illustrate how this works we will create a Java Swing JFrame and listen for MouseClicked events:

% Create the Java Frame
javaFrame = javax.swing.JFrame;
javaFrame.setSize(200, 200);
javaFrame.show;
% Create a UDD peer for the new JFrame (two alternatives)
javaFramePeer = javaFrame.handle('CallbackProperties');  % alternative #1
javaFramePeer = handle(javaFrame, 'CallbackProperties');  % alternative #2
% Create the a listener for the Java MouseClicked event
listen = handle.listener(javaFramePeer, 'MouseClicked', @displayEventInfo);

a simple Java Swing JFrame
a simple Java Swing JFrame

When we click on the JFrame, our UDD peer triggers the callback:

The source object class is: javahandle_withcallbacks.javax.swing.JFrame
The event data class is: handle.JavaEventData

Since we created our peer in the javahandle_withcallbacks package, it is not necessary to create a listener using handle.listener. If we place our callback function handle in the MouseClickedCallback property it will be executed whenever the MouseClicked event is triggered. Such *Callback properties are automatically generated by Matlab when it creates the UDD peer (details [5]).

clear listen
javaFramePeer.MouseClickedCallback = @displayEventInfo

This will work the same as before without the need to create and maintain a handle.listener object. If we had created our UDD peer in the javahandle package rather than javahandle_withcallbacks, we would not have the convenience of the MouseClickedCallback property, but we could still use the handle.listener mechanism to monitor events.

Creating callback properties for custom UDD classes

It is easy to add callback properties to user created UDD objects. The technique involves embedding a handle.listener object in the UDD object. To illustrate this, we add a SimpleEventCallback property to our simple.object, then use a SimpleEventListener property to hold our embedded handle.listener. Add the following to simple.object‘s schema.m definition file:

   % Property to hold our callback handle
   prop = schema.prop(simpleClass, 'SimpleEventCallback', 'MATLAB callback');
   prop.setFunction = @setValue;
   % hidden property to hold the listener for our callback
   prop = schema.prop(simpleClass, 'SimpleEventListener', 'handle');
   prop.Visible = 'off';
end
function propVal = setValue(self, value)
   %SETVALUE function to transfer function handle from callback property to listener
   self.SimpleEventListener.Callback = value;
   propVal = value;
end

Next we add the following to our simple.object constructor file:

% set the hidden listener property to a handle.listener
simpleObject.SimpleEventListener = handle.listener(simpleObject, 'simpleEvent', []);

Now if we set the SimpleObjectCallback property to a function handle, the handle is transferred to the embedded handle.listener Callback property. When a simpleEvent event is generated, our SimpleEventCallback function will be executed.
This series will conclude next week with a look at the special relationship between UDD and Java.

Categories: Guest bloggers, Listeners, Medium risk of breaking in future versions, Stock Matlab function, Undocumented feature


32 Comments (Open | Close)

32 Comments To "UDD Events and Listeners"

#1 Comment By Anubhav Jain On July 18, 2011 @ 03:18

I would like to know if it is possible to listen to events that happen when one drops a block or a subsystem from the Model library to the editor and when one changes the dialog parameters of a block. Furthermore, if such an event can be listened, what type of event would it be?

#2 Comment By Donn Shull On July 18, 2011 @ 12:28

Anubhav – This is actually a very complex topic and an entire book could probably be written about it. When Simulink is installed two additional UDD packages are added to MATLAB. The first package is ‘DAStudio’ and as of R2011a it contains over 100 classes. The second package is Simulink and as of R2011a it contains over 250 classes. A Simulink block diagram is a UDD hierarchy similar to a handle graphics diagram. The top is Simulink.Root with Simulink.BlockDiagram objects as children of this root. You can obtain the UDD object for any Simulink handle with the command:

 
uddObj = get_param(simHandle, 'UDDObject');

So for example to obtain the handle for the current blockdiagram you could use:

 
blkObj = get_param(bdroot, 'UDDObject');

You can then use the the Child events described above to monitor for things added to the top level diagram. Subsystems would have to be handled seperately.

Monitoring parameter changes is a complex matter for example with a gain block you can use:

 
gainObj = get_param(gcb, 'UDDObject');

where gcb returns the currently selected block. Then

 
gainObj.Gain = 10;

Will generate the Property events described above. Unfortunately changes to Gain made with either a set_param or through the Gain blocks dialog will not generate those events. One thing you can play around with if you have too much time on your hands is:

 
toolRoot = DAStudio.ToolRoot;
dialogs = toolRoot.getOpenDialogs;

This will return a DAStudio.Dialog array of objects for any open Simulink Dialogs. With that and DAStudio.imDialog there are a number of ways to manipulate Simulink Dialogs. You would need to study the code in the simulink toolbox and the shared dastudio toolbox.

Donn

#3 Comment By Anubhav Jain On July 18, 2011 @ 23:24

Hi Donn,
I really appreciate your reply on this . I am very thankful to you.. I am getting the list of events by using get_param(gcb,’UDDObject’) command.I am unable to get the drop event i.e. the event which is generated upon dropping a block from simulink library to simulink editor window..

Also I am able to listen to only namechangeevent .I am facing problems with connection event as the listeners are not getting triggered . Can you please elaborate upon the other events like Assertion , SelectionChangeEvent so that I can work upon them . Can I get the utility of all the events being listed by UDDObject command . I would be very greatful to you….

#4 Comment By Donn Shull On July 19, 2011 @ 11:06

@Anubhav – Unfortunately I do not have a reference for the various events for each of the classes in the Simulink package. They are all “Undocumented” after all. The best way to learn about these events is a combination of guesswork, studying code supplied by The MathWorks, and experiment. As an example ‘SelectionChangedEvent’ has an obvious name and is used in about 4 MathWorks files. Experiment shows that it is triggered when a mouse clicks on a block that had not previously been selected in the block diagram the listener is attached to. Unfortunately expirement also shows that while adding a new block to the diagram changes the selected block that action does not generate a SelectionChangeEvent.

I also have a guess as to why set_param and get_param do not generate events while direct manipulation of the Object parameters does. There is a Simulink Engine whichdoes the work of running a block diagram. Since you can use MATLAB and the set_param and get_param commands while a simulation is running it is reasonable to assume that the Simulink Engine runs in its own thread and it the engine may not generate or perhaps pass events back to the MATLAB thread. About a decade ago National Instruments filed a patent infringment lawsuit against The MathWorks regarding intelectual property relating to interacting with block diagrams. At the conclusion some functionality was removed from MATLAB / Simulink interaction. For example the Dials and Gauges blockset was discontinued and replaced with the Gauges blockset in order to comply with the court ruling.

Good Luck with your work,

Donn

#5 Comment By Anubhav Jain On July 19, 2011 @ 23:45

Hi Donn,
Thanks a lot for your co-ordination… I am working upon all events by trial and error method.. I am able to register a few .. Just a last question ..

Is there any possible way to register a drop event i.e. the event which is generated upon dropping a block from simulink library to simulink editor window.. If you can please help me out with this it would really solve my problem……….Just a last one …

#6 Comment By Donn Shull On July 20, 2011 @ 11:01

@Anubhav – I do not know a way of directly working with the Simulonk editor in the way that you have asked. You can probably emulate the behaviour you are seeking in the following way. You will need persistent storage for an array of handle.listener objects. Your callback function will need access to this array. The first listener in your array wil be something like:

 
 hListener(1) = handle.listener(slroot, 'ObjectChildAdded', @myHandler);

The myHandler function will need to add a listener to the array whenever a Simulink.BlockDiagram is added as a child to slroot (note slroot returns the Simulink.Root object which is a singleton.) The added listeners will need to monitor the Simulink.BlockDiagram objects in a similar way using the ‘ObjectChildAdded’ event. If the object being added to a block diagram is a Simulink.SubSystem then you will need to add annother listener to monitor the SubSystem for ‘ObjectChildAdded’ events. You will probably be able to do this all with one event handler which contains a switch statement to determine the action you wish to take depending on which child was added. Some final thoughts are that you may want to develop a system for keeping track of the listeners so you can remove unneeded ones when models are closed or subsystems are deleted from a model. Also when opening existing models you will need to build up a set of listeners for the subsystems that is contains. In that case you can use:

 
find(get_param(addedModelName, 'UDDObject'), '-isa', 'Simulink.SubSystem');

to identify the subsystems that it contains and add listeners for them.

Best Regards,

Donn

#7 Comment By Tarun Jhamnani On July 25, 2011 @ 22:45

Hi Donn,

The article is really helpful.glad to finally get some insight into UDD classes.Its all new to me and sounds very interesting to play around. I have few doubts here,
Is it possible to get the handle of Jframe simulink window and add new events for the same?and how to do that?
If not ,atleast can we have handle of Jframe simulink window to modify the default window looks.

#8 Comment By Donn Shull On July 26, 2011 @ 11:21

Tarun – I don’t think I will be able to help you with this. I believe that the Simulink editor is a “native” application rather than a java application. If you use the following command:

 
windowList = com.mathworks.mwswing.desk.DTWindowRegistry.getInstance;

You will find in the list that Simulink windows are of type:

 
com.mathworks.mde.desk.MLNativeWindow

There are a small number of java methods for these objects and no events as far as I can tell.

Donn

#9 Comment By Tarun Jhamnani On October 30, 2011 @ 22:37

Hi Donn,
I was able to listen to the simulink events.When i used same for statechart i was not able to trace events such as object child added etc.Using the properties of chart block i was able to find callback for copy,move etc but not as an event.I wish to know is it possible to register listener foe statechart and its block.If yes, how?
Thanks in advance.

#10 Pingback By Extending a Java class with UDD | Undocumented Matlab On March 29, 2012 @ 07:42

[…] During the series on UDD, we have mentioned the connection between UDD and Java. In UDD Events and Listeners we described how in Matlab, each Java object can have a UDD companion […]

#11 Comment By Bluesmaster On March 17, 2013 @ 03:42

Dear Yair,

is there a reason, why some properties can be listened to and some not?
eg:

 
 h = handle( gcf );
 l = handle.listener( h, findprop( h , 'CurrentObject') ,  'PropertyPostSet' , @(~,~) disp('changed'));

is not working while:

 
 h = handle( gca );
 l = handle.listener( h, findprop( h , 'XLim') ,  'PropertyPostSet' , @(~,~) disp('changed'))

will.

CurrentPoint, CurrentObj are very important to me, but I do not want to use mouse-click-events. Because I am programming a module that should be independent. As always: Thanks a lot

Bluesmaster

#12 Comment By Yair Altman On March 17, 2013 @ 03:46

@Bluesmaster – I assume that the reason is that CurrentObject is a dependent rather than a regular property. As such it is computed on-the-fly whenever you retrieve it, and so there is no place where Matlab can place a listener and know that it has changed. In fact, it may change multiple times before you retrieve it again and Matlab won’t know this because nobody asked to retrieve the latest value.

#13 Comment By Bluesmaster On March 17, 2013 @ 04:46

that sounds reasonably, the interessting question would be:
what does it depend on? Or can it be listened somewhere else?

But I guess i know the answer 😉

#14 Comment By Bluesmaster On March 20, 2013 @ 00:23

just a small update: CurrentObject seems not to be dependent, as it can be set by the user.

Anyway for anyone whos interessted, I suggest the following workaround in order to listen to the CurrentObject:

– creating a listener for new figures ( l = handle.listener( 0 , ‘ObjectChildAdded’, @myHandler); )
– adding a clicklistener to all new figures ( handle.listener( curFig ,’WindowButtonDownEvent’, @myClickhandler )
– creating a timer with small start delay that calls the method that needs to know the currentObject
– perform gco

Timer is needed, because the clicklistener has higher priority than the update of the currentObject

best regards

Bluesmaster

#15 Pingback By Continuous slider callback | Undocumented Matlab On October 24, 2013 @ 22:46

[…] It doesn’t matter where or how exactly you store hListener, since you will not use it directly in your program. The important thing is just to store it *anywhere*, so that it remains in persistent (heap) memory. As long as the reference handle is “alive”, the listener will keep working. This is explained here. […]

#16 Comment By Rajeev On March 31, 2014 @ 12:49

Here is what I am trying to achieve. I have NI DAQ that I use to acquire 2 channel data continuously (session based, running in background). I use the inbuilt listner to tap the data for plotting and writing to disk. One of the input is a square waveform. Using this waveform, I want to segment the second channel and store in a matrix and keep updating the matrix on each iteration. I tried a few options but couldn’t achieve. Any idea how should I proceed?

Thanks
RY

#17 Comment By Yair Altman On March 31, 2014 @ 12:52

@Rajeev – this is not the right forum for such questions. Try the [12] forum.

#18 Pingback By uicontextmenu performance | Undocumented Matlab On April 2, 2014 @ 11:02

[…] Advanced users could use handle listeners to attached a callback such that when a plot element is deleted, so too are its associated context menus […]

#19 Pingback By Property value change listeners | Undocumented Matlab On August 13, 2014 @ 07:33

[…] addlistener is basically equivalent to the following low-level UDD-based code snippet, as explained here […]

#20 Pingback By uicontextmenu performance | Undocumented Matlab On December 8, 2014 @ 01:28

[…] in 0.29 seconds figure contains 1418 objects – drawn in 0.29 seconds …Advanced users could use handle listeners to attached a callback such that when a plot element is deleted, so too are its associated context […]

#21 Comment By Yury Brodskiy On January 13, 2015 @ 05:48

Dear Yair,

Do you know any substitute for build-in UDD events in new HG2 graphics? I am particularity interested in the ‘ObjectChildAdded’ event for axes object.
From introspection of matlab.graphics.axis.Axes, it is clear that:
it is not possible to listen to “children” property;
it is not possible to subclass Axes and use ‘PreUpdate’ or ‘PostUpdate’ events.

Thank you,

Best regards,
Yury

#22 Comment By Yair Altman On January 13, 2015 @ 07:01

@Yuri – I am not aware of a corresponding event, but you could trap the all-encompassing MarkedClean event and within the callback compare the current Children value with the pre-stored one (e.g., in the ApplicationData). For example, something like this:

addlistener(gca, 'MarkedClean', @markedCleanCallback);

function markedCleanCallback(hAxes,eventData)
   lastChildrenValue = getappdata(hAxes, 'Children');
   if ~isequal(hAxes.Children, lastChildrenValue)
      setappdata(hAxes, 'Children', hAxes.Children);
      newChildren = setdiff(hAxes.Children, lastChildrenValue);
      % now do something interesting with newChildren
   end
end  % markedCleanCallback

#23 Comment By Sebastian On February 26, 2016 @ 00:58

Hi,

I have come across the same problem with Matlab 2015b and have tried Yair’s “markedCleanCallback” solution. Unluckily it does not work, since the MarkedClean event is only fired, if a new child to an axis changes the axis state. This means e.g. that if you plot a single point into the center of an existing axis the event will not be fired.

Since the properties “Children” and the events “PostUpdate” are not observable and protected, respectively, I don’t see any way to monitor the state of axis children in HG2 at the moment.

Curious to see if anyone proves me wrong …

Cheers

Sebastian

#24 Comment By Yair Altman On February 26, 2016 @ 13:57

@Sebastian – I believe that you are mistaken: if you add a new point to an axes, even at the center, the markedClean event is indeed triggered. For example:

>> f = figure;  % new figure
>> a = axes;    % new axes
>> addlistener(a, 'MarkedClean', @(h,e)disp(e));
>> plot(.5,.5);  % new point at center of axes - triggers callback below:

  Update with properties:

       Source: [1x1 Axes]
    EventName: 'MarkedClean'

#25 Comment By Yair Altman On February 26, 2016 @ 13:58

In any case you can try any of the other axes events as described here: [13]

#26 Comment By Sebastian On February 26, 2016 @ 22:36

If you add the following commands to your list you will see that the last plot added will not trigger any event:

plot(.5,.6,'.'); % axis limits change, MarkedClean-event is triggered
hold on;
plot(.5,.55,'.'); % axis limits do not change, MarkedClean-event is not triggered

In essence the MarkedClean event is only triggered if the appearance of the axis somehow changes. Concerning the other events mentioned in your link (I also checked to see if there are any additional events in 2015b) I don’t think how they could be used to monitor the number of childs.

Sebastian

#27 Comment By Sebastian On March 8, 2016 @ 00:59

Good news,

I just downloaded release 2016a and the following events are now available for axes:

‘ChildAdded’, ‘ChildRemoved’, ‘NodeChildAdded’, ‘NodeChildRemoved’

They are all public, so this should be really useful.

Sebastian

#28 Comment By Vishnu S Nair On April 21, 2015 @ 02:56

Hi,
The discussion details helped me to solve my problem. But I have some doubts,
If I change the name of state or transition, how can I listen the events. I tried this below code:

HG = sfgco;
hProp = findprop(HG,'Name');
hListener = handle.listener(HG, hProp, 'PropertyPostSet', @lineCallback)

It listen the event when I right click and change LabelString in properties of Stateflow object. How can I listen when changing the name of Stateflow object from GUI.
Thank you in advance.

#29 Comment By John toscano On November 28, 2015 @ 05:33

HOW CAN I MEET WITH THE MATRIX SOURCE

WHY IS YOUR INTERACTION OBSCURE

#30 Comment By Yair Altman On November 28, 2015 @ 08:31

Ha ???

#31 Comment By Joan F. Alonso On January 8, 2016 @ 08:31

Dear Yair,
After reading Yury’s post and your response, I am trying to do something similar to detect deleted children. But it turns out that I get a

 0x1 empty GraphicsPlaceholder array 

Is there any other way to detect if a user deleted a line or a patch?
Thank you! And Happy New Year, by the way!

#32 Comment By Miguel Secundino On February 10, 2016 @ 00:10

This discussion is the only place that I found with some relation with my question:
Could be possible minimize the Simulink editor window from Matlab?
I have spended a lot of time looking for some answer.
The reason is that I need open a Simulink block and after I need to hidde the editor window.
Thanks in advance.
M. Secundino


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/udd-events-and-listeners

URLs in this post:

[1] discussion: http://www.mathworks.com/help/techdoc/matlab_oop/bqvggvt.html

[2] Creating a Simple UDD Class: http://undocumentedmatlab.com/blog/creating-a-simple-udd-class/

[3] question: https://www.mathworks.com/matlabcentral/newsreader/view_thread/303232

[4] UDD properties: http://undocumentedmatlab.com/blog/udd-properties/

[5] details: http://undocumentedmatlab.com/blog/matlab-callbacks-for-java-events/

[6] Property value change listeners : https://undocumentedmatlab.com/articles/property-value-change-listeners

[7] Waiting for asynchronous events : https://undocumentedmatlab.com/articles/waiting-for-asynchronous-events

[8] Capturing print events : https://undocumentedmatlab.com/articles/capturing-print-events

[9] Matlab callbacks for Java events : https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events

[10] Undocumented HG2 graphics events : https://undocumentedmatlab.com/articles/undocumented-hg2-graphics-events

[11] Matlab callbacks for Java events in R2014a : https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events-in-r2014a

[12] : http://www.mathworks.com/matlabcentral/answers/

[13] : https://undocumentedmatlab.com/blog/undocumented-hg2-graphics-events

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.