I want to turn on/off dependency of two class properties based on the third property.

I made a class "rect" for rectangle, with independent properties width, height and fix_aspect_ratio.
What I want to do is:
  • If fix_aspect_ratio is 0, width and height are independently modifiable.
  • If fix_aspect_ratio is 1, height/width should be maintained. When I change width, height should be modified to keep the ratio, and vise versa.
What I wrote:
classdef rect < handle
properties
width (1,1) double {mustBePositive} = 1
height (1,1) double {mustBePositive} = 1
fix_aspect_ratio (1,1) logical = 0
end
methods
function obj = rect(width, height, fix_aspect_ratio)
arguments
width (1,1) double {mustBePositive} = 3
height (1,1) double {mustBePositive} = 4
fix_aspect_ratio (1,1) logical = 0
end
obj.width = width;
obj.height = height;
obj.fix_aspect_ratio = fix_aspect_ratio;
end
function set.width(obj, width)
if obj.fix_aspect_ratio
obj.height = obj.height * width/obj.width;
end
obj.width = width;
end
function set.height(obj, height)
if obj.fix_aspect_ratio
obj.width = obj.width * height/obj.height;
end
obj.height = height;
end
end
end
Problem:
  • When I try to change width, set.height is called, in which set.width is called, ... I get Maximum recursion error
  • When I try to change height, same thing.
Can I get any solution?
Thank you.
Kang.

 Akzeptierte Antwort

chrisw23
chrisw23 am 13 Feb. 2023
Save the listener handles as private properties and use the listeners 'Enabled' property to turn on/off the dependency as needed.
i.e.
obj.listenerObservedProp = addlistener(obj,'ObservedProp'...
obj.listenerObservedProp.Enabled = false

3 Kommentare

Thank you @chrisw23.
I'm trying to apply setObsevable and listeners.
But I've encountered another problem.
classdef rect < handle
properties (SetObservable)
width
height
end
properties
fix_aspect_ratio (1,1) logical = 0
end
properties (Access = private)
listener_width
listener_height
end
methods
function obj = rect(width, height, fix_aspect_ratio)
arguments
width (1,1) double {mustBePositive} = 3
height (1,1) double {mustBePositive} = 4
fix_aspect_ratio (1,1) logical = 0
end
obj.width = width;
obj.height = height;
obj.fix_aspect_ratio = fix_aspect_ratio;
obj.listener_width = addlistener(obj, 'width', 'PreSet', @rect.propChange);
obj.listener_height = addlistener(obj, 'height', 'PreSet', @rect.propChange);
end
end
methods (Static)
function propChange(metaProp, eventData)
% How can I get the new value to set width or height?
end
end
end
In the propChange method, I need to know both the old and new value of width or height.
For example, if the original width was 3 and I want to change it to 6, height also has to be doubled.
But if I make the listener as Preset, the new value cannot be accessed because it is not passed yet,
while if I make the listener as Postset, the old value cannot be accessed because it is already discarded.
Can I pass the new value to listener callback?
Thank you.
why static ?
methods (private)
function propChange(obj,metaProp, eventData)
...
would give you access via obj and saving obj.lastPropVal should not be a problem using the prop set/get methods.
Thank you.
Solved by adding private properties for width and height.
Here is my new code:
classdef rect < handle
properties (Dependent)
width
height
end
properties
fix_aspect_ratio (1,1) logical = 0
end
properties (Access = private)
p_width
p_height
end
methods
function obj = rect(width, height, fix_aspect_ratio)
arguments
width (1,1) double {mustBePositive} = 3
height (1,1) double {mustBePositive} = 4
fix_aspect_ratio (1,1) logical = 0
end
obj.p_width = width;
obj.p_height = height;
obj.fix_aspect_ratio = fix_aspect_ratio;
end
function width = get.width(obj)
width = obj.p_width;
end
function height = get.height(obj)
height = obj.p_height;
end
function set.width(obj, width)
if obj.fix_aspect_ratio
obj.p_height = obj.p_height * width/obj.p_width;
end
obj.p_width = width;
end
function set.height(obj, height)
if obj.fix_aspect_ratio
obj.p_width = obj.p_width * height/obj.p_height;
end
obj.p_height = height;
end
end
end
Your suggestion was helpful by the way.
Thank you.
Kang.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Produkte

Version

R2022a

Gefragt:

am 12 Feb. 2023

Bearbeitet:

am 14 Feb. 2023

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by