Reputation: 341
Assume I have created a new FMX project with nothing more than a TButton and a TProgressBar on it. Now I added a 'Countertest.pas' file using [Shift] + [F11]. (see code below)
Now I have implemented a procedure into 'Unit1.pas' (the main app) to be triggered by a procedure inside the 'Countertest.pas' file to change the Value of the TProgressBar.
Inside 'Unit1.pas' I wrote this to be called from inside the 'Countertest.pas' file:
procedure TForm1.SomethingChanged(newPercentage:Integer);
begin
ProgressBar1.Value:=newPercentage;
showmessage('Congratulations, you have just reached '+IntToStr(newPercentage)+' Percent ;)');
end;
To simplify my problem, this is my stripped down 'Countertest.pas' file:
unit Countertest;
interface
uses FMX.Memo; // Will be used later
type
TCountertest = Class
private
zahl: Integer;
published
constructor Create();
destructor Destroy();
procedure Counter();
property Percentage: Integer read zahl;
end;
implementation
constructor TCountertest.Create();
begin
end;
destructor TCountertest.Destroy();
begin
end;
procedure TCountertest.Counter();
begin
for i := 0 to 1337 do
Percentage:=0;
begin
zahl:=i;
if Percentage<>round(i / 100) then
begin
// Here I want to call a Procedure inside 'Unit1.pas' to change a Value of the TProgressBar (and some other components like TLabel.Text)
end;
Percentage:=round(i / 100);
end;
end;
end.
As far as I know there is the possibility to use something like procedure(Sender: TObject) of object;
and it seems to be the thing a want to use, however I don't have any idea of how to use this.
My Intention is to write something similar to an OnChange Event used in a TEdit Control.
Of Course I could add 'Unit1.pas' into the Uses section of 'Countertest.pas' and then call the procedure directly, but as have to handle multiple Instances of TCountertest, I want to have it more like this:
procedure InstanceOfTCountertest.SomethingChanged(newPercentage:Integer);
begin
ProgressBar1.Value:=newPercentage;
showmessage('Congratulations, you have just reached a new Percent ;)');
end;
In the final app there are multiple Instances of TCountertest, so I have multiple Progressbars as well (and other GUI components such as TLabels). Maybe there are other ways to do this, so feel free to suggest anything, that could fit the purpose to show the Progress of those Instances.
Upvotes: 2
Views: 2204
Reputation: 3485
Usually, components (like TButton
for example) expose events as properties (eg.: TButton.OnCLick
) and it's up to the parent or sibling components (the parent TForm
in this case) to set the event handler. Let's say we want to change the Button1.OnClick
event handler:
// Setting the handler:
procedure TForm1.Create(AOwner: TComponent);
begin
Button1.OnClick := Self.MyCustomClickHandler;
end;
// And the handler implementation:
procedure TForm1.MyCustomClickHandler(Sender: TObject);
begin
// ...
end;
So, I imagine you want to have an event for your TCountertest
like TCountertest.OnCount
so that other components / forms can set a handler and act in response to a change in your counter's progress. Let's describe how to do it the Delphi way (untested code):
First, your component should implement and expose the event:
unit Countertest;
interface
type
// Custom type for your event handler
TCountEvent = procedure(Sender: TObject; Percentage: Integer) of object;
TCountertest = Class
private
FPercentage: Integer;
// Variable that holds the event handler set by the user
FOnCount: TCountEvent;
// Internal event trigger
procedure DoCount();
public
constructor Create();
destructor Destroy();
procedure Counter();
published
property Percentage: Integer read FPercentage;
// This is the property for your event handler assignment
property OnCount: TCountEvent read FOnCount write FOnCount;
end;
implementation
constructor TCountertest.Create();
begin
// Initialize event handler to nil
FOnCount := nil;
end;
destructor TCountertest.Destroy();
begin
end;
// Event trigger
procedure TCounterTest.DoCount();
begin
// Check that the user assigned an event handler
if Assigned(FOnCount) then
FOnCount(Self, FPercentage);
end;
procedure TCountertest.Counter();
begin
// Your code (update FPercentage in your code)...
// When you need to trigger the event:
DoCount();
// Rest of your code...
end;
end.
Now we are ready to create and set event handlers to your instances of TCountertest
:
unit Unit1;
// ...
type
TForm1 = class
private
// ...
// Declare the handler
procedure CounterCount(Sender: TObject; Percentage: Integer);
public
// ...
end;
implementation
// ...
// Implement the handler
procedure TForm1.CounterCount(Sender: TObject; Percentage: Integer);
begin
ProgressBar1.Value := Percentage;
end;
// Set the event handlers for your counters
procedure TForm1.Create(AOwner: TComponent);
var
Counter1, Counter2: TCountertest;
begin
// Create the counters
Counter1 := TCountertest.Create();
Counter2 := TCountertest.Create();
// Set the event handlers
Counter1.OnCount := Self.CounterCount;
Counter2.OnCount := Self.CounterCount;
end;
end.
I hope it helps. Feel free to ask if not.
Upvotes: 4