Создание формы в режиме run-time
Модератор: Модераторы
Создание формы в режиме run-time
Здравствуйте.
Лазарус изучаю не больше недели. До этого ничего кроме си++ не знала. Очень нужна ваша помощь.Есть форма, на ней две кнопки. Первая создает приложение в в design-time, а вторая тоже самое но в run-time.Настройки хранятся в ini файле С design-time я разобралась, а вот с run-time не понятно. Что значит "описать ссылки на компоненты" ? Как это ? как ими после пользоваться? Что бы разобраться мне бы хватило примерчика....например с Label? как его создать в динамическом режиме? помогите=)
Лазарус изучаю не больше недели. До этого ничего кроме си++ не знала. Очень нужна ваша помощь.Есть форма, на ней две кнопки. Первая создает приложение в в design-time, а вторая тоже самое но в run-time.Настройки хранятся в ini файле С design-time я разобралась, а вот с run-time не понятно. Что значит "описать ссылки на компоненты" ? Как это ? как ими после пользоваться? Что бы разобраться мне бы хватило примерчика....например с Label? как его создать в динамическом режиме? помогите=)
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;
Вот, в принципе, и всё.
Допустим, Вам нужно создать 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 писал(а):MyLabel.Left:=100;MyLabel.Top:=100;
Не учите плохому
BeginFormUpdate;
...
SetBounds(ALeft, ATop, AWidth, AHeight: integer);
...
EndFormUpdate;
Vadim писал(а):MyLabel.Show;
По моему, это не надо. А у формы можно сделать update или Invalidate, а можно и не делать, если EndFormUpdate правильно отработает. В Лазарусе нельзя быть во всем уверенным точно... И еще, Создание компонентов в рантайм на форме лучше делать конструктором, а не по кнопке. Просто не могу представить, что нужно именно по кнопке. А что будет при повторном нажатии кнопки?
stikriz писал(а):Не учите плохому
Не вижу разницы. Особенно на ненагруженной всякими разными эвентами форме.
stikriz писал(а):По моему, это не надо.
Это так, на всякий случай.
stikriz писал(а): И еще, Создание компонентов в рантайм на форме лучше делать конструктором, а не по кнопке.
В каком то смысле я с Вами согласен. Но, наверное, человек просто учится это делать и ему нужно узнать механизм.
stikriz писал(а):А что будет при повторном нажатии кнопки?
Именно то, что Вы и подумали - старый лэйбел удёт в нирвану, а на его месте будет новый.
>>Новый автоматом убъётся, а старый так и останется висеть в нирване, он уже недоступен.
Он доступен и убъется такимже автоматом как новый, благодаря:
Имхо новичкам не стоит вдаваться в "сложности" типа:
Когда на форме всё начнет мелькать и ездить, а принципы создания рандайм контролов будут поняты (надеюсь иакже станет понятно почему контролы замелькали при каждом изменении), тогда стоит задуматься о более оптимальном создании
Для начала вполне достаточно:
Единственное - MyLabel.Show вобщемто не нужен - контрол виден по умолчанию после присвоения Parent`а, а назначать MyLabel.Parent лучше в конце всех настроек, чтоб эти настройки не мелькали на экране:
Он доступен и убъется такимже автоматом как новый, благодаря:
Код: Выделить всё
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;Так то вроде понятно, но создается пустая форма.. в чем проблема?
вот код модуля
вот код модуля
Код: Выделить всё
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.
>>Free;;
это что? не успев создать убиваем?
Ну и потомучто форма всетаки создается, думаю FormCreate не назначено в соответствующее сабытие
Добавлено спустя 3 минуты 55 секунд:
Или Free;; относится к TIniFile? тогда может цикл не крутится, sec.Count=0?
это что? не успев создать убиваем?
Ну и потомучто форма всетаки создается, думаю FormCreate не назначено в соответствующее сабытие
Добавлено спустя 3 минуты 55 секунд:
Или Free;; относится к TIniFile? тогда может цикл не крутится, sec.Count=0?
Из возможных проблем:
1. Вы уверены, что Ваш INI-файл загрузился?
2. Вы уверены, что в выбранных в цикле секциях содержаться соответствующие ключи с значениями.
3. В каком месте формы должен располагаться создаваемый лэйбл? Вы уверены, что смотрите именно в это место?
1. Вы уверены, что Ваш INI-файл загрузился?
2. Вы уверены, что в выбранных в цикле секциях содержаться соответствующие ключи с значениями.
3. В каком месте формы должен располагаться создаваемый лэйбл? Вы уверены, что смотрите именно в это место?
Создаю в точности как вы советовали.....даже без ини файла, что бы точно не там проблема была
но все равно форма создается пустая...я уже не знаю в чем еще может быть дело((
Код: Выделить всё
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.
но все равно форма создается пустая...я уже не знаю в чем еще может быть дело((
Код: Выделить всё
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.
Ура)) Работает))
Благодарю, добрый человек =))
Благодарю, добрый человек =))
Какая разница между
и
Код: Выделить всё
MyLabel := TLabel.Create(Self);и
Код: Выделить всё
MyLabel := TLabel.Create(Form1);Код: Выделить всё
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
// 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;
выдает ошибку на присвоение события, в чем ошибка?
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;
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 писал(а):img.OnClick:=imgClk(Sender);
timer1.OnTimer:=Timer;
Так не правильно!!!
Вот так правильно:
Код: Выделить всё
img.OnClick:=@imgClk;
timer1.OnTimer:=@Timer;