Autor Téma: zrušení rodičovského objektu  (Přečteno 173 krát)

rustymattock

  • Host
zrušení rodičovského objektu
« kdy: 06-11-2017, 07:55:50 »
Zdravím pánové.

Mám třídu, která obsahuje mimo jiné panel a na něm button. Když už panel nepotřebuji, tak ho přes button zruším. Výsledné .exe dělá co má dělat, ale při spusštění přes debugger je samozřejmě vidět, že se mu v události onClick nelíbí, když ji zruším panel (coby rodiče).
Chybová hláška: ...raised exception class $C0000005 with message 'access violation at 0x7698adba: read of addres 0x91202800

Dotaz tedy zní, zda se taková věc ignoruje (když to na straně uživatele nikoho neruší) ? ...což mi ale nepřijde v pořádku.
Nebo má tenhle problém pro vás profíky triviální řešení ?

děkuji.

TPiece = class
  pnl:TPanel;
  btn:TButton;
end;


var
Collect: array of TPiece;  //panely se vytváří  za běhu a ruší v předem neznámém pořadí.

..
procedure TForm1.ClickToFree(Sender:TObject);
begin
  Collect[(sender as TButton).Tag].btn.Free;
  Collect[(sender as TButton).Tag].pnl.Free;
  Collect[(sender as TButton).Tag].Free;
end;

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1764
  • Karma: 72
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:zrušení rodičovského objektu
« Odpověď #1 kdy: 06-11-2017, 08:05:21 »
A když vytváříš ty btn a pnl, koho nastavuješ u nich jako vlastníka?
Embarcadero MVP - Czech republic

rustymattock

  • Host
Re:zrušení rodičovského objektu
« Odpověď #2 kdy: 06-11-2017, 08:46:08 »
jako self
Collect[High(Collect)].pnl:=TPanel.Create(self);

stejně tak btn. Nikdy jsem to nedělal, tak mě nic jiné nenapadlo.
Zkoušel jsem jako vlastníka nastavit jak objekt: TPanel.Create(Collect[High(Collect)]);       //to jsem ale musel třídu odvodit od TObject a stejně to ničemu nepomohlo
Taky jako komponentu ve které celé pole panelú je: TPanel.Create(pnlLayout);

Ale jelikož filozofii vlastníka vytvořeného objektu ještě nechápu, tak spíš improvizuji.    ...a neúspěšně

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 2972
  • Karma: 29
    • Verze Delphi: XE7 professional
Re:zrušení rodičovského objektu
« Odpověď #3 kdy: 06-11-2017, 08:47:58 »
V prvom rade by som zmenil poradie. Najprv zrušil čo je na panely a až potom panel.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

rustymattock

  • Host
Re:zrušení rodičovského objektu
« Odpověď #4 kdy: 06-11-2017, 08:57:50 »
veď tak to aj mám. Ale pred zrušením panelu sa aj tak ruší Button a mám za to, že to práve jeho udalosti onClick (kde sa objekt ruší) vadí.

Mal som za to, že nejaký obecný postup, ako zlikvidivať objekt (včetne rodičovského objektu a  udalosti, ktorá ho práve ruší) sa používa bežne :-(

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 1845
  • Karma: 87
    • Verze Delphi: D2007, XE3, DX10
Re:zrušení rodičovského objektu
« Odpověď #5 kdy: 06-11-2017, 09:01:36 »
Excellent
Rated 1 time
Mal som za to, že nejaký obecný postup, ako zlikvidivať objekt (včetne rodičovského objektu a  udalosti, ktorá ho práve ruší) sa používa bežne :-(
Pouziva: dela se to asynchrone tak, ze z te udalosti, kde to chces zrusit, si posles nejakemu vhodnemu objektu nejakou k tomu nadefinovanou user message. Tim dojde k ukonceni
obsluhy tlacitka a pri obsluze te user message se to zdestruuje.

Normalni je udelat vsem formularum spolecneho predka a tam si k tomu naprogramovat vse potrebne a pak to jenom volat a pretezovat.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1764
  • Karma: 72
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:zrušení rodičovského objektu
« Odpověď #6 kdy: 06-11-2017, 09:09:44 »
Jenom doplním pf
1) když to uvolníš z toho pole, co uděláš s tou pozicí v poli, nemuze se stat ze to uvolnujes nejak 2x? Osobně bych použit TObjectList<TPiece>, a místo toho posledního Free bych to ze seznamu odstranil. Nebo aspon pouzij FreeAndNil.
2) Lepší by bylo u toho btn, dát vlastníka panel, a u panel dat vlastníka nil. Pak uvolnovat jen ten panel, ten zajisti uvolneni i vlastnenych komponent, ale  Delphi RTL to rozchodi i kdyz to máš tak jak to je.
Embarcadero MVP - Czech republic

rustymattock

  • Host
Re:zrušení rodičovského objektu
« Odpověď #7 kdy: 06-11-2017, 14:29:08 »
Tak problém jsem vyřešil dle zmíněného doporučení pf1957, přes PostMessage (zajímavá možnost o které jsem ani netušil)

Radek:
neuvolňuju to 2x
Když to úmyslně uvolním 2x, vyhodí chybu Invalid pointer operation a spadne na tom samozřejmě i spuštěné .exe.

Jestli tobě vhodné nastavení vlastníka funguje, tak bude chyba někde jinde, jelikož mě to hází stejnou chybu pořád. Jestli si to tedy myslel takhle:
Collect[High(Collect)].pnl:=TPanel.Create(nil);
Collect[High(Collect)].btn:=TButton.Create(Collect[High(Collect)].pnl);

už jen kůli studijním důvodům by mě zajímalo, co máme jinak, že to mě nejde. Tady ukázka na pastebin:
https://pastebin.com/ZdCfWdKu

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 2972
  • Karma: 29
    • Verze Delphi: XE7 professional
Re:zrušení rodičovského objektu
« Odpověď #8 kdy: 06-11-2017, 14:46:12 »
Ja som riešil niečo podobné. Príspevok som nenašiel ???  Problém bol v tom, že sa najprv tlačidlo zrušilo (= nil) a potom chcela dobehnúť jeho udalosť. Tiež mi tu dali riešenie pomocou PostMessage.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Křestní jméno zpěváka Gotta: