Recent

Author Topic: Run-time TPanel move  (Read 1151 times)

davor

  • Newbie
  • Posts: 2
Run-time TPanel move
« on: November 20, 2023, 03:18:47 pm »
Is it possible to move same TPanel component between different forms in run-time?

Handoko

  • Hero Member
  • *****
  • Posts: 5106
  • My goal: build my own game engine using Lazarus
Re: Run-time TPanel move
« Reply #1 on: November 20, 2023, 03:42:14 pm »
Hello davor,
Welcome to the forum.

Yes, most visual components can be moved to other forms easily.

Try this:
Code: Pascal  [Select][+][-]
  1. unit frmMain;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, Graphics, ExtCtrls, StdCtrls, frmChild;
  9.  
  10. type
  11.  
  12.   { TMainform }
  13.  
  14.   TMainform = class(TForm)
  15.     Button1: TButton;
  16.     Panel1: TPanel;
  17.     procedure Button1Click(Sender: TObject);
  18.     procedure FormActivate(Sender: TObject);
  19.     procedure FormCreate(Sender: TObject);
  20.   end;
  21.  
  22. var
  23.   Mainform: TMainform;
  24.  
  25. implementation
  26.  
  27. {$R *.lfm}
  28.  
  29. { TMainform }
  30.  
  31. procedure TMainform.FormCreate(Sender: TObject);
  32. begin
  33.   Panel1.BevelInner := bvLowered;
  34.   Panel1.Color      := clCream;
  35. end;
  36.  
  37. procedure TMainform.FormActivate(Sender: TObject);
  38. begin
  39.   Childform.Left := Left + Width + 10;
  40.   Childform.Top  := Top;
  41.   Childform.Show;
  42. end;
  43.  
  44. procedure TMainform.Button1Click(Sender: TObject);
  45. begin
  46.   if Panel1.Parent = Mainform then
  47.   begin
  48.     Panel1.Parent := Childform;
  49.     Exit;
  50.   end;
  51.   if Panel1.Parent = Childform then
  52.     Panel1.Parent := Mainform;
  53. end;
  54.  
  55. end.

wp

  • Hero Member
  • *****
  • Posts: 11779
Re: Run-time TPanel move
« Reply #2 on: November 20, 2023, 03:56:24 pm »
Hmmm, I don't know... A control also has an owner - this is the component which is responsible to destroy it. The panel was created by Form1 and, therefore, has Form1 as its owner. When the panel now is moved to Form2 with your code still Form1 remains the owner. When now Form1 is destroyed before Form2 the panel is removed from Form2 (hopefully!) - but this will be very surprising for the user.

The problem is that the Owner is a read-only property and cannot be change easily in the same way as you did with the Parent.

One solution might be to create a new panel on Form2, assign the Form1.panel to it (i.e. copy its properties), and then destroy the panel on Form1. Of course, this must be repeated for all controls sitting on the panel...

But possibly there is a better solution...


Handoko

  • Hero Member
  • *****
  • Posts: 5106
  • My goal: build my own game engine using Lazarus
Re: Run-time TPanel move
« Reply #3 on: November 20, 2023, 03:59:47 pm »
I already thought about it before posting the reply. I am sure no problem with my code, because Form1 is the main form. Closing main form will cause all other forms to close too. And you can see from the code, closing child form will cause the program to halt.
« Last Edit: November 20, 2023, 04:01:38 pm by Handoko »

wp

  • Hero Member
  • *****
  • Posts: 11779
Re: Run-time TPanel move
« Reply #4 on: November 20, 2023, 04:55:37 pm »
I already thought about it before posting the reply. I am sure no problem with my code, because Form1 is the main form. Closing main form will cause all other forms to close too. And you can see from the code, closing child form will cause the program to halt.
But why should closing the child form close the application? You put a "Halt" into the code. But why?

When the child from does NOT close the application, but is destroyed and reactivates the main form, we have another confusing situation: The panel was parented by the child form. When the child form is killed the panel disappears from the screen along with its parent, but still exists - without parent - in memory, but still owned by the main form. This does not mean that it must be a dangerous situation, but it least it is unusual.

Handoko

  • Hero Member
  • *****
  • Posts: 5106
  • My goal: build my own game engine using Lazarus
Re: Run-time TPanel move
« Reply #5 on: November 20, 2023, 05:03:04 pm »
But why should closing the child form close the application? You put a "Halt" into the code. But why?

If you download the code, remove the halt and run it then you will know why.

When the child from does NOT close the application, but is destroyed and reactivates the main form

Closing the child form does not cause it to be freed or destroyed. It simply hides the form. That is the default form behavior (in Lazarus).
« Last Edit: November 20, 2023, 05:05:43 pm by Handoko »

luca

  • Jr. Member
  • **
  • Posts: 83
Re: Run-time TPanel move
« Reply #6 on: November 20, 2023, 05:30:08 pm »
Hi,
I've downloaded the code.

The Button1Click event is never fired.
Every time I click on the button the FormActivate event is triggered and nothing more happen.

If I removed the code from FormActivate procedure, and show the Child form when I click on another button (I've created on main form), then all it's fine and no error appears even if I remove the Halt instruction.
It seems the problem is that every time you click on the MainForm the ChildForm is showed back and the program can't exit.

Best regards
Luca

wp

  • Hero Member
  • *****
  • Posts: 11779
Re: Run-time TPanel move
« Reply #7 on: November 20, 2023, 06:20:33 pm »
Showing the child from in Handoko's code in the OnActivate handler should be protected by some state variable preventing multiple execution:

Code: Pascal  [Select][+][-]
  1. type
  2.   TMainForm = class(TForm)
  3.   ...
  4.   private
  5.     Activated: Boolean;
  6.   end;
  7.  
  8. procedure TMainform.FormActivate(Sender: TObject);
  9. begin
  10.   if not Activated then
  11.   begin
  12.     Activated := true;
  13.     Childform.Left := Left + Width + 10;
  14.     Childform.Top  := Top;
  15.     Childform.Show;
  16.   end;
  17. end;
  18.  
« Last Edit: November 20, 2023, 07:50:04 pm by wp »

luca

  • Jr. Member
  • **
  • Posts: 83
Re: Run-time TPanel move
« Reply #8 on: November 20, 2023, 07:48:07 pm »
Generally speaking I don't like to use OnActivate event.

Regards
Luca
« Last Edit: November 21, 2023, 07:46:52 am by luca »

davor

  • Newbie
  • Posts: 2
Re: Run-time TPanel move
« Reply #9 on: November 21, 2023, 10:21:47 am »
Big Thanks Handoko!!!!
This is exactly the solution I was looking for.  :)

Handoko

  • Hero Member
  • *****
  • Posts: 5106
  • My goal: build my own game engine using Lazarus
Re: Run-time TPanel move
« Reply #10 on: November 21, 2023, 11:54:19 am »
This is exactly the solution I was looking for.

Glad to know it is useful.
But you should pay attention about the potential issue that wp pointed out. That would be too advanced for you now, just remember if you ever have problem with this 'moving component to other form', report back.

Generally speaking I don't like to use OnActivate event.

As a programmer, I would try and use anything that works. Is there any reason you don't like it?

I've downloaded the code.

The Button1Click event is never fired.
Every time I click on the button the FormActivate event is triggered and nothing more happen.

I'm sorry it does not work for you. I wrote it and tested only on Linux. Did you use Windows?

Showing the child from in Handoko's code in the OnActivate handler should be protected by some state variable preventing multiple execution:

Thank you for the improvement. I like to use global variable as little as possible, I would suggest to move that private/global variable to local:
Code: Pascal  [Select][+][-]
  1. procedure TMainform.FormActivate(Sender: TObject);
  2. const
  3.   Activated: Boolean = false;
  4. begin
  5.   if not Activated then
  6.   begin
  7.     Activated := true;
  8.     Childform.Left := Left + Width + 10;
  9.     Childform.Top  := Top;
  10.     Childform.Show;
  11.   end;
  12. end;
« Last Edit: November 21, 2023, 11:56:13 am by Handoko »

 

TinyPortal © 2005-2018