Reputation: 1351
I have a class that represent some data and a (short) chain of results originating from this data. The class has the three properties Data1
, Data2
and Data3
, where Data2
depends on Data1
(it is actually a filtered version of it) and Data3
depends on Data2
.
My idea was to trigger an event when Data1
changes that computes Data2
, and then trigger an other event that leads to the computation of Data3
. However, in the test class below, Data3
is empty after construction.
Note that I use uiw.event.EventData
from the Widget toolbox.
classdef test < handle
events
DataChanged
end
properties
DataChangedListener event.listener
end
properties (AbortSet)
Data1 (:,:) double = []
Data2 (:,:) double = []
Data3 (:,:) double = []
end
methods
function self = test()
self.DataChangedListener = event.listener(self, 'DataChanged', @self.onDataChanged);
self.Data1 = peaks(64);
end
%% setter
function set.Data1(self, d)
self.Data1 = d;
evt = uiw.event.EventData( ...
'EventType', 'DataChanged', ...
'Property', 'Data1', ...
'Model', self );
self.notify('DataChanged', evt);
end
function set.Data2(self, d)
self.Data2 = d;
evt = uiw.event.EventData( ...
'EventType', 'DataChanged', ...
'Property', 'Data2', ...
'Model', self );
self.notify('DataChanged', evt);
end
function set.Data3(self, d)
self.Data3 = d;
evt = uiw.event.EventData( ...
'EventType', 'DataChanged', ...
'Property', 'Data3', ...
'Model', self );
self.notify('DataChanged', evt);
end
%% Event callback
function onDataChanged(self, ~, evt)
switch evt.Property
case 'Data1'
self.Data2 = self.Data1 + 5;
case 'Data2'
self.Data3 = self.Data2 + 10;
end
end
end
end
If one debugs this, one sees that onDataChanged
is never called with the uiw.event.eventData
with evt.Property = 'Data2'
.
Das anyone know why and how to trigger the event properly?
Upvotes: 1
Views: 74
Reputation: 32084
I think I solved the puzzle.
Your code executes the listener callback recursively.
By default recursive listener is disabled.
Refer to Event and Listener Concepts:
Recursive — Allow listener to trigger the same event that caused execution of the callback. Recursive is false by default. If the callback triggers the event for which it is defined as the callback, the listener cannot execute recursively. Therefore, set Recursive to false if the callback must trigger its own event. Setting the Recursive property to true can create a situation where infinite recursion reaches the recursion limit and triggers an error.
All you need to do is setting Recursive
property to true
:
After self.DataChangedListener = event.listener(self, 'DataChanged', @self.onDataChanged);
Add: self.DataChangedListener.Recursive = true;
Upvotes: 1