Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];

Вниз

Непонимаю почему не работает   Найти похожие ветки 

 
boleg ©   (2006-12-29 10:40) [0]

Страннно компилятор пропускает, а на епапе выполнения выдается ошибка типа "Access violation at address". Если уважаемому ALL эти потуги новичка не покажутся скучными :-) то объясните почему не работает:

type
 TForm1 = class(TForm)
   Button1: TButton;

   procedure Button1Click(Sender: TObject);
   procedure PanelDblClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 Panel: TPanel;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Panel:=TPanel.Create(Self);
 Panel.Top:=100;
 Panel.Left:=100;
 Panel.Parent:=Self;

 Panel.OnDblClick:=PanelDblClick;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 Panel.Free;
end;

procedure TForm1.PanelDblClick(Sender: TObject);
begin
//  TPanel(Sender).Caption:="rrrrrrrrrr";
 TPanel(Sender).Free;      // выдает ошибку, хотя верхняя рабртает
end;

end.


 
Джо ©   (2006-12-29 10:42) [1]

А откуда компилятору знать, что в процессе выполнения ты освободил экземпляр объекта до вызова его методов?


 
Джо ©   (2006-12-29 10:45) [2]

И совершенно не факт, что «верхняя» будет работать.


 
boleg ©   (2006-12-29 10:54) [3]

Верхняя работает! факт! А вот на счет освобождения экземпляра объекта прошу поподробнее ответить. Я в терминологии не силен (маловато наверно книжек читал).


 
Джо ©   (2006-12-29 10:59) [4]

> [3] boleg ©   (29.12.06 10:54)
> Верхняя работает! факт!

Не факт.


> А вот на счет освобождения экземпляра объекта прошу поподробнее
> ответить


procedure TForm1.Button2Click(Sender: TObject);
begin
Panel.Free;
end;


 
ЮЮ ©   (2006-12-29 11:01) [5]


> Верхняя работает! факт!


Кто верхняя?
объяви   Panel: TPanel; как локальную в методе  TForm1.Button1Click. Глобальная нафиг не нужна, т.к. панелей может быть много, а ссылка только на последнюю созданную.


 
Palladin ©   (2006-12-29 11:04) [6]


> [3] boleg ©  

по встречной полосе тоже можно ехать, факт!


 
umbra ©   (2006-12-29 11:11) [7]


> procedure TForm1.PanelDblClick(Sender: TObject);
> begin
> //  TPanel(Sender).Caption:="rrrrrrrrrr";
>  TPanel(Sender).Free;      // выдает ошибку, хотя верхняя
> рабртает
> end;
>


не стоит уничтожать объект в его обработчике события


 
С   (2006-12-29 11:16) [8]

>boleg ©   (29.12.06 10:40)
procedure TForm1.PanelDblClick(Sender: TObject);
begin
//  TPanel(Sender).Caption:="rrrrrrrrrr";
TPanel(Sender).Free;      // выдает ошибку, хотя верхняя рабртает
end;

После возврата из обработчика метод TPanel, который этот обработчик вызывает, пытается обратиться к полям объекта, для которого и произошло событие, а объект оказывается уже уничтоженным, отсюда и ошибка.


 
boleg ©   (2006-12-29 11:18) [9]

Прошу прощения procedure TForm1.Button2Click(Sender: TObject) забыл стереть
дабы не отвлекать внимание. Эта процедура работает. Но работает не так как нужно. Например, если нажать несколько раз на Button1 (создавая несколько панелек на форме), то при нажатии на Button2 первый екземпляр удаляется, а вот повторное нажатие вызывает ошибку (теряет ссылку на объект). Поэтому была придумана  
  procedure TForm1.PanelDblClick(Sender: TObject)
По двойному клику удалять панели с формы, ссылаясь на них TPanel(Sender)
где Sender - указатель на панельку.
Так вот

procedure TForm1.PanelDblClick(Sender: TObject);
begin
 TPanel(Sender).Caption:="rrrrrrrrrr";
end;

работает !!

а так

procedure TForm1.PanelDblClick(Sender: TObject);
begin
 TPanel(Sender).Free;
end;

работает. Почему не могу понять.


 
С   (2006-12-29 11:24) [10]

"Она живет на улице койкого, а он на улице койкого"©


 
boleg ©   (2006-12-29 11:25) [11]

Для Umbra

Такой пример вычитал в книге М.Фленов "Библия Delphi", немного изменив получилалось так как приведено. :-)


 
Elen ©   (2006-12-29 11:28) [12]


> Так вот
...
> работает !!
>
> а так
...
> работает. Почему не могу понять.

Улыбнуло.
У меня твое работает при некоторой доработке
А где у тебя описание Button2Click


 
Elen ©   (2006-12-29 11:29) [13]


>  немного изменив получилалось так как приведено

Немного изменив привожу свое, може поможет. (у меня робэ) :
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, extctrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
    procedure PanelDblClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var       Panel: TPanel;
 Form1: TForm1;

implementation

{$R *.dfm}
procedure TForm1.PanelDblClick(Sender: TObject);
begin
 TPanel(Sender).Caption:="rrrrrrrrrr";
TPanel(Sender).Free;      // âûäàåò îøèáêó, õîòÿ âåðõíÿÿ ðàáðòàåò
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Panel:=TPanel.Create(Self);
Panel.Top:=100;
Panel.Left:=100;
Panel.Parent:=Self;

Panel.OnDblClick:=PanelDblClick;
end;

end.


Хотя [7] конечно верно...


 
Desdechado ©   (2006-12-29 11:31) [14]

внимательно читай umbra ©   (29.12.06 11:11) [7]


 
boleg ©   (2006-12-29 11:33) [15]

"После возврата из обработчика метод TPanel, который этот обработчик вызывает, пытается обратиться к полям объекта, для которого и произошло событие, а объект оказывается уже уничтоженным, отсюда и ошибка".

Прошу пояснить, если не трудно, примером. Как всетаки сделать чтобы работало.

P.S. Прошу прощения за настырность. Но хочу разобраться дабы не задавать глупых вопросов!


 
Elen ©   (2006-12-29 11:36) [16]


> boleg

Sorry но [13] работает только для одной создаваемой панели. (см. [7])
пробуй так :

....................
var       pn,Panel: TPanel;
 Form1: TForm1;

implementation

{$R *.dfm}
procedure TForm1.PanelDblClick(Sender: TObject);
begin
Caption:=TPanel(Sender).Name;
pn:=TPanel(Sender);
end;

..................

procedure TForm1.Button2Click(Sender: TObject);
begin
  pn.Free;
end;


 
umbra ©   (2006-12-29 11:38) [17]


> Как всетаки сделать чтобы работало

чтобы работало что? чего надо добиться?


 
Elen ©   (2006-12-29 11:40) [18]


>  Как всетаки сделать чтобы работало.

Если тебе надо удалять объект по которому ты клацнул то можно попробовать так :

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, extctrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Timer1: TTimer;
   procedure Button1Click(Sender: TObject);
    procedure PanelDblClick(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var       pn,Panel: TPanel;
 Form1: TForm1;

implementation

{$R *.dfm}
procedure TForm1.PanelDblClick(Sender: TObject);
begin
Caption:=TPanel(Sender).Name;
pn:=TPanel(Sender);
Timer1.Enabled:=true;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Panel:=TPanel.Create(Self);
Panel.Name:="n"+inttostr(random(100));
Panel.Top:=random(100);
Panel.Left:=100;
Panel.Parent:=Self;
Panel.OnDblClick:=PanelDblClick;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
pn.Free;  Timer1.Enabled:=false;
end;

end.


 
C   (2006-12-29 11:49) [19]

>boleg ©   (29.12.06 11:33) [15]
А какой тут можно пример? Надо смотреть исходный код TPanel и его предков, то есть всю трассу вызовов от цикла выборки сообщений до вызова обработчика OnDoubleClick и обратно, до цикла выборки. В частности, после вызова обработчика двойного клика происходит проверка наличия и вызов события OnMouseDown - то есть попытка обратиться к полю FOnMouseDown уже уничтоженного объекта. Причем ошибка может проявляться нестабильно, то появляться, то пропадать, так что лучше взять за аксиому [7].


 
Джо ©   (2006-12-29 11:50) [20]

> [18] Elen ©   (29.12.06 11:40)
>
> >  Как всетаки сделать чтобы работало.
>
> Если тебе надо удалять объект по которому ты клацнул то
> можно попробовать так :

Это называется удалять гланды через кое-что :)

Стандартно поступают так:

const
 WM_KILL = WM_USER + 666;

type

 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   procedure WmKillMem (var Msg: TMessage); message WM_KILL;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 PostMessage (Handle,WM_KILL,Integer(Sender),0)
end;

procedure TForm1.WmKillMem(var Msg: TMessage);
begin
 TObject(Msg.WParam).Free
end;


 
Elen ©   (2006-12-29 11:54) [21]

Удалено модератором
Примечание: Флудить завязываем


 
С   (2006-12-29 12:07) [22]

>Джо ©   (29.12.06 11:50) [20]

Желательно все-же добавить эащиту от попатки многократного удаления одной и той же панели. Например, кроме отравки сообщения еще и удалять обработчик события. Ну или свойство Tag использовать в качестве флага.


 
Джо ©   (2006-12-29 12:17) [23]

> [22] С   (29.12.06 12:07)
> >Джо ©   (29.12.06 11:50) [20]
>
> Желательно все-же добавить эащиту от попатки многократного
> удаления одной и той же панели.

Это зачем?


 
C   (2006-12-29 12:25) [24]

>Джо ©   (29.12.06 12:17) [23]

На случай, если он успеет отправить несколько сообщений до того, как будет выбрано и обработано первое сообщение-киллер. "Маловероятно" не значит "невозможно". Разве нет?


 
Джо ©   (2006-12-29 12:46) [25]

> [24] C   (29.12.06 12:25)
> >Джо ©   (29.12.06 12:17) [23]
>
> На случай, если он успеет отправить несколько сообщений
> до того, как будет выбрано и обработано первое сообщение-
> киллер. "Маловероятно" не значит "невозможно". Разве нет?

В методе Free проверяется не равен ли Self nil и только после этого идет вызов Destroy.


 
C   (2006-12-29 12:59) [26]

>Джо ©   (29.12.06 12:46) [25]

Не понял, честно говоря, как это связано:( Тем более, что нигде в приведенном в [20] коде nil не присваивается  и, соответственно, Self не будет равен nil даже после уничтожения объекта.

Возможно, я выразился недостаточно ясно. Имелось в виду, что в общем случае метод, отправляющий WM_KILL может быть вызван 2 или более раз до того как первое из них будет выбрано из очереди и обработано. Соответственно в очереди окажутся несколько сообщений WM_KILL для одного и того же объекта. И тогда при обработке первого из них объект будет уничтожен, а при обработке второго в Msg.WParam окажется указатель на уже уничтоженный объект. И Self во Free тоже будет равен значению Msg.WParam <> nil.


 
Gloomer ©   (2006-12-29 13:00) [27]

IMHO прав [19]

procedure TForm1.Button1Click(Sender: TObject);
var  Panel: TPanel;
begin
  Panel:=TPanel.Create(Self);
  Panel.Top:=100;
  Panel.Left:=100;
  Panel.Parent:=Self;
  Panel.OnDblClick:=PanelDblClick;
  Panel.OnMouseDown:=PanelMouseDown;
end;

procedure TForm1.PanelDblClick(Sender: TObject);
begin
 TPanel(Sender).Tag:=666;
end;

procedure TForm1.PanelMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  with TPanel(Sender) do
     if Tag=666 then Free;
end;


 
boleg ©   (2006-12-29 17:56) [28]

Спасибо, думаю что разобрался



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.045 c
3-1162280807
Patrick
2006-10-31 10:46
2007.01.21
Компонент для Oracle


3-1162210429
Rickkk
2006-10-30 15:13
2007.01.21
Проблема с lookup-полями в запросе


2-1167105483
delphim
2006-12-26 06:58
2007.01.21
использование ehlib в режиме TreeView


15-1167821218
0x07BBh
2007-01-03 13:46
2007.01.21
SOAP &amp; DELPHI


11-1144316016
BaryVetaL
2006-04-06 13:33
2007.01.21
В догонку к BVLedNumber...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский