Recent

Author Topic: detect if a variable has Changed  (Read 1586 times)

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 323
  • Weitental is a very beautiful garbage depot.
detect if a variable has Changed
« on: October 19, 2021, 11:19:00 am »
Hello :),

is this Somehow possible ?

I know i can use Getter and Setter or define an old Var to store old Value.

Is there a better approach ?

Thanks in advance :)
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 737
Re: detect if a variable has Changed
« Reply #1 on: October 19, 2021, 11:37:00 am »
Flag - is obvious solution:
Code: Pascal  [Select][+][-]
  1. procedure TMyClass.SetValue(AValue:TValue);//Setter
  2. begin
  3.   if AValue <> FValue then begin
  4.     FValue := AValue;
  5.     FValueChanged := True;//Flag
  6.     OnValueChanged(Self, AValue);//Or event
  7.   end;
  8. end;
  9.  
24.11.2021 - DynamicData 4.0 runtime is overhauled to improve scalability.
My project still requires full Delphi 2009 support to be ported to Lazarus.
It's time to finally do it, because Delphi 2009 is 12 years old.

howardpc

  • Hero Member
  • *****
  • Posts: 3833
Re: detect if a variable has Changed
« Reply #2 on: October 19, 2021, 11:45:33 am »
Outside of a class you can use a stand-alone property.
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Dialogs, Spin;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     AlertSpinEdit: TSpinEdit;
  13.     procedure AlertSpinEditChange(Sender: TObject);
  14.   end;
  15.  
  16.  
  17.   procedure SetAlertIfChanged(aValue: Integer);
  18.  
  19.   function GetAlertIfChanged: Integer;
  20.  
  21.   procedure Alert;
  22.  
  23.   property AlertIfChanged: Integer read GetAlertIfChanged write SetAlertIfChanged;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. var
  31.   alertInt: Integer = 50;
  32.  
  33. procedure SetAlertIfChanged(aValue: Integer);
  34. begin
  35.   if aValue <> alertInt then begin
  36.     alertInt := aValue;
  37.     Alert;
  38.   end;
  39. end;
  40.  
  41. function GetAlertIfChanged: Integer;
  42. begin
  43.   Exit(alertInt);
  44. end;
  45.  
  46. procedure Alert;
  47. begin
  48.   ShowMessageFmt('AlertIfChanged is now %d',[AlertIfChanged]);
  49. end;
  50.  
  51. {$R *.lfm}
  52.  
  53. { TForm1 }
  54.  
  55. procedure TForm1.AlertSpinEditChange(Sender: TObject);
  56. begin
  57.   AlertIfChanged := (Sender as TSpinEdit).Value;
  58. end;
  59.  
  60. end.

white_zombie

  • New Member
  • *
  • Posts: 15
Re: detect if a variable has Changed
« Reply #3 on: October 19, 2021, 12:25:05 pm »
Depending on what you want to do, you can implement an observer pattern. I think FPC supports this since version 2.6.4

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 323
  • Weitental is a very beautiful garbage depot.
Re: detect if a variable has Changed
« Reply #4 on: October 19, 2021, 01:14:00 pm »
Depending on what you want to do, you can implement an observer pattern. I think FPC supports this since version 2.6.4

I think thats an overkill for a Single Variable ?

Outside of a class you can use a stand-alone property.
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Dialogs, Spin;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     AlertSpinEdit: TSpinEdit;
  13.     procedure AlertSpinEditChange(Sender: TObject);
  14.   end;
  15.  
  16.  
  17.   procedure SetAlertIfChanged(aValue: Integer);
  18.  
  19.   function GetAlertIfChanged: Integer;
  20.  
  21.   procedure Alert;
  22.  
  23.   property AlertIfChanged: Integer read GetAlertIfChanged write SetAlertIfChanged;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. var
  31.   alertInt: Integer = 50;
  32.  
  33. procedure SetAlertIfChanged(aValue: Integer);
  34. begin
  35.   if aValue <> alertInt then begin
  36.     alertInt := aValue;
  37.     Alert;
  38.   end;
  39. end;
  40.  
  41. function GetAlertIfChanged: Integer;
  42. begin
  43.   Exit(alertInt);
  44. end;
  45.  
  46. procedure Alert;
  47. begin
  48.   ShowMessageFmt('AlertIfChanged is now %d',[AlertIfChanged]);
  49. end;
  50.  
  51. {$R *.lfm}
  52.  
  53. { TForm1 }
  54.  
  55. procedure TForm1.AlertSpinEditChange(Sender: TObject);
  56. begin
  57.   AlertIfChanged := (Sender as TSpinEdit).Value;
  58. end;
  59.  
  60. end.

Isn't this the same when i use a property for a Variable like that (pseudo Code):


Code: Pascal  [Select][+][-]
  1.  
  2. TMyClass = class
  3.  
  4. private
  5.    int fx;
  6.  
  7.    procedure SetX(aValue: Integer);
  8.    function GetX: Integer;
  9.    procedure xChanged
  10.  
  11. public
  12.    property x:Integer read Getx write SetX;
  13. end;
  14.  
  15. implementation
  16.  
  17. procedure TMyClass .SetX(AVAlue: Integer);
  18. begin
  19.    fx:= AVAlue;
  20.    xChanged();
  21. end;
  22.  
  23.  
  24. procedure TMyClass GetX(): Integer;
  25. begin
  26.    Result:= fX;
  27. end;
  28.  

i hope u get what i was trying to say  :-[

Flag - is obvious solution:
Code: Pascal  [Select][+][-]
  1. procedure TMyClass.SetValue(AValue:TValue);//Setter
  2. begin
  3.   if AValue <> FValue then begin
  4.     FValue := AValue;
  5.     FValueChanged := True;//Flag
  6.     OnValueChanged(Self, AValue);//Or event
  7.   end;
  8. end;
  9.  

Isn't this the same as above too ?  :-[

Btw. i need to fire an event just like TEdit has OnChange.

I did not want to create a property and use its setter / getter for this, or create a whole new value just to store the old value. Something like i assign a Handler to a Value and if the Value is changing the Handler "handles" the new Value.

Thanks anyway for your suggestions :)
« Last Edit: October 19, 2021, 01:17:18 pm by Weitentaaal »
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

MarkMLl

  • Hero Member
  • *****
  • Posts: 3514
Re: detect if a variable has Changed
« Reply #5 on: October 19, 2021, 01:21:11 pm »
@Weitentaaal: I've held off commenting up to this point, since I was hoping that either you or somebody else would throw light on the fundamental question: when you say "variable", do you mean a "classic Pascal" unmanaged integer (etc.) in memory, rather than a field of a class?

My suspicion is that if you do, neither FPC nor any other conventional language has the capability of flagging a state-change without wrapping the variable in something: either compile-time complexity (the variable becomes a field in an object, and is then accessed via a property and a setter) or run-time complexity probably involving either an interpretive runtime or alternatively processor-specific debugging capabilities.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 323
  • Weitental is a very beautiful garbage depot.
Re: detect if a variable has Changed
« Reply #6 on: October 19, 2021, 01:46:07 pm »
@Weitentaaal: I've held off commenting up to this point, since I was hoping that either you or somebody else would throw light on the fundamental question: when you say "variable", do you mean a "classic Pascal" unmanaged integer (etc.) in memory, rather than a field of a class?

My suspicion is that if you do, neither FPC nor any other conventional language has the capability of flagging a state-change without wrapping the variable in something: either compile-time complexity (the variable becomes a field in an object, and is then accessed via a property and a setter) or run-time complexity probably involving either an interpretive runtime or alternatively processor-specific debugging capabilities.

MarkMLl

Sorry my fault,

i ment classic Pascal Variable (Integer, String, boolean etc)

 in the following example i have a "Variable" : "fX". if "fX" is changing i want to fire an event. Thats why  i created Property "X" to use the getter and setter of "X". This way i can fire an Event ("xChanged") in the setter methode
Code: Pascal  [Select][+][-]
  1.  
  2. TMyClass = class
  3.  
  4. private
  5.    int fx;
  6.  
  7.    procedure SetX(aValue: Integer);
  8.    function GetX: Integer;
  9.    procedure xChanged
  10.  
  11. public
  12.    property x:Integer read Getx write SetX;
  13. end;
  14.  
  15. implementation
  16.  
  17. procedure TMyClass .SetX(AVAlue: Integer);
  18. begin
  19.    if AValue <> fx then begin //forgott this
  20.       fx:= AVAlue;
  21.       xChanged();
  22.    end;
  23. end;
  24.  
  25.  
  26. procedure TMyClass GetX(): Integer;
  27. begin
  28.    Result:= fX;
  29. end;
  30.  
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

GetMem

  • Hero Member
  • *****
  • Posts: 3510
Re: detect if a variable has Changed
« Reply #7 on: October 19, 2021, 02:29:56 pm »
@Weitentaaal

Try something like this:
Code: Pascal  [Select][+][-]
  1. unit uDetectChange;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils;
  9.  
  10. type  
  11.  
  12.   { TDetectChange }
  13.   TOnVariableChanged = procedure(Sender: TObject; AX: Integer) of object;
  14.   TDetectChange = class
  15.   private
  16.     FX: Integer;
  17.     FOnVariableChanged: TOnVariableChanged;
  18.     procedure SetX(aValue: Integer);
  19.   public
  20.     constructor Create(AX: Integer);
  21.     destructor Destroy; override;
  22.   public
  23.     property X: Integer read FX write SetX;
  24.     property OnVariableChanged: TOnVariableChanged read FOnVariableChanged write FOnVariableChanged;
  25.   end;
  26.  
  27. implementation
  28.  
  29. constructor TDetectChange.Create(AX: Integer);
  30. begin
  31.   FX := AX;
  32. end;
  33.  
  34. destructor TDetectChange.Destroy;
  35. begin
  36.   //
  37.   inherited;
  38. end;
  39.  
  40. procedure TDetectChange.SetX(aValue: Integer);
  41. begin
  42.   if AValue <> FX then
  43.   begin
  44.     FX := AValue;
  45.     if Assigned(FOnVariableChanged) then
  46.       FOnVariableChanged(Self, FX);
  47.   end;
  48. end;
  49.  
  50. end.
  51.  

then:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   uDetectChange;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     procedure Button1Click(Sender: TObject);
  18.     procedure FormCreate(Sender: TObject);
  19.     procedure FormDestroy(Sender: TObject);
  20.   private
  21.    FDetectChange: TDetectChange;
  22.    procedure OnVariableChange(Sender: TObject; AX: Integer);
  23.   public
  24.  
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30. implementation
  31. {$R *.lfm}
  32.  
  33. { TForm1 }
  34.  
  35. procedure TForm1.FormCreate(Sender: TObject);
  36. begin
  37.   FDetectChange := TDetectChange.Create(3);
  38.   FDetectChange.OnVariableChanged := @OnVariableChange;
  39. end;
  40.  
  41. procedure TForm1.FormDestroy(Sender: TObject);
  42. begin
  43.   FDetectChange.Free;
  44. end;
  45.  
  46. procedure TForm1.OnVariableChange(Sender: TObject; AX: Integer);
  47. begin
  48.   ShowMessage('Variable X has changed, new value: ' + IntToStr(AX));
  49. end;
  50.  
  51. procedure TForm1.Button1Click(Sender: TObject);
  52. begin
  53.   FDetectChange.X := 15;
  54. end;
  55.  
  56.  
  57. end.
  58.  

MarkMLl

  • Hero Member
  • *****
  • Posts: 3514
Re: detect if a variable has Changed
« Reply #8 on: October 19, 2021, 02:32:50 pm »
i ment classic Pascal Variable (Integer, String, boolean etc)

I thought you did, hence that it was necessary (eventually) to ask for clarification. So what you're effectively doing there is what I referred to as a compile-time wrapper... I don't know if any sort of runtime wrapper using e.g. debugging registers could be implemented portably and that sort of thing has notoriously poor OS support.

MarkMLl

p.s. That callback should probably be protected by if Assigned().
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Weitentaaal

  • Sr. Member
  • ****
  • Posts: 323
  • Weitental is a very beautiful garbage depot.
Re: detect if a variable has Changed
« Reply #9 on: October 19, 2021, 03:23:29 pm »
"p.s. That callback should probably be protected by if Assigned()."
Thanks for the Hint.

Thanks to all of your Reply's, i guess i will keep the Properties. :)
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.0

 

TinyPortal © 2005-2018