Recent

Author Topic: [Solved]Forms and Units; Form Classes  (Read 18261 times)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12523
  • FPC developer.
Re: Forms and Units; Form Classes
« Reply #15 on: April 03, 2013, 12:13:47 pm »
This thread seems to confuse designtime and runtime creation with manual creation. IOW cod seems to think that designtime forms are always autocreate, they aren't.


Designtime form : form made in designer, stored in resource

manual form       : form entirely made by hand in code.

runtime form      : designtime form that is NOT autocreate, and can be instantiated by hand and multiple times.

autocreate form: designtime form that is autocreated in the .lpr and is closed only when the LCL finalizes.

IOW it is perfectly possible to runtime instantiate a designtime created form in own variables.

Which forms are autocreated, and which not is governed by "project"->"project options"->forms.


cov

  • Full Member
  • ***
  • Posts: 246
Re: Forms and Units; Form Classes
« Reply #16 on: April 03, 2013, 01:18:06 pm »
Yes, I understand about runtime forms.

I have a problem with my Project due to too many designtime forms in it, so I am trying to manually create the form so that it can be instantiated (and destroyed) at runtime.

@User137, thanks for pointing that out.

I can call it from the other unit unit7.buildForm;, but I get a External: SIGSEGV error

Code: [Select]
type

{ TFormB }

TFormB = class(TForm)
  Button1, Button2, Button3, Button4: TButton;
  ComboBox1: TComboBox;
  Label1,Label2: TLabel;
  Panel1: TPanel;
  ListBox1: TListBox;
  AttrGrid: TStringGrid;
  CheckBox1: TCheckBox;
  SelectDirectoryDialog1: TSelectDirectoryDialog;
  procedure OkayButtonClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    constructor Create;
  end;

var
  FormB: TFormB;
  procedure buildForm;

implementation

constructor TFormB.Create;
begin
  Left:=442;<-SIGSEGV here.
end;


procedure buildForm;
begin
  FormB:=TFormB.Create;
  FormB.Show;
end;     

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Forms and Units; Form Classes
« Reply #17 on: April 03, 2013, 01:39:51 pm »
I felt like the issue was more about knowing how classes and objects work in general. There seemed to be huge misunderstandings in the thread on how to simply create an object. Now i'm worried about if you're freeing them.

Therefore i'd suggest to change this:
Code: [Select]
FormB:=TFormB.Create;into this:
Code: [Select]
Application.CreateForm(TFormB, FormB);
I don't know about the SIGSEGV you're getting. It is OK to set Left property in form constructor, and it looks like the form is created.
After small test i noticed it's not inheriting TForm constructor:
Code: [Select]
constructor TFormB.Create;
begin
  inherited Create(application);
  Left:=442;
end;

edit3: Sorry i'm making a mess... This might clear it up:
Code: [Select]
TForm1 = class(TForm)
  private
  public
    constructor Create(TheOwner: TComponent); override;
  end;
...
constructor TForm1.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  Left:=100;
end;
« Last Edit: April 03, 2013, 01:52:14 pm by User137 »

cov

  • Full Member
  • ***
  • Posts: 246
Re: Forms and Units; Form Classes
« Reply #18 on: April 03, 2013, 02:26:54 pm »
Yes.

As I implied in the OP I don't really understand how the relationship between forms and units is maintained.

With designtime form implementation, the Form type is declared as a Class(TForm) and the designed form variable may defined as Form1: TForm1. All procedures and functions relating to the form are defined under FormB so that a procedure may be declared:

procedure setPaths;

and implemented:

procedure TForm1.setPaths;
begin
  ...
end;

However, if I'm just using a PAS file as a unit to contain some functions and procedures and global variables, I generally don't define a class(TForm) type so that my procedures are defined (as above):

procedure setPaths;

but implemented:

procedure setPaths; (without the TForm1. prepended)
begin
  ...
end;

This is what I'm seeking to clarify, particularly in regard to Forms which are constructed at runtime.

cov

  • Full Member
  • ***
  • Posts: 246
Re: Forms and Units; Form Classes
« Reply #19 on: April 03, 2013, 02:39:23 pm »
Code: [Select]
// -----------------8<------------------
  public
    { public declarations }
    constructor Create(TheOwner: TComponent); override;
  end;

var
  FormB: TFormB;
  procedure buildForm;
  procedure LoadDwg;

implementation

constructor TFormB.Create;
begin
  inherited Create(TheOwner);
  Left:=442;                                 
// -----------------8<------------------

Error: function header doesn't match any method of this class "constructor TFormB.Create;"
« Last Edit: April 03, 2013, 03:11:39 pm by cov »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Forms and Units; Form Classes
« Reply #20 on: April 03, 2013, 03:07:29 pm »
Yes.

As I implied in the OP I don't really understand how the relationship between forms and units is maintained.

a Unit can have multiple forms or classes in it it is customary to use one form per unit to keep things clean and easier to understand.

With designtime form implementation, the Form type is declared as a Class(TForm) and the designed form variable may defined as Form1: TForm1. All procedures and functions relating to the form are defined under FormB so that a procedure may be declared:

procedure setPaths;

and implemented:

procedure TForm1.setPaths;
begin
  ...
end;

However, if I'm just using a PAS file as a unit to contain some functions and procedures and global variables, I generally don't define a class(TForm) type so that my procedures are defined (as above):

procedure setPaths;

but implemented:

procedure setPaths; (without the TForm1. prepended)
begin
  ...
end;

This is what I'm seeking to clarify, particularly in regard to Forms which are constructed at runtime.

to put it as simple as I can a class is a unit that has not be loaded or initialized yet. you load and initialize that unit by calling its constructor  the Create method. The constructor allocates enough memory to hold the classes variables and initializes them to a certain value if you do not write code to give them specific values then their memory usually is filled with 0s.
You can have as many of those classes loaded as you like each with different data in their variables showing different things on the same or different layout.

A variable be it form1 or formB or what ever you want to call it is a pointer data type that holds the memory address where the class has been initialized.


a design time form is a form that you used the IDE designer to place controls on it and set specific values to their properties all those changes are saved in the .lfm file which is read at run time to recreate the environment you defined at design time. This means that when you design a form you simply select what are the initialization values for those controls when the form is created and by writing code on the controls events you decide how those controls should react.

The form in its final state after you have finished working with it can be considered a compound control a single controls that handles a more complex logic than a simple Tedit for example, you can create as many of those as you might need and have them represent different views. An easy to understand example is, a form that can be used to edit the data of a customer in a database, you can have multiple forms created that can edit different customers each but you design that form once for all the customers.

Using a single unit with its global variables and procedures do not allow you to have different views at the same time you are confined to one and only one view at each single moment you can change to represent an other view but the moment you do that you loose the old view's data that is a big limitation don't you think?
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Forms and Units; Form Classes
« Reply #21 on: April 03, 2013, 04:59:10 pm »
Quote
a Unit can have multiple forms or classes in it it is customary to use one form per unit to keep things clean and easier to understand.
A unit can certainly have more than one class within it. However it is more than 'customary' that Lazarus prevents you having more than one form in a single unit.
You cannot have more than one (displayable) TForm class definition within a single unit, because there is only ever one .lfm file associated with each form unit. The Form Designer cannot handle designing two or more  forms whose source is found in only a single unit. AFAIK Delphi is no different in this respect.
Each form you create has to be done via File->New Form for this reason (File->New Unit is no good for normal form creation).
In this respect TForm descendants differ from all other LCL/FCL classes (except frames). You need a separate unit for each form. If you really understand the internals of Lazarus it might be possible to squeeze more than one form into a single unit somehow, I couldn't state definitely that it could never be done. However, I don't know why you would want to do such a thing, and I expect if it can be done that it would give you endless grief, since the IDE goes to some lengths to prevent you doing it.
« Last Edit: April 03, 2013, 05:02:01 pm by howardpc »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Forms and Units; Form Classes
« Reply #22 on: April 03, 2013, 05:37:29 pm »
Quote
a Unit can have multiple forms or classes in it it is customary to use one form per unit to keep things clean and easier to understand.
A unit can certainly have more than one class within it. However it is more than 'customary' that Lazarus prevents you having more than one form in a single unit.
You cannot have more than one (displayable) TForm class definition within a single unit, because there is only ever one .lfm file associated with each form unit. The Form Designer cannot handle designing two or more  forms whose source is found in only a single unit. AFAIK Delphi is no different in this respect.
Each form you create has to be done via File->New Form for this reason (File->New Unit is no good for normal form creation).
In this respect TForm descendants differ from all other LCL/FCL classes (except frames). You need a separate unit for each form. If you really understand the internals of Lazarus it might be possible to squeeze more than one form into a single unit somehow, I couldn't state definitely that it could never be done. However, I don't know why you would want to do such a thing, and I expect if it can be done that it would give you endless grief, since the IDE goes to some lengths to prevent you doing it.

As you said the single form per unit is a designer constraint nothing prevents you from having more than one form in a single unit including multiple {$R} directives to include lfm files for each form but using the designer on such a unit is not possible.
That of course is common sense and I do not propose that you should use more that 1 form in a unit it is never the less quite possible to do so take a look on the dialogs unit for example.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

cov

  • Full Member
  • ***
  • Posts: 246
Re: Forms and Units; Form Classes
« Reply #23 on: April 03, 2013, 06:19:35 pm »
As regards multiple views from a single PAS unit, I feel that it's probably worthwhile splitting the unit if I need multiple views.


taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Forms and Units; Form Classes
« Reply #24 on: April 03, 2013, 06:47:25 pm »
Are you searching for reasons to use OOP or are you trying to understand how to use it?
if the first then easy of use and re use is the most common reason to do that if the second read the posts again.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

cov

  • Full Member
  • ***
  • Posts: 246
Re: Forms and Units; Form Classes
« Reply #25 on: April 03, 2013, 09:34:58 pm »
I'm trying to create forms on the fly as recommended in the link on the OP.


cov

  • Full Member
  • ***
  • Posts: 246
Re: Forms and Units; Form Classes
« Reply #26 on: April 04, 2013, 11:07:01 am »
Okay. enough of the whys and wherefores.

I've followed the instructions given by User137:

Code: [Select]
type

{ TFormB }

TFormB = class(TForm)
  Button1, Button2, Button3, Button4: TButton;
  ComboBox1: TComboBox;
  Label1,Label2: TLabel;
  Panel1: TPanel;
  ListBox1: TListBox;
  AttrGrid: TStringGrid;
  CheckBox1: TCheckBox;
  SelectDirectoryDialog1: TSelectDirectoryDialog;
  procedure OkayButtonClick(Sender: TObject);
  procedure ComboBox1Change(Sender: TObject);
  procedure ListBox1Click(Sender: TObject);
  procedure ListBox1MouseMove(Sender: TObject);
  procedure Button4Click(Sender: TObject);
  procedure Button1Click(Sender: TObject);
  procedure CheckBox1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    constructor Create(TheOwner: TComponent); override;
  end;

var
  FormB: TFormB;

implementation

constructor TFormB.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  Left:=442;                 


The Form is instantiated from another  unit:
Code: [Select]
  FormB:=TFormB.CreateNew(nil);
  FormB.ShowModal;
  FormB.Free;

(I tried User137's suggestion using Application.CreateForm(TFormB, FormB);, but this raised an exception "EResNotFound" and an advice to use Createnew)

Anyway, this does call up a form, but it is completely blank. Nothing on it, and set at Top=0 and Left=0.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Forms and Units; Form Classes
« Reply #27 on: April 04, 2013, 11:22:48 am »
after the implementation there should be a line {$R *.lfm} which I do not see. since your code is not complete I do not know if it exists at all. make sure that line exists right after the implementation keyword and use Create not CreateNew
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

cov

  • Full Member
  • ***
  • Posts: 246
Re: Forms and Units; Form Classes
« Reply #28 on: April 04, 2013, 12:49:58 pm »
Correct.

There is no {$R *.lfm} directive because the Form is created programmatically.

Quote
unit_blocks.pas(344,1) Error: Can't open resource file "C:\Documents and Settings\dave\My Documents\Laz\eVision\unit_blocks.lfm"

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Forms and Units; Form Classes
« Reply #29 on: April 04, 2013, 12:56:16 pm »
{$R} is required regardless how you create it at runtime.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

 

TinyPortal © 2005-2018