Форум: "Основная";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];
ВнизСохранение компонентов в файл и чтение из него Найти похожие ветки
← →
DmitryNekl (2004-07-19 18:07) [0]Добрый день. Не знаю, может, мне в БД надо... В общем, вопрос такой:
Создаю форму:procedure TForm1.FormCreate(Sender: TObject);
begin
ADOConnection1:=TADOConnection.Create(self);
ADOConnection1.Name:="ADOConnection1";
ADOConnection1.LoginPrompt:=False;
ADOConnection1.ConnectionString:="...";
ADOConnection1.GetTableNames(Combobox1.Items, False);
ADOQuery1:=TADOQuery.Create(self);
ADOQuery1.Connection:=ADOConnection1;
DataSource1:=TDataSource.Create(self);
DataSource1.Name:="DataSource1";
DataSource1.DataSet:=ADOQuery1;
DBGrid1:=TDBGrid.Create(Form1);
DBGrid1.Name:="DBGrid1";
DBGrid1.Parent:=Form1;
DBGrid1.DataSource:=DataSource1;
end;
Потом что-то делаю с ней, и в гриде отображаются какие-то данные. После этого сохраняю компоненты в файл:procedure TForm1.Button6Click(Sender: TObject); // сохраняем табличку в файл
begin
ADOConnection1.Name:="";
WriteComponentResFile("ADOConnection1.dfm", ADOConnection1);
ADOConnection1.Name:="ADOConnection1";
ADOQuery1.Name:="";
WriteComponentResFile("ADOQuery1.dfm", ADOQuery1);
ADOQuery1.Name:="ADOQuery1";
DataSource1.Name:="";
WriteComponentResFile("DataSource1", DataSource1);
DataSource1.Name:="DataSource1";
DBGrid1.Name:="";
WriteComponentResFile("DBGrid1.dfm", DBGrid1);
DBGrid1.Name:="DBGrid1";
end;
А потом пытаюсь прочесть из файла (в другую форму, чистую):procedure TForm1.Button7Click(Sender: TObject);
var F: TForm;
begin
F:=TForm4.Create(Form1);
end;constructor TForm4.Create(AOwner: TComponent); // override;
var
fname: String;
begin
RegisterClasses([TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
CreateNew(AOwner);
ReadComponentResFile("ADOConnection1.dfm", Self);
ReadComponentResFile("ADOQuery1.dfm", Self);
ReadComponentResFile("ADODataSource1.dfm", Self);
ReadComponentResFile("DBGrid1.dfm", Self);
Self.Name:="";
Self.Caption:="...";
Self.Show;
end;
и получаю ошибку "Property Connected does not exist"...
Как бороться? Заранее спасибо!
← →
Defunct © (2004-07-20 03:29) [1]Что-то я вопрос не понял...
что надо сохранить?
← →
DmitryNekl (2004-07-20 09:09) [2]Исходно задача такая. Пишу приложение для работы с БД. Хочу сделать максимально гибко настраиваемым.
В частности, можно сделать так: настроить все поля в редакторе полей, визуально сформировать соответствующий грид (чтобы названия колонок по-русски отображались и т.д.). Но тогда мы жестко привязываемся к структуре таблиц базы.
А можно на этапе выполнения подключаться к таблице и все вышеперечисленные вещи настраивать. А чтобы не делать это каждый раз, хочется сохранять настроенные компоненты (настроенные - значит с сохранением инфы о таблице, полях и т.д.) в файл и загружать их по мере необходимости.
Вот, собственно, и пытаюсь сначала сохранить, а потом - восстановить...
← →
Sun bittern © (2004-07-20 09:09) [3]WriteComponent не сохраняет указатели на внешние компоненты.
← →
DmitryNekl (2004-07-20 09:17) [4]А как это можно реализовать?
← →
Sun bittern © (2004-07-20 09:23) [5]А, ветку на пенсию уже отправели. Ищи сайт TDElphi (адрес непомню) и на этом сайте ищи компоненты LMDTools (там говорят дезайнер есть, но еще не смотрел, можещь тпм реализацию глянуть). Ну или этот же пакет ищи гденибудь в другом месте.
← →
DmitryNekl (2004-07-20 10:28) [6]В общем, научился я сохранять и загружать:
Сохранение:
f := TFileStream.Create("c:\stream.vcl", fmCreate);
f.WriteComponent(DBGrid1);
f.Free;
Загрузка:
f := TFileStream.Create("c:\stream.vcl", fmOpenRead);
f.ReadComponent(DBGrid1);
f.Free;
Все работает, но интересный глюк (или я чего не понимаю):
Есть исходная форма, на которой расположен этот самый грид. Я его сохраняю в файл и потом загружаю на другую форму. В момент загрузки этот грид с первой формы исчезает :(.
С чем это может быть связано и как, собственно, бороться?
← →
Sun bittern © (2004-07-20 11:08) [7]>> f.ReadComponent(DBGrid1);
Form2 := TForm(f.ReadComponent(DBGrid1));
Может так?
← →
DmitryNekl (2004-07-20 11:16) [8]А почему так? Я код не полностью привел, на самом деле в конструкторе второй формы делаю так:
RegisterClasses([TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
CreateNew(AOwner);
f:=TFileStream.Create("c:\stream.vcl", fmOpenRead);
f.ReadComponent(DBGrid1);
f.Free;
DBGrid1.Align:=alClient;
DBGrid1.Parent:=Self;
DBGrid1.Visible:=True;
У меня вопрос, в общем-то - почему исчезает грид с первой формы???
← →
Sun bittern © (2004-07-20 11:37) [9]var
FS: TFileStream;
A: TComponent;
begin
FS := TFileStream.Create("Nova.dfa", fmOpenRead or fmShareDenyRead);
try
A := FS.ReadComponent(nil);
if A is TControl then
TControl(A).Parent := Form2;
finally
FS.Free;
end;
end;
← →
DmitryNekl (2004-07-20 11:53) [10]Спасибо, все заработало! :)
Хотя я и не понимаю, почему :).
Можно ссылочку на какую-нить статью на эту тему?
← →
Sun bittern © (2004-07-20 12:14) [11]>> Хотя я и не понимаю, почему :).
FS.ReadComponent(nil);
А гдето в инете давно данный пример откопал. Возможно на королевстве дельфи.
Кстати
DBGrid1.Align:=alClient;
DBGrid1.Parent:=Self;
DBGrid1.Visible:=True;
Данные Published свойства (те что видны в инспекторе объектво) сохраняются WriteComponent (кроме, как я описал выше линек на внешние компоненты) и изменять необязательно. В данном случае Parent не Published свойство, вот и портебовалось указать ему родителя.
← →
DmitryNekl (2004-07-20 13:10) [12]Нашел еще неприятную особенность... в качестве всяких ADOQuery, ADOConnection при загрузке формы используются те, которые находятся на форме, с которой происходит сохранение грида.
Как бы мне вместе с гридом сохранять и компоненты ADOQuery, ADOConnection, DataSource, а при загрузке грида загружать и их и подключать к гриду?
← →
Sun bittern © (2004-07-20 13:29) [13]Может тебе не кусками сохранять, а всю форму в поток слхранить? Как этот вариант?
← →
DmitryNekl (2004-07-20 14:07) [14]Да, это я умею... но тут прикол в том, что редактирую я все это дело в одной форме, а открываю настроенный грид - в другой. А в первой всяких "лишних" наворотов до дури...
← →
Sun bittern © (2004-07-20 14:10) [15]Ты свой мини дизайнер создаешь чтоли :)
← →
DmitryNekl (2004-07-20 14:15) [16]Не совсем... но стало близко к нему :)
Изначально я делал приложение для работы с БД, но структура БД стала меняться слишком часто... в общем, я решил, что это оптимально :). И в принципе, сделал... осталось тока научиться сохранять/загружать...
А по существу есть мысли?
← →
Sun bittern © (2004-07-20 16:59) [17]>> А в первой всяких "лишних" наворотов до дури...
1. Дурь можно вынести на отдельную форму - яля панель инструментов
2. Или. Кинуть нужные компоненты на отдельный TWinControl (например TPanel). Тоесть точто нужно сохранить просаем на эту панельку. Но чтобы вместе с этой панелькой сохранились и компоненты наней, лежащие на ней компоненты должны пренадлежать ей т.е. она должна являться хозяином для них (Owner). Далее сохранить панель в файл (указать только панель, раз для компонентов хозяином является панель, то то что на ней автоматически сохранится в файл)
3. Ну можно еще чего насоченять ;)
← →
DmitryNekl (2004-07-20 18:04) [18]О, классная мысль (про панельку)! :)
Непременно попробую, спасибо огромное! :)
← →
DmitryNekl (2004-07-21 10:17) [19]Хрень какая-то... Не работает. Т.е.:
procedure TForm1.FormCreate(Sender: TObject);
begin
Panel1:=TPanel.Create(Form1);
Panel1.Parent:=Form1;
ADOConnection1:=TADOConnection.Create(Panel1);
ADOConnection1.Name:="ADOConnection1";
ADOConnection1.LoginPrompt:=False;
ADOConnection1.ConnectionString:="...";
...
ADOQuery1:=TADOQuery.Create(Panel1);
ADOQuery1.Connection:=ADOConnection1;
DataSource1:=TDataSource.Create(Panel1);
DataSource1.Name:="DataSource1";
DataSource1.DataSet:=ADOQuery1;
DBGrid1:=TDBGrid.Create(Panel1);
DBGrid1.Name:="DBGrid1";
DBGrid1.Align:=alClient;
DBGrid1.DataSource:=DataSource1;
DBGrid1.Parent:=Panel1;
end;
Потом выбираю таблицу БД, грид загружается данными... Сохраняю:procedure TForm1.Button6Click(Sender: TObject);
var f: TFileStream;
begin
f := TFileStream.Create("c:\stream1.vcl", fmCreate);
f.WriteComponent(Panel1);
f.Free;
end;
Потом читаю в другой форме:constructor TForm4.Create(AOwner: TComponent);
var
fname: String;
FS: TFileStream;
a1, a2, a3, a4: TComponent;
begin
RegisterClasses([TPanel, TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
CreateNew(AOwner);
FS := TFileStream.Create("c:\stream1.vcl", fmOpenRead or fmShareDenyRead);
try
A4 := FS.ReadComponent(nil);
if A4 is TControl then
begin
TControl(A4).Parent := Self;
TControl(A4).Align :=alClient;
end;
finally
FS.Free;
end;
end;
Форма появляется, на ней - панелька, на панельке - грид, но грид к таблице не подключен, а пустой :(
Почему? Что делать?
← →
Sun bittern © (2004-07-21 10:59) [20]Я же тебе писал WriteComponent не сохраняет указатели на внешние компоненты и методы (события). Ковыряйся в компонентах с исходниками может там нароешь.
Sun bittern © (20.07.04 09:23) [5]
Я начинал делать парсер строк для определения ссылки на компоненты и методы используя RTTI но до конца пока не доделал.
Сайт http://www.tdelphi.spb.ru/ раздел компоненты
← →
DmitryNekl (2004-07-21 11:13) [21]Что-то я не пойму. Я сохраняю панель, которая является owner-ом для:
1. DBGrid
2. ADOConnection
3. ADOQuery
4. DataSource
Вместе с панелью сохраняется грид... почему же не сохраняется все остальное? Где тут внешние компоненты?
← →
Sun bittern © (2004-07-21 11:33) [22]TDBGrid.DataSourece := MyDataSource
Вот MyDataSource и не сохранится в свойстве DataSourece компонента TDBGrid. Также как к примеру и TPopupMenu в свойстве PopupMenu компонента TPanel.
← →
Sun bittern © (2004-07-21 11:52) [23]Точнее наверно будет сказать так:
В свойстве DataSourece компонента TDBGrid не сохранится указатель на компонент MyDataSource.
← →
DmitryNekl (2004-07-21 12:00) [24]А еще интересный вопрос. После выхода из конструктора как мне до мой панельки или до грида добраться? Self.ComponentCount выдает 0 (последним оператором в конструкторе)...
← →
DmitryNekl (2004-07-21 12:03) [25]Sun bittern © (21.07.04 11:52) [23]
Точнее наверно будет сказать так:
В свойстве DataSourece компонента TDBGrid не сохранится указатель на компонент MyDataSource.
Я правильно понимаю, что все 4 компонента вместе с панелью сохранились, и достаточно настроить их взаимные связи? Тока вот добраться бы до них :)
← →
Sun bittern © (2004-07-21 12:10) [26]Self это форма? Если для компонент Owner панелька, то это действительно должно быть так.
← →
Sun bittern © (2004-07-21 12:15) [27]>> 4 компонента вместе с панелью сохранились
Если Owner у них панелька, то должны вместе сней в файл слиться.
← →
DmitryNekl (2004-07-21 12:16) [28]Да, в конструкторе формы Self - это форма. Для компонент Owner - действительно панелька. НО! КАК МНЕ ДОБРАТЬСЯ ДО КОМПОНЕНТОВ, чтобы настроить их свойства?
← →
Sun bittern © (2004-07-21 12:24) [29]Дык. Чей Owner у компонент, у того вроде и надо спрашивать. А у кого? Можешь узнать например так, псоле загрузки: DataSource1.Owner.Name
← →
DmitryNekl (2004-07-21 14:17) [30]Ничего не понимаю... в конструктор добавил:
(Panel1.Components[1] as TADOQuery).Connection:=(Panel1.Components[0] as TADOConnection);
(Panel1.Components[2] as TDataSource).DataSet:=(Panel1.Components[1] as TADOQuery);
(Panel1.Components[3] as TDBGrid).DataSource:=(Panel1.Components[2] as TDataSource);
Все работает (сообщений об ошибках нет), но грид выводится пустой...
← →
Sun bittern © (2004-07-21 15:13) [31]>> Panel1.Components[2] as TDataSource
От куда такая уверенность? Индексы могут ведь и поменяться со временем.
P.S. Можешь свой проект на мыло мне кинуть. Только без *.dcu, *.exe, *.~* и другого мусора.
← →
DmitryNekl (2004-07-21 15:27) [32]С одной стороны, могу, а с другой - это бесполезно, ибо к базе я подключаюсь в инете (MySQL), и тебе придется настроить источники данных и т.д.
Уверенность - я проверил один раз... если бы что-то изменилось, была бы ошибка приведения типов, а ее не происходит.
← →
Sun bittern © (2004-07-21 15:36) [33]DmitryNekl (21.07.04 15:27) [32]
Может компонентам адошным и таблицам надо в проперти Active в True принудительно указать?
← →
Sun bittern © (2004-07-21 15:41) [34]DmitryNekl (21.07.04 15:27) [32]
после загрузки проверь открыты ли у тебя источники данных (Active = True)
← →
DmitryNekl (2004-07-21 15:45) [35]Пробовал... однако торможу.
Смотри, фигня какая. Привожу еще раз код:
Создание компонентов на первой форме:procedure TForm1.FormCreate(Sender: TObject);
begin
Panel1:=TPanel.Create(Form1);
Panel1.Name:="Panel1";
Panel1.Left:=20;
Panel1.Width:=Form1.Width-40;
Panel1.Top:=320;
Panel1.Height:=Form1.Height div 4;
Panel1.Parent:=Form1;
ADOConnection1:=TADOConnection.Create(Panel1);
ADOConnection1.Name:="ADOConnection1";
ADOConnection1.LoginPrompt:=False;
ADOConnection1.ConnectionString:="...";
ADOQuery1:=TADOQuery.Create(Panel1);
ADOQuery1.Connection:=ADOConnection1;
DataSource1:=TDataSource.Create(Panel1);
DataSource1.Name:="DataSource1";
DataSource1.DataSet:=ADOQuery1;
DBGrid1:=TDBGrid.Create(Panel1);
DBGrid1.Name:="DBGrid1";
DBGrid1.Align:=alClient;
DBGrid1.DataSource:=DataSource1;
DBGrid1.Parent:=Panel1;
end;
Код создания второй формы:
constructor TForm4.Create(AOwner: TComponent); // override;
var
i: integer;
fname: String;
FS: TFileStream;
a4: TComponent;
begin
RegisterClasses([TPanel, TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
CreateNew(AOwner);
FS := TFileStream.Create("c:\stream1.vcl", fmOpenRead or fmShareDenyRead);
try
A4 := FS.ReadComponent(nil);
if A4 is TControl then
begin
TControl(A4).Parent:=Self;
TControl(A4).Align:=alClient;
end;
finally
FS.Free;
end;
ShowMessage(Panel1.Parent.ClassName);
(Panel1.Components[1] as TADOQuery).Connection:=(Panel1.Components[0] as TADOConnection);
(Panel1.Components[2] as TDataSource).DataSet:=(Panel1.Components[1] as TADOQuery);
(Panel1.Components[3] as TDBGrid).DataSource:=(Panel1.Components[2] as TDataSource);
Self.Name:="";
Self.Caption:="Редактирование содержимого таблицы";
Self.Show;
end;
То, что жирным выделено, до меня дошло вставить туда только что... Выводит Form1, т.е. я играю не с тем объектом.
А операторfor i:=0 to TControl(A4).ComponentCount-1 do ShowMessage (TControl(A4).Components[i].ClassName);
вставленный вместо жирного, выводит только TDBGrid... и больше нифига. Это получается, что остальные три объекта не сохраняются вместе с панелькой?
← →
Sun bittern © (2004-07-21 16:30) [36]Блин. Выходит, что сохраняются только TControl :^( Щас сам проверил.
← →
DmitryNekl (2004-07-21 16:33) [37]И что теперь делать? Что ли, сохранять каждый компонент по отдельности и загружать на форму, а потом настраивать связи?
← →
Sun bittern © (2004-07-21 16:49) [38]Не знаю поможет ли
http://delphimaster.net/view/5-1089284149/
Как второй извращщенный вариант :(
Поместить не визуальные компоненты в DataModule (для удобства)
Визуальным компонентам назначить уникальный Tag. Полсле загрузки панельки перебрать на ней контролы и проверять Tag. Например если 1, то ага, значит у тебя есть проперти DataSource и назначить ему соотвествующий DataSource из DataModule.
Но это все изврат и неудобно в дальнейшем расширять функциональность. Лучше скачать пакет компонент Sun bittern © (20.07.04 09:23) [5] и посомтреть как это профи сделали. Или создавать парсер строк (по типу *.dfm файла) с помощью RTTI.
← →
DmitryNekl (2004-07-21 17:34) [39]Извращенный вариант не пройдет: смысл именно в том, чтобы сохранять все изменения в составе и описаниях полей и т.д.
А насчет поможет ли - посмотрим... Боюсь, кода профи я не пойму... не настолько глубоко все знаю. :(
Будем учиться :)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];
Память: 0.63 MB
Время: 0.042 c