Создание формы в режиме run-time

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Создание формы в режиме run-time

Сообщение Kristina » 11.11.2012 14:21:19

Здравствуйте.
Лазарус изучаю не больше недели. До этого ничего кроме си++ не знала. Очень нужна ваша помощь.Есть форма, на ней две кнопки. Первая создает приложение в в design-time, а вторая тоже самое но в run-time.Настройки хранятся в ini файле С design-time я разобралась, а вот с run-time не понятно. Что значит "описать ссылки на компоненты" ? Как это ? как ими после пользоваться? Что бы разобраться мне бы хватило примерчика....например с Label? как его создать в динамическом режиме? помогите=)
Kristina
незнакомец
 
Сообщения: 4
Зарегистрирован: 11.11.2012 14:07:40

Re: Создание формы в режиме run-time

Сообщение Vadim » 11.11.2012 18:58:12

Run-time - это нечто происходящее во время работы программы.
Допустим, Вам нужно создать Label на форме и поместить его в точку с координатами 100 пикселов по горизонтали (от левого края формы) и 100 пикселов по вертикали (от верхнего края формы, без учёта заголовка формы).
1. Прежде всего должна быть объявлена переменная, через которую Вы будете работать с компонентом. Тип переменной - TLabel, т.е. это класс и следовательно, объявленная переменная будет являться ссылкой, хранящей адрес объекта.
Var
MyLabel: TLabel;
Прежде, чем начать использовать эту переменную, необходимо присвоить ей адрес объекта, путём создания его в памяти, иначе переменная будет просто показывать пальцем в небо.
MyLabel:=TLabel.Create(Form1);
MyLabel.Parent:=Form1;
Здесь мы создали объект и привязали его к уже существующей форме Form1 и назначили хозяином этого объекта ту же форму. Теперь эта форма будет отвечать за всё, что происходит с этим объектом, но чем мы, непосредственно, не занимаемся. Например, при удалении формы, она убъёт его самостоятельно, без нашего нашего вмешательства, как Тарас Бульба своего сына Андрея.
3. Теперь, нужно присвоить объекту все необходимые свойства, как минимум это должны быть координаты и некий текст, который этот Label отображает:
MyLabel.Left:=100;
MyLabel.Top:=100;
MyLabel.Caption:='Какой-нибудь текст';
4. Теперь, чтобы Label был виден на форме, его надо показать:
MyLabel.Show;

Вот, в принципе, и всё. ;)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Создание формы в режиме run-time

Сообщение stikriz » 11.11.2012 20:54:31

Vadim писал(а):MyLabel.Left:=100;MyLabel.Top:=100;

Не учите плохому :-)
BeginFormUpdate;
...
SetBounds(ALeft, ATop, AWidth, AHeight: integer);
...
EndFormUpdate;
Vadim писал(а):MyLabel.Show;

По моему, это не надо. А у формы можно сделать update или Invalidate, а можно и не делать, если EndFormUpdate правильно отработает. В Лазарусе нельзя быть во всем уверенным точно... И еще, Создание компонентов в рантайм на форме лучше делать конструктором, а не по кнопке. Просто не могу представить, что нужно именно по кнопке. А что будет при повторном нажатии кнопки? :-) И кто потом первые компоненты убъет?
Аватара пользователя
stikriz
энтузиаст
 
Сообщения: 612
Зарегистрирован: 15.03.2006 09:37:47

Re: Создание формы в режиме run-time

Сообщение Vadim » 12.11.2012 05:06:08

stikriz писал(а):Не учите плохому

Не вижу разницы. Особенно на ненагруженной всякими разными эвентами форме. ;)
stikriz писал(а):По моему, это не надо.

Это так, на всякий случай. :)
stikriz писал(а): И еще, Создание компонентов в рантайм на форме лучше делать конструктором, а не по кнопке.

В каком то смысле я с Вами согласен. Но, наверное, человек просто учится это делать и ему нужно узнать механизм.
stikriz писал(а):А что будет при повторном нажатии кнопки?

Именно то, что Вы и подумали - старый лэйбел удёт в нирвану, а на его месте будет новый. :D Новый автоматом убъётся, а старый так и останется висеть в нирване, он уже недоступен.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Создание формы в режиме run-time

Сообщение zub » 12.11.2012 12:57:23

>>Новый автоматом убъётся, а старый так и останется висеть в нирване, он уже недоступен.
Он доступен и убъется такимже автоматом как новый, благодаря:
Код: Выделить всё
MyLabel:=TLabel.Create(Form1);


Имхо новичкам не стоит вдаваться в "сложности" типа:
Код: Выделить всё
BeginFormUpdate;
...
SetBounds(ALeft, ATop, AWidth, AHeight: integer);
...
EndFormUpdate;

Когда на форме всё начнет мелькать и ездить, а принципы создания рандайм контролов будут поняты (надеюсь иакже станет понятно почему контролы замелькали при каждом изменении), тогда стоит задуматься о более оптимальном создании

Для начала вполне достаточно:
Код: Выделить всё
MyLabel:=TLabel.Create(Form1);
MyLabel.Parent:=Form1;
MyLabel.Left:=100;
MyLabel.Top:=100;
MyLabel.Caption:='Какой-нибудь текст';
MyLabel.Show;

Единственное - MyLabel.Show вобщемто не нужен - контрол виден по умолчанию после присвоения Parent`а, а назначать MyLabel.Parent лучше в конце всех настроек, чтоб эти настройки не мелькали на экране:
Код: Выделить всё
MyLabel:=TLabel.Create(Form1);
MyLabel.Left:=100;
MyLabel.Top:=100;
MyLabel.Caption:='Какой-нибудь текст';
MyLabel.Parent:=Form1;
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Создание формы в режиме run-time

Сообщение Kristina » 13.11.2012 23:19:01

Так то вроде понятно, но создается пустая форма.. в чем проблема?
вот код модуля
Код: Выделить всё
unit Unit4;

{$mode objfpc}{$H+}

interface

uses  inifiles,
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var sec:TStringList;i:integer;l:TLabel;
begin
  with TIniFile.Create(ExtractFilePath(ParamStr(0))+'q.ini') do begin
   sec:=TStringList.Create;
    ReadSections(sec);
    for i:=0 to sec.Count-1 do begin
      l:=TLabel.Create(self);
      l.Caption:=ReadString(sec[i],'Name','');
      l.Color:=ReadInteger(sec[i],'Color',clDefault);
      l.AutoSize:=true;
      l.Parent:=self;
      l.Show;
    end;
   sec.Free;
   Free;;
  end;
end;

end.
Kristina
незнакомец
 
Сообщения: 4
Зарегистрирован: 11.11.2012 14:07:40

Re: Создание формы в режиме run-time

Сообщение zub » 14.11.2012 02:25:23

>>Free;;
это что? не успев создать убиваем?
Ну и потомучто форма всетаки создается, думаю FormCreate не назначено в соответствующее сабытие

Добавлено спустя 3 минуты 55 секунд:
Или Free;; относится к TIniFile? тогда может цикл не крутится, sec.Count=0?
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Создание формы в режиме run-time

Сообщение Vadim » 14.11.2012 05:15:27

Из возможных проблем:
1. Вы уверены, что Ваш INI-файл загрузился?
2. Вы уверены, что в выбранных в цикле секциях содержаться соответствующие ключи с значениями.
3. В каком месте формы должен располагаться создаваемый лэйбл? Вы уверены, что смотрите именно в это место?
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Создание формы в режиме run-time

Сообщение Kristina » 14.11.2012 18:56:48

Создаю в точности как вы советовали.....даже без ини файла, что бы точно не там проблема была
Код: Выделить всё
unit Unit5;

{$mode objfpc}{$H+}

interface

uses  inifiles,
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm4 = class(TForm)
    MyLabel: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm4.FormCreate(Sender: TObject);
var sec:TStringList;i:integer;l:TLabel;
  inif:TIniFile;
begin


  MyLabel:=TLabel.Create(Form4);
MyLabel.Parent:=Form4;
MyLabel.Left:=100;
MyLabel.Top:=100;
MyLabel.Caption:='Какой-нибудь текст';
MyLabel.Show;
end;

end.

но все равно форма создается пустая...я уже не знаю в чем еще может быть дело((
Kristina
незнакомец
 
Сообщения: 4
Зарегистрирован: 11.11.2012 14:07:40

Re: Создание формы в режиме run-time

Сообщение VirusFree » 14.11.2012 20:22:38

Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }
{
//надо так
procedure TForm1.FormCreate(Sender: TObject);
var MyLabel: TLabel;
begin
  MyLabel := TLabel.Create(Self);//владельцем MyLabel указываем себя =Self
  MyLabel.Left:=100;
  MyLabel.Top:=100;
  MyLabel.Caption:='Какой-нибудь текст';
  MyLabel.Parent:=Self;
  //MyLabel.Free будет вызван из деструктора владельца
end;
}

//тоже-самое, но компактнее
procedure TForm1.FormCreate(Sender: TObject);
begin
  with TLabel.Create(Self)//владельцем указываем себя =Self
  do begin
     Left:=100;
     Top:=100;
     Caption:='Какой-нибудь текст';
     Parent:=Self;
     //Free будет вызван из деструктора владельца
     end
{Чтобы управлять созданными объектами (экземплярами некоторого класса)из других мест,
надо хранить их (регистрировать) например в коллекции TCollection, списке TList или в массиве.
Если владельца не указывать (...TLabel.Create(nil) ), то это необходимо и для вызова их деструкторов.}
end;

end.

VirusFree
новенький
 
Сообщения: 11
Зарегистрирован: 22.07.2011 03:11:56

Re: Создание формы в режиме run-time

Сообщение Kristina » 14.11.2012 21:18:00

Ура)) Работает))
Благодарю, добрый человек =))
Kristina
незнакомец
 
Сообщения: 4
Зарегистрирован: 11.11.2012 14:07:40

Re: Создание формы в режиме run-time

Сообщение mig-31 » 15.11.2012 13:17:00

Какая разница между
Код: Выделить всё
MyLabel := TLabel.Create(Self);

и
Код: Выделить всё
MyLabel := TLabel.Create(Form1);
mig-31
постоялец
 
Сообщения: 224
Зарегистрирован: 14.07.2011 13:46:48

Re: Создание формы в режиме run-time

Сообщение MaratIsk » 15.11.2012 14:57:23

Код: Выделить всё
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
// Just for fun, dynamically build a complete form with TEdit for each
// field in a table. TEdit are named 'Edit' with fieldname appended.
// There is an OK and a CANCEL button. The form is centered on screen.
// TEdit are filled with current record values if the Init argument is TRUE.
// Of course, you could use a classical form designed with Delphi.
function TTblDemoForm.CreateEditForm(Table : TDataSet; Init : Boolean) : TForm;
var
    Fld      : Integer;
    Edit     : TEdit;
    Lbl      : TLabel;
    Btn      : TButton;
    LblSize  : Integer;
    MaxWidth : Integer;
begin
    Result := TForm.Create(nil);
    try
        LblSize  := Canvas.TextWidth('ABCDEFGHIJ');
        MaxWidth := 0;
        Edit     := nil;   // Makes compiler happy about initialization
        for Fld := 0 to Table.FieldCount - 1 do begin
            Edit           := TEdit.Create(Result);
            Edit.Parent    := Result;
            Edit.Top       := 16 + Fld * (Edit.Height + 4);
            Edit.Left      := 16 + LblSize + 4;
            Edit.Width     := (Table.Fields[Fld].DisplayWidth + 1) * (LblSize div 10);
            Edit.MaxLength := Table.Fields[Fld].DisplayWidth;
            Edit.Name      := 'Edit' + Table.Fields[Fld].DisplayLabel;
            if Init then
                Edit.Text  := Table.Fields[Fld].DisplayText
            else
                Edit.Text  := '';
            if Edit.Width > MaxWidth then
                 MaxWidth := Edit.Width;
            Lbl            := TLabel.Create(Result);
            Lbl.Parent     := Result;
            Lbl.Caption    := Table.Fields[Fld].DisplayLabel;
            Lbl.Left       := Edit.Left - 4 - Canvas.TextWidth(Lbl.Caption);
            Lbl.Top        := Edit.Top + (Edit.Height - Lbl.height) div 2;
        end;
        Result.Width := Edit.Left + MaxWidth + 16 +
                        (Result.Width - Result.ClientWidth);
        // Create OK button
        Btn             := TButton.Create(Result);
        Btn.Parent      := Result;
        Btn.Caption     := '&OK';
        Btn.Default     := TRUE;
        Btn.ModalResult := mrOk;
        Btn.Left        := (Result.ClientWidth - 2 * Btn.Width - 4) div 2;
        Btn.Top         := Edit.Top + Edit.Height + 8;
        // Create CANCEL button
        Btn             := TButton.Create(Result);
        Btn.Parent      := Result;
        Btn.Caption     := '&Cancel';
        Btn.Cancel      := TRUE;
        Btn.ModalResult := mrCancel;
        Btn.Left        := ((Result.ClientWidth - 2 * Btn.Width - 4) div 2) + Btn.Width + 4;
        Btn.Top         := Edit.Top + Edit.Height + 8;
        // Set the Form height
        Result.Height := Btn.Top + Btn.Height + 16 +
                         (Result.Height - Result.ClientHeight);
        // Center the form on screen
        Result.Top := (Screen.Height - Result.Height) div 2;
        Result.Left := (Screen.Width - Result.Width) div 2;
    except
        Result.Free;
        Result := nil;
    end;
end;
MaratIsk
постоялец
 
Сообщения: 121
Зарегистрирован: 20.08.2009 18:15:20

Re: Создание формы в режиме run-time

Сообщение sema_90 » 10.11.2013 13:54:12

выдает ошибку на присвоение события, в чем ошибка?

img:=TImage.create(self);
timer1:=TTimer.Create(self);
label1:=TLabel.Create(self);
img.Height:=497;
img.Proportional:=true;
img.Width:=665;
img.Top:=0;
img.Left:=0;
img.Parent:=Self;
label1.Parent:=Self;
timer1.Interval:=1000;
timer1.Enabled:=false;
label1.top:=520;
label1.Left:=272;
label1.Height:=13;
label1.Width:=27;
label1.Caption:='caption';
label1.Visible:=true;
img.OnClick:=imgClk(Sender);
timer1.OnTimer:=Timer;
sema_90
незнакомец
 
Сообщения: 6
Зарегистрирован: 10.11.2013 13:50:31

Re: Создание формы в режиме run-time

Сообщение ssadragon » 10.11.2013 18:15:48

sema_90 писал(а):img.OnClick:=imgClk(Sender);
timer1.OnTimer:=Timer;

Так не правильно!!!
Вот так правильно:
Код: Выделить всё
img.OnClick:=@imgClk;
timer1.OnTimer:=@Timer;
ssadragon
постоялец
 
Сообщения: 148
Зарегистрирован: 03.12.2012 20:21:35

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 231

Рейтинг@Mail.ru