Форум: "Начинающим";
Текущий архив: 2005.10.16;
Скачать: [xml.tar.bz2];
ВнизWith Tpanel.Create(scroolbox).... Найти похожие ветки
← →
kot andrei © (2005-09-12 17:31) [80]что так и говорит...
Warning[17]: Может не работать.
Error[17]: Действительно не работает.
← →
Игорь Шевченко © (2005-09-12 17:33) [81]
> F := TForm.Create(Form1);
F := TForm.Create(nil);
← →
Digitman © (2005-09-12 17:33) [82]
> ananax (12.09.05 17:25) [79]
> Как мне действовать?
для начала понять, что и L.Name и F.Name есть обращения к опубликованному СВОЙСТВУ КОМПОНЕНТА.
св-во объекта (экз-ра класса-наследника) класса TComponent НЕ может иметь значения, содержащие символы кириллицы (*).
Объекты классов И TLabel И TForm - это КОМПОНЕТНТЫ, потому что они являются экз-рами классов-наследников класса TComponent.
а раз так, то см. (*)
← →
ananax (2005-09-12 17:56) [83]АГА!!!
Вот оказываестя что! Интересно!
Имя дать смог..... Но как теперь изменить свойства найденного компонента?
FindComponent("abcdef") видимо для других целей...
← →
Игорь Шевченко © (2005-09-12 18:01) [84]ananax (12.09.05 17:56) [83]
А собственно, форму ты так не создашь, поэтому FindComponent не сработает.
Кроме того, список всех созданных форм находится в списке Screen.Forms
← →
Digitman © (2005-09-12 18:06) [85]
> как теперь изменить свойства найденного компонента?
обычным образом
Идентификатор.Свойство := НовоеЗначениеЭтогоСвойства;
> FindComponent("abcdef") видимо для других целей
да, для других .. а именно - для поиска/идентификации компонента по имени в списке компонентов, владельцем корогого является компонент, метод FindComponent() которого ты вызываешь
← →
ananax (2005-09-13 11:05) [86]Уж очень разрозненно как-то получается...
с объяснениями..
Подскажите, что можно по данной теме почитать... Перелистал свои домашние книжки, все что-то не то... В примерах тоже только совсем примитив ((((
← →
Digitman © (2005-09-13 11:29) [87]
> ananax (13.09.05 11:05) [86]
тебе следует понять, что в среде Делфи компонентом считается любой класс/объект-наследник класса TComponent
форма (т.е. класс/объект-наследник класса TForm) - не исключение, это тоже компонент
- любой компонент в среде Делфи имеет св-во Owner, которое либо ссылается на заведомо существующего владельца (компонент-владелец) данного компонента (объект-владелец при своем уничтожении неявно ответственен уничтожение всех объектов, зн-е св-ва Owner которых есть ссылка на уничтожаемый объект-владелец) либо хранит nil, что означает отсутствие заведомо указанного компонента-владельца; св-во Owner любого компонента указывается при его создании/конструировании и не м.б. изменено после создания/конструирования
- любой компонент в среде Делфи имеет св-во Name, зн-е которого м.б. либо пустой строкой либо строкой символов (лат.алфавит + алф.-цифр. символы + некоторые спец.символы
- если зн-е св-ва Name компонента не пустое, оно д.б. уникальным в пределах значений св-в Name каждого из компонентов в св-ве-списке Components[] того компонента, который "владеет" данным компонентом; именно на этом правиле основана логика работы метода любого компонента FindComponent()
← →
ananax (2005-09-13 14:48) [88]ок. это я вроде понял.
Теперь дальше:
procedure MyPr;
var
f: TForm;
b: TButton;
begin
f:=TForm.Create(Form1);
b:=TButton.Create(f);
b.Parent:=f;
b.Visible:=True;
f.ShowModal;
end;
Так?
f и b локальные переменные... да и если я несколько раз вызову эту процедуру (вместо ShowModal Visible:= True), то создастся несколько форм.
как получить указатель на созданные формы, чтобы их в последствии можно было изменить... я понимаю, что практически это не нужно (по крайней мере мне), но для общего развития не помешало бы научиться это делать.
← →
Digitman © (2005-09-13 15:10) [89]
> ananax (13.09.05 14:48) [88]
вникай .. я комментирую каждую твою строчку :
//создать объект-компонент класса TForm
//владельцем создаваемого объекта назначить объект-компонент, на кототрый ссылается значение переменной Form1
//ссылку на созданный объект-компонент записать в переменную f
f:=TForm.Create(Form1);
//создать объект-компонент класса TButton
//владельцем создаваемого объекта назначить объект-компонент, на кототрый ссылается значение переменной f
//ссылку на созданный объект-компонент записать в переменную b
b:=TButton.Create(f);
//назначить с-ву Parent объекта, ссылка на который хранится в переменной b, значение, равное ссылке на объект, хранящейся в переменной f
b.Parent:=f;
//указать, что на объекте-компоненте-форме, ссылка на который хранится в переменной f, объект-компонент-"кнопка" с этого момента должна быть видимой
b.Visible:=True;
//показать модально объект-компонент-форму, ссылка на который хранится в переменной f
f.ShowModal;
> f и b локальные переменные
это значит, что время их жизни равно времени жизни той п/программы, где эти переменные объявлены.
непосредственно после возврата из п/программы эти переменные более не существуют в памяти, следовательно хранимые в них значения (ссылки на некие объекты) безвозвратно утеряны.
НО !
при
TForm.Create(Form1);
ссылка на только что созданный объект-форму будет фигурировать в списке Screen.Forms[] вплоть до момента вызова метода-деструктора ЭТОГО объекта-формы
а поскольку владельцем объекта-компонента b: TButton является тот самый объект-форма, который таки пока еще фигурирует в списке Screen.Forms[], его всегда можно найти методом FindComponent(имя_компонента) среди прочих объектов-компонентов на этом объекте-форме - все эти объекты-компоненты имеют владельцем тот самый объект-форму и имеют уникальное значение св-ва Name
← →
msguns © (2005-09-13 16:11) [90]>Digitman © (13.09.05 15:10) [89]
Все это, конечно, круто и правильно, но..
А почему везде упоминается слово компонент ? Если надо создать экземпляр класса, порожденного не от TComponent, с ним что, надо шаманить по-особенному ?
;))
← →
ananax (2005-09-14 14:51) [91]Огромное спасибо Digitman!
Вроде бы я это понял, только вот вопрос:
если по клику у меня будет выполняться описанная выше процедура, то получается, что моя ссылка (F) переписовается каждый раз, когда я тыкаю по этой кнопке... Так? Те стоит действовать что-то вроде динамического массива создать fff: array of TForm.... попробую так... есть ли другое решение?
← →
Digitman © (2005-09-14 15:07) [92]
> msguns © (13.09.05 16:11) [90]
> Если надо создать экземпляр класса, порожденного не от
> TComponent, с ним что, надо шаманить по-особенному ?
а разве нет ?
и в чем "шаманство". по-твоему, заключается ?
← →
Digitman © (2005-09-14 15:16) [93]
> ananax (14.09.05 14:51) [91]
> если по клику у меня будет выполняться описанная выше процедура,
> то получается, что моя ссылка (F) переписовается каждый
> раз, когда я тыкаю по этой кнопке... Так?
судя по описанной выше процедуре - не так.
твоя переменная F - это локальная переменная процедуры, она "живет" только при "жизни" той самой процедуры, где F объявлена в кач-ве локальной.
в дан.случае ты ничего не "переписываешь" - ты просто записываешь во "временную" переменную некое значение (ссылку на только что созданный объект), потом где-то в той же процедуре используешь эту переменную и ее значение, после чего (т.е. после возврата из процедуры) эта переменная благополучно "умирает", унося с собой "в могилу" свое содержимое.
← →
ananax (2005-09-14 16:00) [94]Тогда как будет правельнее сделать?
1. через локальные переменные и FindComponent() или
2. через глобальные массивы и уже обращаться к форме через массив?
Если 1, то возникает вопрос:
как после нахождения компонента (формы и всего, что на ней находится) можно изменить, скажем, лейбл лежащий на форме? У меня не получилось...
я сделал:
FindComponent("abcdef").<а тут только общие для TComponent процедуры и совйства...>;
← →
Digitman © (2005-09-14 18:38) [95]
> FindComponent("abcdef").<а тут только общие для TComponent
> процедуры и совйства...>;
приведи рез-т работы FindComponent() к нужному типу
например, если ты точно знаешь, что на форме F есть компонент класса TLabel с именем "abcdef", то обратиться, например, к св-ву Caption этого компонента проще простого :
TLabel(F.FindComponent("abcdef")).Caption := "....";
← →
ananax (2005-09-19 10:08) [96]ДА! Точно! DigitMan, ты просто монстр!
я сделал немного по другому, но смысл, видимо, тотже.
Вроде все работает, только вот хотелось сделать код краси"вее.
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
bnNew: TButton;
cbList: TComboBox;
edMsg: TEdit;
bnSend: TButton;
procedure bnNewClick(Sender: TObject);
procedure bnClick(Sender: TObject);
procedure bnSendClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
f: array[0..100] of TForm;
i: Integer = 0;
implementation
{$R *.dfm}
procedure TForm1.bnClick(Sender: TObject);
begin
with Sender as TButton do
begin
with GetParentComponent as TForm do
begin
Close;
end;
end;
end;
procedure NewWindow;
begin
f[i] := TForm.Create(Form1);
//Само окно
with f[i] do
begin
Name := "f"+IntToStr(i);
Caption := Name;
Width := 200;
Height := 200;
Top := 100;
Left := 100;
Visible := True;
end;
//Кнопка закрытия
with TButton.Create(f[i]) do
begin
Name := "b"+IntToStr(i);
Caption := "Close";
top := 130;
left := 10;
Visible := True;
Parent := f[i];
OnClick := Form1.bnClick;
end;
//Мемо для текста
with TMemo.Create(f[i]) do
begin
Name := "m"+ IntToStr(i);
Text := "";
top :=1;
left :=1;
width := 190;
height := 120;
Visible := True;
Parent := f[i];
end;
i := i+1;
end;
procedure TForm1.bnNewClick(Sender: TObject);
begin
NewWindow;
cbList.Items.Add(IntToStr(i-1));
end;
procedure TForm1.bnSendClick(Sender: TObject);
begin
if cbList.ItemIndex<>-1 then
with f[cbList.ItemIndex].FindComponent("m"+IntToStr(cbList.ItemIndex)) as TMemo do
begin
Lines.Add(edMsg.Text);
end;
end;
end.
Ругайте! Не стесняйтесь!
← →
Leonid Troyanovsky © (2005-09-19 11:23) [97]
> ananax (19.09.05 10:08) [96]
> Ругайте! Не стесняйтесь!
1. Глобальные переменные - MD, есть Screen, есть Forms.
2. Формы удобно проектировать в дизайнере (отдельный юнит),
убирая из autocreate. Если форм много, то их, видимо, лучше
уничтожать при закрытии (action := caFree).
3. Ссылки в комбобоксе должны обновляться при уничтожении
(a propos?) формы, RTFM: Notification.
--
Regards, LVT.
← →
ananax (2005-09-19 12:13) [98]Ага!
Все верно!
те делаем так...
procedure TForm1.bnClick(Sender: TObject);
begin
with Sender as TButton do
begin
with GetParentComponent as TForm do
begin
action := caFree;
end;
end;
end;
> 2. Формы удобно
Так вся фишка была в том, чтобы их создавать динамически...
если знаешь, как по "шаблону" создавать формы (не чайлды) пиши :)
> 1. Глобальные переменные
А можно про это поподробнее? что не так?
← →
ananax (2005-09-19 12:15) [99]
> procedure TForm1.bnClick(Sender: TObject);
> begin
> with Sender as TButton do
> begin
> with GetParentComponent as TForm do
> begin
> action := caFree;
> end;
> end;
> end;
не работает (((((
← →
msguns © (2005-09-19 13:00) [100]>ananax (19.09.05 12:15) [99]
>не работает (((((
И не должно.
← →
Leonid Troyanovsky © (2005-09-19 13:00) [101]
> ananax (19.09.05 12:13) [98]
> те делаем так...
> with GetParentComponent as TForm do
> begin
> action := caFree;
> end;
> end;
Action := caFree делается в OnClose той самой формы.
Или, если уж на то пошло - в DoClose; override.
Кроме того, GetParentComponent здесь ни к чему.
По смыслу: в цепочке Parent"ов найти контрол класса формы,
или, на худой конец, это Owner.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2005-09-19 13:10) [102]
> ananax (19.09.05 12:13) [98]
> Так вся фишка была в том, чтобы их создавать динамически.
> ..
> если знаешь, как по "шаблону" создавать формы (не чайлды)
> пиши :)
Формы и так создаются по шаблону, записанному в ресурс
экзешника. Оный шаблон можно и просмотреть ObjectBinaryToText,
а можно и изменить путем ObjectTextToBinary.
RTFM: VCL Reference
WriteComponent, Seek, ObjectBinaryToText, DataString, ObjectTextToBinary,
ReadComponent Example
--
Regards, LVT.
← →
Leonid Troyanovsky © (2005-09-19 13:24) [103]
> ananax (19.09.05 12:13) [98]
> > 1. Глобальные переменные
>
> А можно про это поподробнее? что не так?
Глобальных переменных быть не должно.
Неизбежное зло - это переменные, которые уже объявлены Борландом,
т.е., Screen, Application, Printer и т.д. Т.е., умножать их кол-во не стоит.
Во избежании неприятностей никогда не следует использовать
автоматически генерируемые переменные типа FormX: TFormX.
Ну, а если, вдруг, понадобился, скажем список создаваемых
форм (или массив), то его можно сделать полем формы.
Хотя, лучше не создавать список, а каждый раз выделять из Screen.Forms
те, что имеют, например, искомый клас, т.е. Screen.Forms[i] is TFormX.
Кроме того, нужно быть весьма осторожным с регулярными процедурами,
типа NewWindow, особенно если они вдруг описаны в разделе интерфейса.
--
Regards, LVT.
← →
msguns © (2005-09-19 13:27) [104]>ananax
Диджитмэн абсолютно верно объяснил как можно использовать объекты не по их именам. Только вот мне лично совершенно непонятно, почему при этом он "плясал" от TComponent, ведь далеко не все объекты приложения являются оными. Есть еще TControls, который, имхо, существеннее при анализе динамически создаваемых визуальных объектов, кроме того, подлежит "контейнеризации", т.е. позволяет перебирать, например, все эдиты, расположенные на панели.
Что же касается формы "по шаблону", то есть два весьма удобных способа:
1. Создание базового класса с визуальной конструкцией внешнего вида и инкапсуляцией в нем большинства методов
2. Использование вместо форм фрэймов, также сконструированных в дизайне во вполне комфортабельных условиях ;) Собственно, для того и придуманы.
← →
Игорь Шевченко © (2005-09-19 13:28) [105]Leonid Troyanovsky © (19.09.05 13:24) [103]
> Во избежании неприятностей никогда не следует использовать
>
> автоматически генерируемые переменные типа FormX: TFormX.
>
Во избежание каких именно неприятностей ?
← →
Leonid Troyanovsky © (2005-09-19 14:24) [106]
> Игорь Шевченко © (19.09.05 13:28) [105]
> > Во избежании неприятностей никогда не следует использовать
> > автоматически генерируемые переменные типа FormX: TFormX.
> Во избежание каких именно неприятностей ?
Для начинающих наиболее распространен вариант с потерей ссылок
при неоднократном создании формы.
Да и, вообще, наличие оной переменной толкает их к смешению стилей
и bad design (в смысле ООП).
--
Regards, LVT.
← →
ananax (2005-09-19 14:35) [107]
> msguns ©
Действительно стоящие замечания!
Глобальные переменные мне самому не нравятся ))))
Но
Action := caFree все равно не работает((( пишет
[Error] main.pas(74): Incompatible types: "TBasicAction" and "TCloseAction"
> Leonid Troyanovsky ©
Мда... про базовый класс - действительно интересно... надо почитать, как это делается.
← →
Leonid Troyanovsky © (2005-09-19 14:42) [108]
> msguns © (19.09.05 13:27) [104]
> непонятно, почему при этом он "плясал" от TComponent, ведь
> далеко не все объекты приложения являются оными. Есть еще
> TControls, который, имхо, существеннее при анализе динамически
> создаваемых визуальных объектов, кроме того, подлежит "контейнеризации",
>
TControl is TComponent.
А контейнером для него может быть лишь TWinControl.
Т.е., это сужение предметной области.
Поэтому, оно и "существеннее".
Например, для динамически создаваемых контролов отсутствие Owner -
нормальное явление, а отсутствие Parent - экзотика.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2005-09-19 14:53) [109]
> ananax (19.09.05 14:35) [107]
> Глобальные переменные мне самому не нравятся ))))
> Но
> Action := caFree все равно не работает((( пишет
У формы есть событие OnClose, там нужная переменная и
фигурирует.
Внимательней надо, внимательней ;)
--
Regards, LVT.
← →
msguns © (2005-09-19 15:23) [110]>Leonid Troyanovsky © (19.09.05 14:42) [108]
>TControl is TComponent.
Сам же и подтверждаешь мои слова:
любой контрол есть компонент, но не любой компонент есть контрол
Отсюда делаем вывод, что при поиске визуального контрола (читаем сабж про динамически создаваемые группы контролов нв контейнере (форме, фрэйме, панели..) предпочтительнее перебирать контролы, чем компоненты, т.к. последних может быть существенно больше.
Самое же главное отличие в том, что Components/ComponentCount адресует только "подотчетные" (т.е. у кого овнер - адресующийся объект) объекты, а Controls/ControlCount - содержащиеся внутри (Parent) объекты, что для поиска-перебора визуальных кнтролов внутри контейнера-носителя куда важнее.
Другими словами, соданные на панели эдиты могут иметь собственника форму и через TPanel.Component к ним не обратишься. А через Controls запросто.
← →
Leonid Troyanovsky © (2005-09-19 15:37) [111]
> msguns © (19.09.05 15:23) [110]
> >TControl is TComponent.
> Сам же и подтверждаешь мои слова:
> любой контрол есть компонент, но не любой компонент есть
> контрол
Это, конечно, слова правильные, но не похожи "от TComponent,
ведь далеко не все объекты приложения являются оными".
А уж TControl, в отличии от многих других объектов, is TComponent.
В остальном, смысл моих слов понят почти правильно ;)
--
Regards, LVT.
← →
Игорь Шевченко © (2005-09-19 15:40) [112]Leonid Troyanovsky © (19.09.05 14:24) [106]
> Для начинающих наиболее распространен вариант с потерей
> ссылок
> при неоднократном создании формы.
> Да и, вообще, наличие оной переменной толкает их к смешению
> стилей
> и bad design (в смысле ООП).
Я бы не сказал, что использование переменных есть bad design в смысле ООП.
Кроме того, Borland зачем-то сделал ведь такую конструкцию, с самой первой версии она в Delphi существует - Application.CreateForm. Для DataModule"й, например, очень удобно - создаешь один раз, используешь по мере надобности в нужных местах.
С уважением,
← →
msguns © (2005-09-19 15:42) [113]>Leonid Troyanovsky © (19.09.05 15:37) [111]
>Это, конечно, слова правильные, но не похожи "от TComponent,
ведь далеко не все объекты приложения являются оными".
Да уж.. Иногда перечитаешь то, что написал по-другому и ужаснешься ;))
Я хотел сказать кратко то, что подробно изложил в [110], ан не вышло ;((
← →
Leonid Troyanovsky © (2005-09-19 16:33) [114]
> Игорь Шевченко © (19.09.05 15:40) [112]
> Я бы не сказал, что использование переменных есть bad design
> в смысле ООП.
Вообще, с глобальными FormX легко согрешить не только
начинающему, но и даже более продвинутому ООПрограммисту,
когда он впервые сталкивается с необходимостью, например,
использовать Win32 API, скажем некий Enum* из объектного кода.
Ведь тот же MakeObjectInstance открывают для себя после (пары) шишек.
> Кроме того, Borland зачем-то сделал ведь такую конструкцию,
> с самой первой версии она в Delphi существует - Application.
> CreateForm. Для DataModule"й, например, очень удобно - создаешь
> один раз, используешь по мере надобности в нужных местах.
Им, наверное, влом было чего-то менять в концепции главной
формы приложения ;)
Да, и угодить они старались дезертирам бейсика, а не c++, IMHO.
Ну, а по-поводу как лучше на rsdn.ru\delphi было даже что-то
вроде конкурса. Затолкали всех сторонники IInterface.
--
Regards, LVT.
← →
Игорь Шевченко © (2005-09-19 16:38) [115]Leonid Troyanovsky © (19.09.05 16:33) [114]
> Ну, а по-поводу как лучше на rsdn.ru\delphi было даже что-
> то
> вроде конкурса. Затолкали всех сторонники IInterface.
Что касается теории и пуризма, я конечно понимаю, тем более, что rsdn особой любовью к Delphi не блещет :)
Но зачем изобретать себе дополнительные трудности, уже перестаю понимать, делать всякие интерфейсы и прочее. Убрать форму из AutoCreate может каждый, два клика мышью :)
Я всегда использую эти переменный для тех форм, которые гарантировано будут в единственном экземпляре и создаются в момент инициализации приложения. Например, для главной формы и для всегда необходимых датамодулей.
Страницы: 1 2 3 вся ветка
Форум: "Начинающим";
Текущий архив: 2005.10.16;
Скачать: [xml.tar.bz2];
Память: 0.7 MB
Время: 0.065 c