Recent

Author Topic: Function to provision an object and return a reference to it?  (Read 2137 times)

rwebb616

  • Full Member
  • ***
  • Posts: 133
Hello,

I'm wondering if this is possible... and I think I have to use pointers to accomplish but here goes:

I have a TFPObjectList that maintains a list of Label objects and a function called "GetLabel" that will either create a label if one doesn't exist or return the one asked for.  It also sets various properites the way that I need them for my app (labels is the TFPObjectList):

Code: Pascal  [Select][+][-]
  1. function GetLabel(Name: String; Fontsize : integer): TLabel;
  2. var
  3.   i:integer;
  4.   myLabel : TLabel;
  5. begin
  6.   Result := nil;
  7.   i:=0;
  8.   while i < labels.Count do begin
  9.     if (labels[i] as TLabel).Name = Name then begin
  10.       myLabel := labels[i] as Tlabel;
  11.       myLabel.Font.Size := FontSize;
  12.       Result := myLabel;
  13.       myLabel.Free;
  14.       exit;
  15.     end;
  16.     inc(i);
  17.   end;
  18.   // Existing label not found - create one and return label
  19.   myLabel := TLabel.create(nil);
  20.   myLabel.Name:=Name;
  21.   myLabel.font.size := FontSize;
  22.   myLabel.font.color := clWhite;
  23.   myLabel.font.name := 'Roboto Black';
  24.   labels.add(myLabel);
  25.   Result := myLabel;
  26.   myLabel.free;
  27. end;                                                                  

And this works to get a label the same as the one in the list but it's not THE one in the list.  How do I get it to return a reference to the one in the list so that the things I do to it from the calling procedure affect the one in the list? I hope that's clear.. hard to describe.

Rich

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: Function to provision an object and return a reference to it?
« Reply #1 on: April 16, 2021, 06:16:25 pm »
U don't want to free the local label because it is ponter to the one in the list.

Yeah was getting a SIGSEGV .. probably where that was coming from... then comes the question of how to manage it and free it when necessary.

I'm also open to suggestions as a better way to handle it as well.  At any given time throughout the application I could be tracking anywhere between 15 and 20 labels - hence the objectlist.

Also I just refactored this to return the label rather than the index of the object in the list because I always have to keep type casting to TLabel because the objectlist stores TObject.  I know I could possibly create a descendant of the objectlist for the TLabels but I'm not sure how to do that...

Rich

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Function to provision an object and return a reference to it?
« Reply #2 on: April 16, 2021, 06:52:02 pm »
See the attached project for an example

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: Function to provision an object and return a reference to it?
« Reply #3 on: April 16, 2021, 07:19:14 pm »
See the attached project for an example

This looks like what I am doing... my problem is that the label that I'm editing (as in your button click events) is not the label in the object list but the local lbl label.  I want to be able to have "GetLabel" return a reference so that as I edit properties on it, it's editing the properties of the label in the list.

Is that possible?
Rich

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Function to provision an object and return a reference to it?
« Reply #4 on: April 16, 2021, 07:50:49 pm »
Of course it's possible.

See the example I gave, where every fpobjectlist entry is a reference to an actual label created in the normal way by dropping a component on the form.
Perhaps you need to post a (minimum) compilable project that fails to do what you are after.
As jamie pointed out you seem not to understand the difference between a label instance and a reference to that instance, and you "Free" references which should not ever be required.
 Ensure the form (or some container) owns all your components, and let the automatic Freeing mechanism of ownership do the task for you. A reference can just be set to Nil when it is no longer useful or required.

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: Function to provision an object and return a reference to it?
« Reply #5 on: April 16, 2021, 09:42:54 pm »
Of course it's possible.

See the example I gave, where every fpobjectlist entry is a reference to an actual label created in the normal way by dropping a component on the form.
Perhaps you need to post a (minimum) compilable project that fails to do what you are after.
As jamie pointed out you seem not to understand the difference between a label instance and a reference to that instance, and you "Free" references which should not ever be required.
 Ensure the form (or some container) owns all your components, and let the automatic Freeing mechanism of ownership do the task for you. A reference can just be set to Nil when it is no longer useful or required.

Yes, I am a beginner - just trying to understand the concepts of how things work... sorry if I came off as criticizing your code that wasn't my intention - you know FAR more than I do to be sure.  So to be clear are you saying that in your code:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.GetNewLabelButtonClick(Sender: TObject);
  2. var
  3.   lbl: TLabel;
  4. begin
  5.   GetNewLabelButton.Enabled := False;
  6.   lbl := GetLabel('label4', 9);
  7.   with lbl do
  8.     begin
  9.       Font.Color := clYellow;
  10.       AnchorSideLeft.Control := Label1;
  11.       AnchorSideLeft.Side := asrRight;
  12.       AnchorSideTop.Control := Label1;
  13.       BorderSpacing.Left := 30;
  14.       Parent := Self;
  15.     end;
  16. end;

that lbl is just a reference to label4 in the object list? So if any properties change with lbl then the changes are kept with the control in the object list? 

So I guess the difference here is lbl is assigned the return value of the GetLabel function and not a locally created object (label)?

Rich



howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Function to provision an object and return a reference to it?
« Reply #6 on: April 16, 2021, 09:54:15 pm »
Code: Pascal  [Select][+][-]
  1. procedure TForm1.GetNewLabelButtonClick(Sender: TObject);
  2. var
  3.   lbl: TLabel;
  4. begin
  5.   GetNewLabelButton.Enabled := False;
  6.   lbl := GetLabel('label4', 9);
  7.   with lbl do
  8.     begin
  9.       Font.Color := clYellow;
  10.       AnchorSideLeft.Control := Label1;
  11.       AnchorSideLeft.Side := asrRight;
  12.       AnchorSideTop.Control := Label1;
  13.       BorderSpacing.Left := 30;
  14.       Parent := Self;
  15.     end;
  16. end;

that lbl is just a reference to label4 in the object list? So if any properties change with lbl then the changes are kept with the control in the object list? 

So I guess the difference here is lbl is assigned the return value of the GetLabel function and not a locally created object (label)?

Rich
Better to say that lbl is a reference held by (and retrieved from) the object list to the label on the form named 'Label4'.
So if your code does
Code: Pascal  [Select][+][-]
  1. lbl.Property := SomeNewValue;
then the new assignment to Label4's Property value is reflected immediately and you see the label change visually on the form, just as if you had written
Code: Pascal  [Select][+][-]
  1. Label4.Property := SomeNewValue;
lbl is a (typed pointer) variable that has been made to reference the same TLabel instance as the variable Label4 refers to.
« Last Edit: April 16, 2021, 09:58:38 pm by howardpc »

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: Function to provision an object and return a reference to it?
« Reply #7 on: April 16, 2021, 10:00:04 pm »
So if I do:
Code: Pascal  [Select][+][-]
  1. lbl := Tlabel.create(false)

Then lbl is still a typed pointer variable but to a locally created object?

Cool.. then I guess the default stance is what I was already trying to do.  I just need to make sure that my form owns all the labels so they get destroyed when the form is destroyed.

Now in my project the GetLabel function is in a different unit but I wouldn't guess that would matter.  It probably makes more sense for it to be with the form anyway since it has to do with creating/positioning labels on the form. 

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Function to provision an object and return a reference to it?
« Reply #8 on: April 17, 2021, 10:16:32 am »
So if I do:
Code: Pascal  [Select][+][-]
  1. lbl := Tlabel.create(false)

Then lbl is still a typed pointer variable but to a locally created object?
True.
And that reference is to a new label object distinct from any other pre-existing label instance you may have constructed (whether created in code or via the form designer).
So that lbl will never equal an existing label (unless you deliberately change its referent, and so lose track of the newly created label it originally referred to).

 

TinyPortal © 2005-2018