Lazarus

Free Pascal => General => Topic started by: lazer on January 31, 2023, 12:08:03 pm

Title: How to assign onclick event to dynamically created object ?
Post by: lazer on January 31, 2023, 12:08:03 pm
Hi,

I have created a bunch of TstaticText objects dynamically and need to assign some event handlers to be the same as a design time control of the same type.

Code: Pascal  [Select][+][-]
  1.     result[i]:=TstaticText.create(nil);
  2.     result[i].onclick:=refTextClick.onclick;
  3.  

It fails to compile saying the number of arguments does not match.
Code: Pascal  [Select][+][-]
  1.  Error: Wrong number of parameters specified for call to "refTextClick"

Can someone explain what I should be doing?

TIA.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: bytebites on January 31, 2023, 12:35:15 pm
Code: Pascal  [Select][+][-]
  1.  result[i].onclick:=@refTextClick.onclick;
Title: Re: How to assign onclick event to dynamically created object ?
Post by: TRon on January 31, 2023, 12:36:25 pm
See also https://wiki.freepascal.org/Form_Tutorial#Creating_a_new_form_dynamically.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: Zvoni on January 31, 2023, 01:02:48 pm
Code: Pascal  [Select][+][-]
  1.  result[i].onclick:=@refTextClick.onclick;
If not Mode Delphi!
Title: Re: How to assign onclick event to dynamically created object ?
Post by: KodeZwerg on January 31, 2023, 01:10:13 pm
Code: Pascal  [Select][+][-]
  1.  Error: Wrong number of parameters specified for call to "refTextClick"
If the current suggestions not work, I would suggest that...
Can someone explain what I should be doing?
...you explain by showing your "OnClick" event header/signature.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: lazer on January 31, 2023, 02:12:01 pm
Code: Pascal  [Select][+][-]
  1.     result[i].onclick:=@refTextClick.onclick;
  2.  
I wondered if that was it but it doesn't seems to help:
Quote
Error: Wrong number of parameters specified for call to "refTextClick"

Quote
...you explain by showing your "OnClick" event header/signature.

Code: Pascal  [Select][+][-]
  1.     procedure refTextClick(Sender: TObject);

How does that explain what syntax I need?  I'm trying to assign a event procedure to an event , not define a new one.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: TRon on January 31, 2023, 02:20:40 pm
Code: Pascal  [Select][+][-]
  1.     procedure refTextClick(Sender: TObject);
How does that explain what syntax I need?  I'm trying to assign a event procedure to an event , not define a new one.
That is not an event and also not what you showed in your first post. see: https://wiki.freepascal.org/Form_Tutorial#Creating_a_new_form_dynamically
Title: Re: How to assign onclick event to dynamically created object ?
Post by: Thaddy on January 31, 2023, 02:37:11 pm
If refTextClick.OnClick is already an existing method from an existing instance (a procedure of object and assuming refTextClick is a TStaticText) the initial code should work. It is perfectly allowed to share a method between classes/components, but they should be there.
A method has a hidden self parameter. You can't simply assign a normal procedure to an event. That needs to be a method, a.k.a. procedure of object.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: lazer on January 31, 2023, 03:27:18 pm
If refTextClick.OnClick is already an existing method from an existing instance (a procedure of object and assuming refTextClick is a TStaticText) the initial code should work. It is perfectly allowed to share a method between classes/components, but they should be there.

"Should" but doesn't.  As I reported it fails to compile.  The event handler for the refText object was created in the IDE.  I'm simply trying to assign it to a bunch of similar but dynamically created objects.

Quote
A method has a hidden self parameter. You can't simply assign a normal procedure to an event. That needs to be a method, a.k.a. procedure of object.

That is exactly what I'm doing. Maybe I did not post enough context with that declaration:
Code: Pascal  [Select][+][-]
  1.   TPuzzleForm = class(TForm)        
  2.     procedure refTextClick(Sender: TObject);
  3.   private
  4. .....

So I seem to be doing what you say should work but it gets rejected by the compiler. Maybe I'm still missing, or mis-explaining, something.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: TRon on January 31, 2023, 03:31:03 pm
That is exactly what I'm doing. Maybe I did not post enough context with that declaration:
Code: Pascal  [Select][+][-]
  1.   TPuzzleForm = class(TForm)        
  2.     procedure refTextClick(Sender: TObject);
  3.   private
  4. .....

So I seem to be doing what you say should work but it gets rejected by the compiler. Maybe I'm still missing, or mis-explaining, something.
That is at least much better and yes that is how it is suppose to look.

What type (and in case an array what type of elements) is your result variable ? Otherwise post a complete small example that generates your issue.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: alpine on January 31, 2023, 03:38:53 pm
*snip*
That is exactly what I'm doing. Maybe I did not post enough context with that declaration:
Code: Pascal  [Select][+][-]
  1.   TPuzzleForm = class(TForm)        
  2.     procedure refTextClick(Sender: TObject);
  3.   private
  4. .....

So I seem to be doing what you say should work but it gets rejected by the compiler. Maybe I'm still missing, or mis-explaining, something.

But the refTextClick is a "procedure of object". Why you're appending .onclick after it?

Edit:
When you have 2 components, say CompA and CompB, it is normal to assign:
Code: Pascal  [Select][+][-]
  1.   CompB.OnClick := CompA.OnClick;
Since both components have an OnClick property.
But when you want to assign a procedure, then you should write:
Code: Pascal  [Select][+][-]
  1.   CompB.OnClick := @refTextClick; // Depending on the mode you may not need the @
Title: Re: How to assign onclick event to dynamically created object ?
Post by: lazer on January 31, 2023, 04:12:31 pm
Thanks alpine. This works:

Code: Pascal  [Select][+][-]
  1. result[i].onclick:=refText.onclick;

since refText.onclick   is refTextClick  , I still don't see why it failed doing it that way.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: KodeZwerg on January 31, 2023, 04:16:00 pm
How does that explain what syntax I need?  I'm trying to assign a event procedure to an event , not define a new one.
Since you get an error, I asked, I am sorry that it made you sad that I asked.

Anyway, I show you an example, maybe you find your error by reading it.
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes , SysUtils , Forms , Controls , Graphics , Dialogs , ExtCtrls ,
  9.   StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     btnremove: TButton;
  17.     btncreate: TButton;
  18.     Panel1: TPanel;
  19.     procedure btncreateClick(Sender: TObject);
  20.     procedure btnremoveClick(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure GenericOnClick(Sender: TObject);
  23.   strict private
  24.     FInc: Integer;
  25.   private
  26.  
  27.   public
  28.  
  29.   end;
  30.  
  31. var
  32.   Form1: TForm1;
  33.  
  34. implementation
  35.  
  36. {$R *.lfm}
  37.  
  38. { TForm1 }
  39.  
  40. procedure TForm1.GenericOnClick(Sender: TObject);
  41. begin
  42.   if Sender is TLabel then
  43.     begin
  44.       TLabel(Sender as TLabel).Caption := IntToStr(FInc);
  45.       Inc(Finc);
  46.     end;
  47. end;
  48.  
  49. procedure TForm1.btncreateClick(Sender: TObject);
  50. var
  51.   lbl: TLabel;
  52. begin
  53.   lbl := TLabel.Create(Self);
  54.   try
  55.     lbl.Parent := Panel1;
  56.     lbl.Align := alTop;
  57.     lbl.Caption := 'test';
  58.     lbl.Name := 'Label1';
  59.     lbl.OnClick := @GenericOnClick;
  60.   finally
  61.     lbl.Visible := True;
  62.   end;
  63.   btncreate.Enabled := False;
  64.   btnremove.Enabled := True;
  65. end;
  66.  
  67. procedure TForm1.btnremoveClick(Sender: TObject);
  68. var
  69.   lbl: TLabel;
  70. begin
  71.   lbl := nil;
  72.   if (FindComponent('Label1') <> nil) then
  73.     begin
  74.       lbl := TLabel(FindComponent('Label1'));
  75.       lbl.OnClick := nil;
  76.       lbl.Free;
  77.       lbl := nil;
  78.       btnremove.Enabled := False;
  79.       btncreate.Enabled := True;
  80.     end;
  81. end;
  82.  
  83. procedure TForm1.FormCreate(Sender: TObject);
  84. begin
  85.   FInc := 0;
  86. end;
  87.  
  88. end.
  89.  
Title: Re: How to assign onclick event to dynamically created object ?
Post by: lazer on January 31, 2023, 04:22:52 pm
Quote
Since you get an error, I asked, I am sorry that it made you sad that I asked.
Where did I say I was "sad".

Your rather annoying way of refusing to answer the question and making it ten times harder to understand does not help. I'm sure you are playing some kind of "teacher" game but it does not work. Reconsider the "educational theory" you think you learnt somewhere.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: KodeZwerg on January 31, 2023, 04:33:37 pm
Code: Pascal  [Select][+][-]
  1. result[i].onclick:=refTextClick.onclick;
Hmm...
since refText.onclic   is refTextClick  , I still don't see why it failed doing it that way.
Double hmmm....

All in here told how to do but you refuse to use what they write.
Code: Pascal  [Select][+][-]
  1.   CompB.OnClick := @refTextClick; // Depending on the mode you may not need the @
Code: Pascal  [Select][+][-]
  1.     lbl.OnClick := @GenericOnClick;

You still dont see a difference to your way?...
Your rather annoying way of refusing to answer the question and making it ten times harder to understand does not help. I'm sure you are playing some kind of "teacher" game but it does not work. Reconsider the "educational theory" you think you learnt somewhere.
...good luck, I just tried to help and put even a full working example here.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: dseligo on January 31, 2023, 06:49:51 pm
Thanks alpine. This works:

Code: Pascal  [Select][+][-]
  1. result[i].onclick:=refText.onclick;

since refText.onclick   is refTextClick  , I still don't see why it failed doing it that way.

Because you wrote refTextClick.onclick (in your first post).

You either write method name:
Code: Pascal  [Select][+][-]
  1. result[i].OnClick := refTextClick; // or result[i].onclick := @refTextClick; for ObjFPC mode

or component and it's event:
Code: Pascal  [Select][+][-]
  1. result[i].OnClick := refText.OnClick;
Title: Re: How to assign onclick event to dynamically created object ?
Post by: lazer on January 31, 2023, 07:24:24 pm
Quote
Because you wrote refTextClick.onclick (in your first post).
Ah , indeed.  And so did the first two replies which is why that did not work either !

Anyway, as I posted in my previous reply to alpine, this is now working.  Thanks to all for replies.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: dseligo on January 31, 2023, 08:51:33 pm
Quote
Because you wrote refTextClick.onclick (in your first post).
Ah , indeed.  And so did the first two replies which is why that did not work either !

Anyway, as I posted in my previous reply to alpine, this is now working.  Thanks to all for replies.

Yes, but since you didn't show declaration they couldn't know that your component name was refText and not refTextClick. And '@' is very often problem for people between 'mode delphi' and 'mode ObjFPC', so that is the reason for their answers.
Title: Re: How to assign onclick event to dynamically created object ?
Post by: lazer on February 01, 2023, 03:55:09 am
Quote
since you didn't show declaration they couldn't know that your component name was refText and not refTextClick.
well they couldn't know that refTextClick was not an integer variable either , but  no one assumed that. I did show the create() call of the dynamics and stated that the other variable was of the same type. There was no ambiguity.

What really caused the confusion here was the stupid error message.  Instead of complaining that refTextClick.onclick simply did not exist , it gave me some distracting BS about parameter counts.
Quote
Error: Wrong number of parameters specified for call to "refTextClick"

I was not attempting to call refTextClick,  It could have thought I was trying to call refTextClick.onclick  in that context but that does not exist. That is what the error message should have thrown out. Or it could have said refTextClick had not property called onclick.

In either case I would have realised what my mistake was instead of trying to find what the "parameter" BS was supposed to mean.

TinyPortal © 2005-2018