Recent

Author Topic: Which button is clicked?  (Read 19176 times)

Haeleng

  • New Member
  • *
  • Posts: 10
Which button is clicked?
« on: May 30, 2017, 11:01:59 am »
Hi,

I'm new to Lasarus and object programming.
In code I created some buttons see code below.
When I press on lets say the second button the procedure BtnSourceClick is called.
In BtnSource a listbox becomes visible, which is the same for all buttons.
In the listbox I click on some itemtekst.
This text should become the captiontext of the button that has been pressed.
How do I determine that for example button 2 is pressed?
    for i:=0 to BoxCount-1 do
    begin
      ButtonArr:=TButton.Create(self);
      ButtonArr.Left:=(i mod 5)*(PanelWidth+PtPOffsetX)+(Xoffset+ButtonOffsetX);
      ButtonArr.Top:=(i div 5)*(PanelHeight+PtPOffsetY)+(Yoffset+ButtonOffsetY);
      ButtonArr.Caption := 'I/O Device';
      ButtonArr.OnClick := @BtnSourceClick;
      ButtonArr.Parent:=aParent;
    end;

Thanks

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: Which button is clicked?
« Reply #1 on: May 30, 2017, 11:10:57 am »
Every event handler has a parameter "Sender" which points to the object from which the event originates. The parameter is very generic, and you will have to cast it to TButton to get access to its properties:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.BtnSourceClick(Sender: TObject);
  2. begin
  3.   if Sender is TButton then begin
  4.     TButton(Sender).Caption := Listbox1.Items[Listbox1.ItemIndex];
  5. end;

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Which button is clicked?
« Reply #2 on: May 30, 2017, 11:30:27 am »
In additions to wp's answer, also note that every component can have a (unique) name by setting the name property for each created component.

Additionally you can use your own array that keeps track of each individual created component and use that array for reference.


howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Which button is clicked?
« Reply #3 on: May 30, 2017, 01:07:20 pm »
One way to track controls such as buttons is to give their Tag property a unique value when they are created. Later you can check the Tag value to identify the control (unless you already use the Tag property for some other purpose). This is slightly easier/quicker than checking the control's Name, and for dynamically created controls you may not set the Name at all.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Which button is clicked?
« Reply #4 on: May 30, 2017, 01:39:05 pm »
One way to track controls such as buttons is to give their Tag property a unique value when they are created. Later you can check the Tag value to identify the control (unless you already use the Tag property for some other purpose). This is slightly easier/quicker than checking the control's Name,
I admit that using tag property is more convenient.

Quote
.. and for dynamically created controls you may not set the Name at all.
Sorry, but lacking English skills there on my part.

Do you mean it is not allowed at all or that it perhaps can be inconvenient depending on user circumstances ?

Because, in case the former then this must be a new rule for (upcoming) lazarus 1.8 release that i do not know of (and introduces Delphi incompatibility). A link stating this new behaviour/rule would be helpful in that case.
« Last Edit: May 30, 2017, 01:47:37 pm by molly »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Which button is clicked?
« Reply #5 on: May 30, 2017, 02:03:31 pm »
Quote
.. and for dynamically created controls you may not set the Name at all.
Do you mean it is not allowed at all or that it perhaps can be inconvenient depending on user circumstances ?

Sorry for the ambiguity.
I merely meant that you might not bother to set the Name of a dynamically created component. You can, of course, and it is better practice to do so. But say you are generating 10 labels to identify 10 spinedits. You would give each label the Caption you wanted, but there might be no purpose at all in bothering to set the Name. Indeed often the Name is only really useful in debugging, to identify a troublesome control.
If you have several forms containing many dynamically created controls, you might name the controls only in the debug phase, and refrain from naming them in your release version (setting all those names adds a microsecond or two).

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Which button is clicked?
« Reply #6 on: May 30, 2017, 02:28:54 pm »
Sorry for the ambiguity.
No problem, e.g. just a misunderstanding/misinterpretation on my part.

Thank you for the elaboration.

With regards of the sanity of setting names of dynamically created components: for me it depends on the situation. Short-lived components that do not require much interaction with other code i leave without a name but, for components that are long-lived and required cross-form access i usually create either an array/list/container or name them so i can always trace each individual component back using application variable.
« Last Edit: May 30, 2017, 02:32:03 pm by molly »

Haeleng

  • New Member
  • *
  • Posts: 10
Re: Which button is clicked?
« Reply #7 on: May 30, 2017, 02:38:38 pm »
@WP,

When I try this code the caption tekst of the pressed button, does not change. Why?

Every event handler has a parameter "Sender" which points to the object from which the event originates. The parameter is very generic, and you will have to cast it to TButton to get access to its properties:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.BtnSourceClick(Sender: TObject);
  2. begin
  3.   if Sender is TButton then begin
  4.     TButton(Sender).Caption := Listbox1.Items[Listbox1.ItemIndex];
  5. end;

balazsszekely

  • Guest
Re: Which button is clicked?
« Reply #8 on: May 30, 2017, 02:42:47 pm »
Name collision is the only issue when you setting names for dynamically created components. This is especially dangerous when you continuously create/free components.

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Which button is clicked?
« Reply #9 on: May 30, 2017, 03:11:22 pm »
When I try this code the caption tekst of the pressed button, does not change. Why?

Can you please provide your code? Compress them and send it to the forum. You must have done something wrong. But without inspecting your code, hard to tell what it is.

I wrote a small test, which the buttons are generated manually. It works correctly:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, StdCtrls;
  9.  
  10. type
  11.  
  12.   TForm1 = class(TForm)
  13.     Button1: TButton;
  14.     Button2: TButton;
  15.     Button3: TButton;
  16.     ListBox1: TListBox;
  17.     procedure ButtonClick(Sender: TObject);
  18.   end;
  19.  
  20. var
  21.   Form1: TForm1;
  22.  
  23. implementation
  24.  
  25. {$R *.lfm}
  26.  
  27. procedure TForm1.ButtonClick(Sender: TObject);
  28. begin
  29.   TButton(Sender).Caption := ListBox1.Items[ListBox1.ItemIndex];
  30. end;
  31.  
  32. end.

You can download the compilable code I provide in the attachment.

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: Which button is clicked?
« Reply #10 on: May 30, 2017, 03:15:04 pm »
@Handoko:
That is not always a guaranteed case. It is just true most of the time and only in simple projects.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ButtonClick(Sender: TObject);
  2. begin
  3.   if sender is TButton then // CHECK IF IT IS A BUTTON first.
  4.      TButton(Sender).Caption := ListBox1.Items[ListBox1.ItemIndex];
  5. end;
  6.  

Now suppose the ButtonClick was also connected to a TForm.OnClick? (perfectly legal)....
Your code would crash.
« Last Edit: May 30, 2017, 03:18:19 pm by Thaddy »
Specialize a type, not a var.

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: Which button is clicked?
« Reply #11 on: May 30, 2017, 03:15:38 pm »
When I try this code the caption tekst of the pressed button, does not change. Why?
Don't know what you're doing. My code is working - see attached project

@Molly: I strongly advise against giving run-time created objects a name because then it is in your responsibility to make sure that the name is unique. As howardpc already noted the name is useless at run-time, maybe only for debugging. If you need one of these objects you can access it using its variable name.

P.S.
Too late, Handoko was faster...

Another P.S.
Replaced the original attachment which was written in Laz trunk by a version for Laz 1.6.4 (Laz trunk adds a new property to TListbox which 1.6.4 does not know).
« Last Edit: May 30, 2017, 04:16:03 pm by wp »

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: Which button is clicked?
« Reply #12 on: May 30, 2017, 03:21:05 pm »
I suppose it is simpler: the OnClick event is not connected to the method anymore or at all, maybe?
When I began using Delphi in 1995 I made that mistake a lot:
- you first design it, create the event through tthe IDE
- then you decide, it's better to do on the fly
- you adapt the code inside the onclick event
- but that is no longer connected.
- that also needs to be done on the fly...

@wp

good remark, I would not "assume" anything when it is on the fly.
« Last Edit: May 30, 2017, 03:23:53 pm by Thaddy »
Specialize a type, not a var.

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Which button is clicked?
« Reply #13 on: May 30, 2017, 03:27:51 pm »
I cannot try wp's clickme.zip. I'm using Lazarus 1.6.4 and got this error:

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Which button is clicked?
« Reply #14 on: May 30, 2017, 03:35:27 pm »
Now suppose the ButtonClick was also connected to a TForm.OnClick? (perfectly legal)....
Your code would crash.

Okay, sir. I was too lazy.  :-[

When I try this code the caption tekst of the pressed button, does not change. Why?
Don't know what you're doing. My code is working - see attached project

Maybe what OP wants is the button's caption changed when user clicks the ListBox's items. So I make my code 'better', now clicking the ListBox's items will change the button's caption:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, StdCtrls;
  9.  
  10. type
  11.  
  12.   TForm1 = class(TForm)
  13.     Button1: TButton;
  14.     Button2: TButton;
  15.     Button3: TButton;
  16.     ListBox1: TListBox;
  17.     procedure ButtonClick(Sender: TObject);
  18.     procedure ListBox1Click(Sender: TObject);
  19.   end;
  20.  
  21. var
  22.   Form1: TForm1;
  23.  
  24. const
  25.   LastButton: TButton = nil;
  26.  
  27. implementation
  28.  
  29. {$R *.lfm}
  30.  
  31. procedure TForm1.ButtonClick(Sender: TObject);
  32. begin
  33.   if not (Sender is TButton) then Exit; // as advised by Thaddy :)
  34.   LastButton := TButton(Sender);
  35.   LastButton.Caption := ListBox1.Items[ListBox1.ItemIndex];
  36. end;
  37.  
  38. procedure TForm1.ListBox1Click(Sender: TObject);
  39. begin
  40.   if Assigned(LastButton) then
  41.     LastButton.Caption := ListBox1.Items[ListBox1.ItemIndex];
  42. end;
  43.  
  44. end.

 

TinyPortal © 2005-2018