Форум: "Начинающим";
Текущий архив: 2007.12.02;
Скачать: [xml.tar.bz2];
ВнизEExternalException.. Найти похожие ветки
← →
pathfinder © (2007-11-09 11:10) [0]Добрый день.
Есть форма на которой edit и label. При изменении значения в edit-e оно должно меняться и label-е. Попытался сделать это с помощью шаблона Наблюдатель. Взял его реализацию из BDS2006. В методе NotifyObservers возникает EEXternalException при попытке вызвать метод Update элемента списка. Подскажите пожалуйста, в чем моя ошибка?
Код самой программы:
var
ProgParams: TProgParams;
ProgView: TProgView;
begin
ProgParams := TProgParams.Create;
ProgView := TProgView.Create(ProgParams);
ProgView.Show;
end.
Реализация классов:
type
TSubject = class;
IObserver = interface
procedure Update(ASubject :TSubject);
end;
TSubject = class
strict private var
FObservers:TList;
strict protected
procedure NotifyObservers;
public
constructor Create;
procedure Attach(AObserver :IObserver);
procedure Detach(AObserver :IObserver);
end;
TProgParams = class(TSubject)
strict private
FTest: string;
public
function GetParam(const Name: string): string;
procedure SetParam(const Name: string);
end;
TProgView = class(TInterfacedObject, IObserver)
strict private
FSubject: TProgParams;
FViewForm: TViewForm;
procedure Refresh;
procedure OnSetParam(Sender: TObject);
public
constructor Create(ASubject: TProgParams);
destructor Destroy;
procedure Show;
procedure Update(ASubject :TSubject);
end;
implementation
constructor TSubject.Create;
begin
inherited Create;
FObservers := TList.Create;
end;
procedure TSubject.Attach(AObserver :IObserver);
begin
FObservers.Add(@AObserver);
end;
procedure TSubject.Detach(AObserver :IObserver);
var
idx :Integer;
begin
idx := FObservers.IndexOf(@AObserver);
If idx <> -1 Then
begin
FObservers.Delete(idx);
end;
end;
procedure TSubject.NotifyObservers;
var
Current :^IObserver;
begin
for Current in FObservers do
Current.Update(self);
end;
constructor TProgView.Create(ASubject: TProgParams);
begin
FSubject := ASubject;
FSubject.Attach(self);
FViewForm := TViewForm.Create(nil);
FViewForm.edtTest.OnChange := OnSetParam;
end;
destructor TProgView.Destroy;
begin
FSubject.Detach(self);
FViewForm.Free;
end;
procedure TProgView.OnSetParam(Sender: TObject);
begin
FSubject.SetParam(FViewForm.edtTest.Text);
end;
procedure TProgView.Refresh;
var
s: string;
begin
s := FSubject.GetParam("");
FViewForm.edtTest.Text := s;
FViewForm.lblTest.Caption := s;
end;
procedure TProgView.Show;
begin
FViewForm.ShowModal;
end;
procedure TProgView.Update(ASubject :TSubject);
begin
Refresh;
end;
{ TProgParams }
function TProgParams.GetParam(const Name: string): string;
begin
Result := FTest;
end;
procedure TProgParams.SetParam(const Name: string);
begin
FTest := Name;
NotifyObservers;
end;
← →
Dib@zol © (2007-11-09 11:15) [1]> [0] pathfinder © (09.11.07 11:10)
> Добрый день.
> Есть форма на которой edit и label. При изменении значения в edit-e оно должно меняться и label-е.
И ради ЭТОГО нужен был весь тот код???
/me Потерял сознание
← →
pathfinder © (2007-11-09 11:18) [2]
> И ради ЭТОГО нужен был весь тот код???
Скорей наоборот.
← →
Ega23 © (2007-11-09 11:19) [3]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
procedure Edit1Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Edit1Change(Sender: TObject);
begin
Label1.Caption := Edit1.Text;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := "";
end;
end.
Всё.
← →
pathfinder © (2007-11-09 11:22) [4]
> Ega23 © (09.11.07 11:19) [3]
>
>
На самом деле я хотел попробовать применить шаблон Наблюдатель на практике, а не просто выполнить эту операцию.
← →
ЮЮ © (2007-11-09 11:22) [5]> [3] Ega23 © (09.11.07 11:19)
> Всё.
Не стыдно, это же "батонокидательство"!
А тут речь о Наблюдателе.
З.Ы. Не зря наблюдение за наблюдающим стоит дороже :)
← →
Dib@zol © (2007-11-09 11:24) [6]А нафика изобретать велосипед с треугольными колёсами? Поищи лучше в гугле задачи на применение этого шаблона, и не майся дурью. ЗЫ Мне аж плохо стало, когда я все эти навороты увидал...
← →
Ega23 © (2007-11-09 11:24) [7]
> Не стыдно, это же "батонокидательство"!
Это наиболее быстрый и дешёвый способ решения КОНКРЕТНОЙ проблемы.
Остальное - побоку.
← →
pathfinder © (2007-11-09 11:25) [8]
> А нафика изобретать велосипед с треугольными колёсами? Поищи
> лучше в гугле задачи на применение этого шаблона, и не майся
> дурью. ЗЫ Мне аж плохо стало, когда я все эти навороты увидал.
> ..
Так какая разница какая задача? Вопрос-то в реализации..
← →
Dib@zol © (2007-11-09 11:27) [9]Попробуй измерить время выполнения твоего алгоритма и предложенного товаришшем Ega23. Последний будет работать на порядок быстрее. Не для того этот шаблон создавался, чтоб на нём такое вытворяли.
← →
pathfinder © (2007-11-09 11:28) [10]
> Попробуй измерить время выполнения твоего алгоритма и предложенного
> товаришшем Ega23. Последний будет работать на порядок быстрее.
> Не для того этот шаблон создавался, чтоб на нём такое вытворяли.
>
Я же говорю, что это не реальная задача, а просто для примера.
← →
pathfinder © (2007-11-09 11:30) [11]И потом вопрос ведь не в том, как оптимальней решить ЭТУ задачу, а что не так в реализации?
← →
icWasya © (2007-11-09 12:51) [12]а почему так
FObservers.Add(@AObserver);
а не так
FObservers.Add(AObserver);
???
← →
Anatoly Podgoretsky © (2007-11-09 12:55) [13]
> Я же говорю, что это не реальная задача, а просто для примера.
Тренируйся на кошках.
← →
pathfinder © (2007-11-09 12:57) [14]
> Anatoly Podgoretsky © (09.11.07 12:55) [13]
Большое спасибо! Это самый ценный совет.
← →
pathfinder © (2007-11-09 12:57) [15]
> icWasya © (09.11.07 12:51) [12]
>
> а почему так
> FObservers.Add(@AObserver);
>
> а не так
> FObservers.Add(AObserver);
> ???
[Pascal Error] Unit2.pas(60): E2010 Incompatible types: "Pointer" and "IObserver"
← →
Сергей М. © (2007-11-09 13:01) [16]
> pathfinder © (09.11.07 12:57) [15]
Ну так сделай FObservers типа TInterfaceList, бо на то этот тип и предназначен.
Или приводи явно интерфейсный тип к указательному.
← →
Anatoly Podgoretsky © (2007-11-09 13:04) [17]> pathfinder (09.11.2007 12:57:14) [14]
Конечно, надо делать более реальную задачу.
← →
pathfinder © (2007-11-09 13:05) [18]
> Конечно, надо делать более реальную задачу.
Не хотелось браться за сложное, если даже с простым не получается.
← →
pathfinder © (2007-11-09 13:07) [19]
> Сергей М. © (09.11.07 13:01) [16]
>
>
> > pathfinder © (09.11.07 12:57) [15]
>
>
> Ну так сделай FObservers типа TInterfaceList, бо на то этот
> тип и предназначен.
> Или приводи явно интерфейсный тип к указательному.
Так здесь то вроде все нормально..
Ошибка здесь:
TSubject.NotifyObservers;
Current.Update(self);
← →
Сергей М. © (2007-11-09 13:14) [20]
> здесь то вроде все нормально
Как же нормально, если при компиляции процитированных тобой в [15] строк компилятором обнаружена тобой же процитированная ошибка ?
← →
pathfinder © (2007-11-09 13:19) [21]
> Как же нормально, если при компиляции процитированных тобой
> в [15] строк компилятором обнаружена тобой же процитированная
> ошибка ?
>
Это если так FObservers.Add(AObserver);
А если FObservers.Add(@AObserver); то все ок.
← →
Сергей М. © (2007-11-09 13:31) [22]
> если FObservers.Add(@AObserver); то все ок
С т.з. компилятора - да.
А с т.з. происходящего при этом в ран-тайм - это полная фигня, о чем тебе и сообщает возникшее при этом исключение.
Так что вопрос к тебе в [12] вполне резонен.
← →
pathfinder © (2007-11-09 13:37) [23]
> Так что вопрос к тебе в [12] вполне резонен.
Это готовая реализация этого шаблона из делфи. Получается они неправильно сделали?
← →
pathfinder © (2007-11-09 13:46) [24]
> Сергей М. © (09.11.07 13:01) [16]
>
> Или приводи явно интерфейсный тип к указательному.
Воспользовался вашим советом и все заработало:)
Всем спасибо!
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.12.02;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.046 c