OberonCore https://forum.oberoncore.ru/ |
|
Несколько одинаковых форм https://forum.oberoncore.ru/viewtopic.php?f=24&t=4045 |
Страница 1 из 1 |
Автор: | Alexander Shiryaev [ Суббота, 11 Август, 2012 21:47 ] |
Заголовок сообщения: | Несколько одинаковых форм |
Как сделать, чтобы бьло несколько одинаковых форм, но чтобы содежимое у каждой было своё? Т.е., например, есть несколько одинаковых форм, на каждой есть текстовое поле, но связаны эти текстовые поля должны быть не с одной и той же глобальной переменной, а с разными. |
Автор: | Info21 [ Суббота, 11 Август, 2012 22:02 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Если статически, то нужно сделать несколько копий формы и привязать поля в каждой соотв. образом. Если динамически, то форма -- это обычный составной документ, его можно программно открыть для редактирования, сделать необх. привязки, а в конце открыть как форму. Работа с разными документами-контейнерами идет вполне единообразно, можно оттолкнуться от текстов. |
Автор: | Alexander Shiryaev [ Суббота, 11 Август, 2012 22:21 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Вот что я хочу сделать: Создать модуль для формы, реализовать его, связать с ним форму. Потом взять и сделать, чтобы таких форм на экране было несколько одновременно, чтобы выглядели они одинаково, чтобы реализация была одна и та же, но чтобы данные у каждой формы были свои. Потом, если я захочу изменить внешний вид или реализацию 1-й формы, то чтобы и у других форм внешний вид и реализация были такими же, как у 1-й, но при этом не хочу каждый раз копировать файлы Mod и Rsrc. Если создавать формы динамически, то наверное это будет не удобно, т.к. в этом случае нельзя будет пользоваться редактором форм. |
Автор: | Alexander Shiryaev [ Суббота, 11 Август, 2012 22:58 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Вот как это можно сделать в Delphi 7: Unit2.pas: Код: unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm2 = class(TForm) Button1: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); private x: Integer; { Private declarations } public { Public declarations } end; var Forms2: array [0..3] of TForm2; implementation {$R *.dfm} procedure TForm2.Button1Click(Sender: TObject); begin Inc(x); Label1.Caption := IntToStr(x) end; end. Unit2.dfm: Код: object Form2: TForm2 Left = 208 Top = 201 Width = 205 Height = 185 Caption = 'Form2' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False Visible = True PixelsPerInch = 96 TextHeight = 13 object Label1: TLabel Left = 32 Top = 32 Width = 32 Height = 13 Caption = 'Label1' end object Button1: TButton Left = 32 Top = 72 Width = 75 Height = 25 Caption = 'Button1' TabOrder = 0 OnClick = Button1Click end end Project1.dpr: Код: program Project1; uses Forms, Unit1 in 'Unit1.pas' {Form1}, Unit2; {$R *.res} var i: Integer; begin Application.Initialize; Application.CreateForm(TForm1, Form1); i := 0; while i < 4 do begin Application.CreateForm(TForm2, Forms2[i]); Inc(i) end; Application.Run; end. При этом можно пользовать редактором форм. Как сделать что-то похожее в BlackBox? |
Автор: | Пётр Кушнир [ Воскресенье, 12 Август, 2012 00:06 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
в ББ с текущей концепции контролов это получится непросто и костыльно |
Автор: | Info21 [ Воскресенье, 12 Август, 2012 08:30 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Alexander Shiryaev писал(а): но чтобы данные у каждой формы были свои. А куда пойдут эти данные?В ББ они автоматом попадают в глобальные переменные-интеракторы. Разные формы -- разные интеракторы. Что значит, реализация одинаковая, а данные разные? Похоже, имеется некий шаблон мышления, который надо подвергнуть деконструкции еще на стадии постановки задачи. |
Автор: | Евгений Темиргалеев [ Воскресенье, 12 Август, 2012 08:32 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Alexander Shiryaev писал(а): Вот что я хочу сделать: Не хотите копировать руками --- копируйте программно, что Info21 Вам и предложил. Работа программиста и заключается в том, чтобы реализовывать алгоритмы, перекладывая их рутинное исполнение на машину ; ничего костыльного в предложенном нет, всё делается штатными способами.Создать модуль для формы, реализовать его, связать с ним форму. Потом взять и сделать, чтобы таких форм на экране было несколько одновременно, чтобы выглядели они одинаково, чтобы реализация была одна и та же, но чтобы данные у каждой формы были свои. Потом, если я захочу изменить внешний вид или реализацию 1-й формы, то чтобы и у других форм внешний вид и реализация были такими же, как у 1-й, но при этом не хочу каждый раз копировать файлы Mod и Rsrc. Копировать модуль A->B. Результат: кодовый файл модуля B --- копии A v := Views.OldView(modALoc, modAName); ASSERT(v # NIL); ASSERT(v IS TextViews.View); modText := Models.CopyOf(v(TextViews.View).ThisModel())(TextModels.Model) --- если не делать копию, то в случае открытости исходника A в ББ он будет (программно) правиться Заменить в modText имя modAName на modBName Скомпилировать: DevCompiler.CompileText(modText, 0, error); ASSERT(~error) Копировать документ формы A->B. Результат: временная копия документа формы A v := Views.OldView(formALoc, formAName); ASSERT(v # NIL); ASSERT(v IS FormViews.View); form := Models.CopyOf(v(FormViews.View).ThisModel())(FormModels.Model) --- то же Для всех контролов в form исправить соотв. свойства (link, guard, etc.) заменив в них modAName на modBName. (Корректно, если все интеракторы, охраны и проч. находятся в модуле A. Насколько понял условие задачи, это так.) Для примера посмотрите реализацию UnicodeConv.FormViewsView, там аналогичная работа выполняется: PROCEDURE FormViewsView (src: FormViews.View): FormViews.View; Открыть временную копию формы: Views.OpenAux(FormViews.dir.New(form), title) |
Автор: | Евгений Темиргалеев [ Воскресенье, 12 Август, 2012 08:46 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Info21 писал(а): Alexander Shiryaev писал(а): но чтобы данные у каждой формы были свои. А куда пойдут эти данные?В ББ они автоматом попадают в глобальные переменные-интеракторы. Разные формы -- разные интеракторы. Что значит, реализация одинаковая, а данные разные? Похоже, имеется некий шаблон мышления, который надо подвергнуть деконструкции еще на стадии постановки задачи. Реализация класса формы --- в одном модуле. Экземпляров можно наплодить сколько хочешь. Данные хранятся в полях контролов, которые в свою очередь поля формы. Этот подход позволяет легко делать копии форм, но обладает своими неудобствами. Самое главное, на мой взгляд (ощущения разницы после пересадки с делфи и сибилдера на ББ), выковыривание из edit1.value --- StrToInt(edit1.value) или StrToReal(edit1.value) и т.п.; и "вковыривание" туда же, в модуле-реализации каждой формы, руками. То, что в ББ делается автоматом --- в базовой реализации контролов, через интеракторы. >Похоже, имеется некий шаблон мышления, который надо подвергнуть деконструкции еще на стадии постановки задачи. Согласен, вполне вероятно, что к задаче можно подойти с другой стороны, обходясь одной формой. И разруливая данные в нужные места через единые интеракторы. Возможный пример: DevInspector |
Автор: | Alexander Shiryaev [ Воскресенье, 12 Август, 2012 11:52 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Нашёл способ лучше, копировать модули не придётся, всё можно сделать в одном: Код: MODULE TmpX; IMPORT Dialog; TYPE Form = RECORD x*: INTEGER END; VAR f1*, f2*, f3*, f4*: Form; forms*: ARRAY 4 OF Form; PROCEDURE Button1Click* (n: INTEGER); BEGIN INC(forms[n].x); Dialog.UpdateInt(forms[n].x) END Button1Click; END TmpX. Генератор форм это воспринимает. Но кнопки на форму надо вручную надо добавлять и привязывать "TmpX.Button1Click(n)", но это не проблема, т.к. делать это нужно будет редко. Только всё равно нужно будет копировать документы формы и заменять привязки "forms[0]" -> "forms[i]". Цитата: А куда пойдут эти данные? Часть данных будет поступать извне и отображаться. Цитата: Согласен, вполне вероятно, что к задаче можно подойти с другой стороны, обходясь одной формой. И разруливая данные в нужные места через единые интеракторы. Возможный пример: DevInspector Нет, нужно, чтобы состояние нескольких одинаковых устройств отображалось на экране одновременно. |
Автор: | Alexander Shiryaev [ Воскресенье, 12 Август, 2012 12:20 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Жаль так нельзя: Код: MODULE TmpX; IMPORT Dialog; TYPE Form = RECORD x*: INTEGER END; VAR forms*: ARRAY 4 OF Form; PROCEDURE (VAR f: Form) Button1Click*, NEW; BEGIN INC(f.x); Dialog.UpdateInt(f.x) END Button1Click; END TmpX. И привязать кнопку к TmpX.forms[0].Button1Click |
Автор: | Пётр Кушнир [ Воскресенье, 12 Август, 2012 12:36 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
в ББ не принято обзывать процедуры Button1Click, ибо 1) процедура ничего не знает про кнопку, я могу вызвать процедуру коммандером, или через Dialog.Call 2) название процедуры должно обозначать действие, типа Handle, Do, GetX или вопрос IsConnected, Empty. Исключение для русского языка составляет процедура-конструктор типа NewItem, но в английском это наверное тоже действие. А для ББ исключения так же: SomeGuard и SomeNotifier. Например, если кнопка "Сохранить", то название процедуры Save, а её охранник SaveGuard. 3) вообще, модуль должен быть максимально отделён от знания про интерфейс пользователя. Ну, понятно, конечно, что Охранники и Уведомители этому не способствуют, но они, в свою очередь могуть быть перенесены в другой модуль. Если рассматривать связь статический Интерактор + Контрол, то мы получим аналог схемы Model + View, при этом модель у нас статическая, и отображение для неё создаёт механизм контролов. Это довольно простой способ отобразить один экземпляр формы для ввода, и он довольно логичен в большинстве случаев, когда человек просто физически не может вводить данные в двух формах сразу. Однако, есть ряд задач, для которых статические интераторы не подходят. Например, отображение данных с кучи датчиков. В свою очередь, слово Отображение, наводит нас на мысль, что форма это не совсем то, что нам нужно в данном случае, поэтому я склоняюсь к мысли, что Вам нужно перепроектировать модуль отображения данных с датчиков по примеру модуля ObxTicks. В итоге, получим что-то типа этого, с настраиваемым отображением, и, самое главное, получим безлимитное количество копий. |
Автор: | Alexander Shiryaev [ Воскресенье, 12 Август, 2012 12:48 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Пётр Кушнир писал(а): в ББ не принято обзывать процедуры Button1Click, ибо 1) процедура ничего не знает про кнопку, я могу вызвать процедуру коммандером, или через Dialog.Call 2) название процедуры должно обозначать действие, типа Handle, Do, GetX или вопрос IsConnected, Empty. Исключение для русского языка составляет процедура-конструктор типа NewItem, но в английском это наверное тоже действие. А для ББ исключения так же: SomeGuard и SomeNotifier. Например, если кнопка "Сохранить", то название процедуры Save, а её охранник SaveGuard. 3) вообще, модуль должен быть максимально отделён от знания про интерфейс пользователя. Ну, понятно, конечно, что Охранники и Уведомители этому не способствуют, но они, в свою очередь могуть быть перенесены в другой модуль. Это я всё знаю Button1Click, TmpX, forms -- это всё имена только для примера. Пётр Кушнир писал(а): Если рассматривать связь статический Интерактор + Контрол, то мы получим аналог схемы Model + View, при этом модель у нас статическая, и отображение для неё создаёт механизм контролов. Это довольно простой способ отобразить один экземпляр формы для ввода, и он довольно логичен в большинстве случаев, когда человек просто физически не может вводить данные в двух формах сразу. Однако, есть ряд задач, для которых статические интераторы не подходят. Например, отображение данных с кучи датчиков. В свою очередь, слово Отображение, наводит нас на мысль, что форма это не совсем то, что нам нужно в данном случае, поэтому я склоняюсь к мысли, что Вам нужно перепроектировать модуль отображения данных с датчиков по примеру модуля ObxTicks. В итоге, получим что-то типа этого, с настраиваемым отображением, и, самое главное, получим безлимитное количество копий. 1) Если устройствами ещё и управлять надо, то что тогда делать? Для управления отдельную форму делать? Так хуже будет. Точнее для экономии места на экране лучше, но для интерактивности хуже. Или не обязательно для управления. Может быть кнопка, при нажатии которой открываются дополнительные сведения об устройстве. 2) Если что-то простенькое, например, один график выводить, то можно и View, но когда графиков несколько, и не только графики есть, но ещё и другие View, то возни много с размещением. С редактором форм проще. |
Автор: | Пётр Кушнир [ Воскресенье, 12 Август, 2012 13:10 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Alexander Shiryaev писал(а): С редактором форм проще. Как я уже сказал, простого способа нет, но с формами он не только сложный но ещё и костыльный. Уж извините. А ещё можно юзать TextViews со ссылками вместо кнопок. Но раз уж формы однозначно лучше... |
Автор: | Alexander Shiryaev [ Воскресенье, 12 Август, 2012 13:18 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Пётр Кушнир писал(а): Alexander Shiryaev писал(а): С редактором форм проще. Как я уже сказал, простого способа нет, но с формами он не только сложный но ещё и костыльный. Уж извините. Почему это? Размещать элементы удобнее с помощью редактора форм, чем в тексте программы. И отображения (Views) на форму можно добавлять. |
Автор: | Alexander Shiryaev [ Воскресенье, 12 Август, 2012 13:24 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Пётр Кушнир писал(а): А ещё можно юзать TextViews со ссылками вместо кнопок. Но раз уж формы однозначно лучше... На TextView размещать элементы неудобно. |
Автор: | Alexander Shiryaev [ Воскресенье, 12 Август, 2012 13:40 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Alexander Shiryaev писал(а): Пётр Кушнир писал(а): Alexander Shiryaev писал(а): С редактором форм проще. костыльный Кстати, мне нужно, чтобы было небольшое фиксированное количество "форм", динамическое создание не требуется, расширяемость тоже не требуется. Важнее удобство быстрого изменения (внешнего вида и реализации). |
Автор: | Илья Ермаков [ Воскресенье, 12 Август, 2012 17:31 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Можно представить себе такую схему: модуль сделан с ARRAY OF Form, как у Вас, процедуры - с параметром. При дизайне формы указывается некое макрообозначение: например, formN. Далее сделаем некую процедуру OpenTool/AuxDialogN (номер формы...), которая перед открытием формы пробегает по всем интеракторам и меняет макрообозначение на указанный номер. |
Автор: | Alexander Shiryaev [ Воскресенье, 12 Август, 2012 20:51 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Спасибо за советы. Пока сделал так: Код: MODULE TmpOpenForm; IMPORT Files, Views, FormViews, FormModels, Containers, Controls, StdDialog, Dialog, Windows, Properties, StdLog; (* 1.2[3]4 -> 1.2[fix]4 1.2(3)4 -> 1.2(fix)4 *) PROCEDURE Fix (VAR s: Dialog.String; IN fix: ARRAY OF CHAR); VAR new: Dialog.String; i (* s reader *), j (* new writer *), k (* fix reader *): INTEGER; c: CHAR; BEGIN i := 0; WHILE (i < LEN(s)) & (s[i] # 0X) & (s[i] # '.') DO new[i] := s[i]; INC(i) END; IF (i < LEN(s)) & (s[i] = '.') THEN new[i] := '.'; INC(i); WHILE (i < LEN(s)) & (s[i] # 0X) & ~((s[i] = '[') OR (s[i] = '(')) DO new[i] := s[i]; INC(i) END; IF (i < LEN(s)) & ((s[i] = '[') OR (s[i] = '(')) THEN new[i] := s[i]; j := i + 1; IF s[i] = '[' THEN c := ']' ELSE (* '(' *) c := ')' END; WHILE (i < LEN(s)) & (s[i] # 0X) & (s[i] # c) DO INC(i) END; IF (i < LEN(s)) & (s[i] = c) THEN INC(i); k := 0; WHILE (k < LEN(fix)) & (fix[k] # 0X) DO new[j] := fix[k]; (* TRAP on new[j] bound overflow OK *) INC(j); INC(k) END; new[j] := c; INC(j); (* TRAP on new[j] bound overflow OK *) WHILE (i < LEN(s)) & (s[i] # 0X) DO new[j] := s[i]; (* TRAP on new[j] bound overflow OK *) INC(j); INC(i) END; new[j] := 0X; (* TRAP on new[j] bound overflow OK *) StdLog.String(s); StdLog.String(" -> "); s := new; StdLog.String(s); StdLog.Ln END END END END Fix; (* сделано как в UnicodeConv.ControlsControl *) PROCEDURE ControlsControl (src: Controls.Control; IN fix: ARRAY OF CHAR): Controls.Control; VAR res: Controls.Control; plist : Properties.Property; p : Controls.Prop; poll : Properties.PollMsg; set : Properties.SetMsg; BEGIN res := Views.CopyOf(src, Views.deep)(Controls.Control); Views.HandlePropMsg(src, poll); plist := poll.prop; WHILE (plist # NIL) & ~(plist IS Controls.Prop) DO plist := plist.next END; IF plist # NIL THEN p := plist(Controls.Prop); p.known := {Controls.link,Controls.guard,Controls.notifier}; p.valid := {Controls.link,Controls.guard,Controls.notifier}; Fix(p.link, fix); Fix(p.guard, fix); Fix(p.notifier, fix); set.old := NIL; set.prop := p; Views.HandlePropMsg(res, set) END; RETURN res END ControlsControl; (* сделано как в UnicodeConv.ConvertThisView *) PROCEDURE ConvertThisView (src: Views.View; IN fix: ARRAY OF CHAR): Views.View; VAR dst: Views.View; BEGIN WITH src: Controls.Control DO dst := ControlsControl(src, fix) ELSE dst := NIL END; RETURN dst END ConvertThisView; (* сделано как в UnicodeConv.FormViewsView *) PROCEDURE FormViewsView (src: FormViews.View; IN fix: ARRAY OF CHAR): FormViews.View; VAR res: FormViews.View; m: FormModels.Model; c: Containers.Controller; v, v1, cv: Views.View; BEGIN res := Views.CopyOf(src, Views.deep)(FormViews.View); m := res.ThisModel(); c := res.ThisController(); c.GetFirstView(Containers.any, v); WHILE v # NIL DO v1 := v; c.GetNextView(Containers.any, v1); (* след-й надо брать до замены *) cv := ConvertThisView(v, fix); IF cv # NIL THEN m.ReplaceView(v, cv) END; v := v1 END; RETURN res END FormViewsView; PROCEDURE GetForm (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR): FormViews.View; VAR v: FormViews.View; BEGIN v := Views.OldView(Files.dir.This(masterDir), masterName$)(FormViews.View); ASSERT(v # NIL); RETURN FormViewsView(v, fix) END GetForm; (* сделано как в StdApi.ThisMask *) PROCEDURE Mask (v: Views.View); VAR c: Containers.Controller; BEGIN IF v # NIL THEN WITH v: Containers.View DO c := v.ThisController(); IF c # NIL THEN c.SetOpts(c.opts - {Containers.noFocus} + {Containers.noCaret, Containers.noSelection}) ELSE Dialog.ShowMsg("#System:NotEditable") END ELSE Dialog.ShowMsg("#System:ContainerExpected") END END END Mask; (* сделано как в StdApi.OpenAuxDialog *) PROCEDURE OpenAuxDialog* (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR; IN title: ARRAY OF CHAR); VAR t0: Views.Title; done: BOOLEAN; v: Views.View; BEGIN Dialog.MapString(title, t0); Windows.SelectByTitle(NIL, {Windows.isAux}, t0, done); IF ~done THEN v := GetForm(masterDir, masterName, fix); Mask(v); StdDialog.Open(v, title, NIL, "", NIL, FALSE, TRUE, TRUE, FALSE, TRUE) END END OpenAuxDialog; (* сделано как в StdApi.OpenToolDialog *) PROCEDURE OpenToolDialog* (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR; IN title: ARRAY OF CHAR); VAR t0: Views.Title; done: BOOLEAN; v: Views.View; BEGIN Dialog.MapString(title, t0); Windows.SelectByTitle(NIL, {Windows.isTool}, t0, done); IF ~done THEN v := GetForm(masterDir, masterName, fix); Mask(v); IF v # NIL THEN StdDialog.Open(v, title, NIL, "", NIL, TRUE, FALSE, TRUE, FALSE, TRUE) END END END OpenToolDialog; PROCEDURE Test*; BEGIN OpenAuxDialog("Tmp/Rsrc", "X1", "0", "Form X1 1 aux"); OpenAuxDialog("Tmp/Rsrc", "X1", "1", "Form X1 2 aux"); OpenToolDialog("Tmp/Rsrc", "X1", "1", "Form X1 2 tool") END Test; END TmpOpenForm. (!)TmpOpenForm.Test Все отображения (Views), размещаемые на форме, должны быть Control-ами, потому что иначе к ним будет неудобно привязываться. Если какой-нибудь график надо выводить, то его тоже надо оборачивать в Control. |
Автор: | Alexander Shiryaev [ Понедельник, 13 Август, 2012 19:17 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Почему-то у форм-копий не такой размер, как у оригинала (размер при копировании теряется). Как это исправить? |
Автор: | Евгений Темиргалеев [ Вторник, 14 Август, 2012 13:54 ] |
Заголовок сообщения: | Re: Несколько одинаковых форм |
Alexander Shiryaev писал(а): Почему-то у форм-копий не такой размер, как у оригинала (размер при копировании теряется). Как это исправить? Корневая вьюшка документа, с которой мы имеем дело, внедрена во вьюшку документа (Documents.Document), которая непосредственно показывается в окне. Размер внедрённой вьюшки хранится в её контексте, принадлежащем контейнеру... Поглядите UnicodeConv.ConvertThisFile и устройство StdDialog.Open.
|
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |