Recent

Author Topic: [solved] Try playing with frame  (Read 2165 times)

folkeu08

  • Jr. Member
  • **
  • Posts: 53
[solved] Try playing with frame
« on: November 19, 2021, 08:34:35 pm »
Hi
I try to use frames. I find very few examples and even software sources using them.
I manage to dynamically incorporate a frame in a Panel of a MainForm.
The second step is to modify the selection of TabSheets of a PageControl of the frame from 5 buttons positioned in the MainForm.
I guess wrongly declare my Frame to have access to its controls from the MainForm.
I need a little help here.
Thank you
Francois
« Last Edit: November 21, 2021, 12:06:24 am by folkeu08 »

af0815

  • Hero Member
  • *****
  • Posts: 846
Re: Try playing with frame
« Reply #1 on: November 19, 2021, 08:37:50 pm »
In this bugreport https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/39478 is a sample of a frame in frame in frame with TPageControl. Remove only the Component, with the issue.

« Last Edit: November 19, 2021, 08:39:54 pm by af0815 »
regards
Andreas

Lulu

  • Full Member
  • ***
  • Posts: 143
Re: Try playing with frame
« Reply #2 on: November 19, 2021, 08:51:32 pm »
Hi François, one way can be to declare some procedure in your class TCelluleFrame:
Code: Pascal  [Select][+][-]
  1. TCelluleFrame=class
  2. ...
  3. public
  4.   procedure ViewEquipe;
  5.   procedure ViewPeriode;
  6. ..etc...
Code: Pascal  [Select][+][-]
  1. procedure TCelluleFrame.ViewEquipe;
  2. begin
  3.   Cellule_PageControl.ActivePage:= Equipe_TabSheet;
  4. end;

and call them in your main form:
Code: Pascal  [Select][+][-]
  1. procedure TMainForm.Equipe_OnClick(Sender: TObject);
  2.   begin
  3.     Frame.ViewEquipe;
  4.   end;
  5.  

repeat for all tabsheet you have.
« Last Edit: November 19, 2021, 08:53:12 pm by Lulu »
Have a nice life

folkeu08

  • Jr. Member
  • **
  • Posts: 53
Re: Try playing with frame
« Reply #3 on: November 19, 2021, 11:35:24 pm »
Thanks Lulu,
I made the changes but I don't really know where to place
"TCelluleFrame = class"
or if it's my line
TCelluleFrame = class (TFrame) to be modified as well.
I have done several tests and the "viewEquipe" is not recognized in the mainform.
Francois



howardpc

  • Hero Member
  • *****
  • Posts: 3860
Re: Try playing with frame
« Reply #4 on: November 20, 2021, 12:09:33 am »
You need to declare Frame as TCelluleFrame (not TFrame), which means removing the implementation uses clause of Main_Unit, so it looks like this:
Code: Pascal  [Select][+][-]
  1. unit Main_Unit;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
  9.   ComCtrls, celluleframe_unit;
  10.  
  11. type
  12.  
  13.   { TMainForm }
  14.  
  15.   TMainForm = class(TForm)
  16.     CelluleButton: TButton;
  17.     FormationButton: TButton;
  18.     PresenceButton: TButton;
  19.     HabilitationButton: TButton;
  20.     PublicationButton: TButton;
  21.     LeftPanel: TPanel;
  22.     MasterPanel: TPanel;
  23.     StatusBar: TStatusBar;
  24.     procedure Cellule_OnClick(Sender: TObject);
  25.     procedure Formation_OnClick(Sender: TObject);
  26.     procedure Habilitation_OnClick(Sender: TObject);
  27.     procedure MainForm_OnCreate(Sender: TObject);
  28.     procedure Presence_OnClick(Sender: TObject);
  29.     procedure PublicationButtonClick(Sender: TObject);
  30.   private
  31.     Frame: TCelluleFrame;
  32.   end;
  33.  
  34. var
  35.   MainForm: TMainForm;
  36.  
  37. implementation
  38.  
  39. {$R *.lfm}
  40.  
  41. { TMainForm }
  42.  
  43. procedure TMainForm.MainForm_OnCreate(Sender: TObject);
  44.   begin
  45.     Frame := TCelluleFrame.Create(self);
  46.     Frame.parent := MasterPanel;
  47.     Frame.Align := alClient;
  48.   end;
  49.  
  50.  
  51. procedure TMainForm.Cellule_OnClick(Sender: TObject);
  52.   begin
  53.     Frame.ViewEquipe;
  54.   end;
  55.  
  56.  
  57. procedure TMainForm.Presence_OnClick(Sender: TObject);
  58.   begin
  59.      Frame.ViewPresence;
  60.   end;
  61.  
  62.  
  63. procedure TMainForm.Formation_OnClick(Sender: TObject);
  64.   begin
  65.     Frame.Viewformation;
  66.   end;
  67.  
  68. procedure TMainForm.Habilitation_OnClick(Sender: TObject);
  69.   begin
  70.     Frame.ViewHabilitation;
  71.   end;
  72.  
  73. procedure TMainForm.PublicationButtonClick(Sender: TObject);
  74.   begin
  75.     Frame.ViewPublication;
  76.   end;
  77.  
  78. end.
Then you're good to go.

wp

  • Hero Member
  • *****
  • Posts: 9178
Re: Try playing with frame
« Reply #5 on: November 20, 2021, 12:19:29 am »
The problem is that you declare the Frame as TFrame, but you created it as a descendant, TCelluleFrame. Therefore, Frame does not know the controls that you added to TCelluleFrame.

To fix this you have two options:

/1/ The simpler one is to declare Frame as TCelluleFrame, rather than TFrame:
Code: Pascal  [Select][+][-]
  1. type
  2.   TMainForm = class(TForm)
  3.     ...
  4.   public
  5.     Frame: TCelluleFrame;  // <--- was: TFrame
  6.   end;

This is probably fine for the current state of your project. But maybe later, you have other frame types which you want to insert dynamically instead of the TCelluleFrame; this would have the consequence that you cannot talk to these frames because the frame type known to the form is still TCelluleFrame. Therefore, I propose another option.

/2/ Keep the declaration of Frame as TFrame. But then, whenever you access the frame, check whether it is a TCelluleFrame ("if Frame is TCelluleFrame then...") and them make a type-cast to TCelluleFrame. This is a standard trick in object-oriented programming to handle polymorphism. After the type-cast the compiler knows that it should consider the Frame variable as a TCelluleFrame and you have access to the the components of TCelluleFrame. Here is one example:
Code: Pascal  [Select][+][-]
  1. procedure TMainForm.Cellule_OnClick(Sender: TObject);
  2. begin
  3.   if Frame is TCelluleFrame then
  4.     with TCelluleFrame(Frame) do
  5.       Cellule_PageControl.ActivePage:= Equipe_TabSheet;
  6. end;
The "with" is used here to shorten the code. Many people don't like "with" (because it can result in code which is difficult to read) - here is the version without "with":
Code: Pascal  [Select][+][-]
  1. procedure TMainForm.Cellule_OnClick(Sender: TObject);
  2. begin
  3.   if Frame is TCelluleFrame then
  4.     TCelluleFrame(Frame).Cellule_PageControl.ActivePage:= TCelluleFrame(Frame).Equipe_TabSheet;
  5. end;

P.S.
Ah, Howard was faster with option 1.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

folkeu08

  • Jr. Member
  • **
  • Posts: 53
Re: Try playing with frame
« Reply #6 on: November 20, 2021, 01:54:41 pm »
@howardpc
Hi HowardPC,

It's ok for your solution.
I post the corrction of my source.
Thanks
François

After I add a second frame to test the ideas at WP and I repost the new source.
I have add a new panel in the main form wtih 4 boutons (Add, Edit, delete and report). I will try to modify the text of each buttons according to the selected tabsheet of the Pagecontrol in the frame.
I will try to control the elements of the MainForm from the actions in the Frames
Thanks
François

folkeu08

  • Jr. Member
  • **
  • Posts: 53
Re: [solved] Try playing with frame
« Reply #7 on: November 21, 2021, 12:13:23 am »
Hi,
Since then, I added a second frame and I manage to change the frame concerned by calling it with the button on the left and accessing the correct TabSheet of the PageControl.
I also wanted to change the captions of the button at the top by selecting (clicking) on ​​the TabSheet. It works and I made it for the second frame (VehicleFrame).
Very Thanks at all for your help.
Now, I can continue my soft for my job.
Thanks
François

 

TinyPortal © 2005-2018