Event'y dla dynamicznego obiektu

0

Witam,
Próbuję stworzyć metodę **OnClick **dla dynamicznego obiektu:

 TTempBlok = class(TSelection)
  private
  {}
  protected
  {}
  public
    tPanel: TRectangle;
    tLabel: TText;
    tIkona: TImage;
    tNode : TSelectionPoint;
    tLinia: TLine;
    tNumer: TText;
  
  tTYPE : string;

    constructor Create(Owner: TComponent); override;
  published
   {}
  end;

Tworzę taki zgrabny czworokącik:
screenshot-20171105205644.png

W chwili obecnej ropoznaje zdarzenia dotyczące rodzica, czyli TSelection, a potrzebuję konkretnie dla elementu opartego o klasę TSelectionPoint - jasna kropka. Jakieś pomysły?

1

utwórz jedną metodę do obsługi onClick i podepnij ją pod oba zdarzenia, TtempBook.onclick oraz tNode.onClick.
Senderem będzie obiekt wywołujący metodę więc na podstawie klasy Sendera możesz w kodzie metody zrobić dwie różne obsługi zdarzenia
BTW... nazwy pól klasy zaczynające się od litery "t" są bardzo mylące. Litera "T" na początku sugeruje definicję klasy
Samo nazewnictwo pól też jest mocno mylące np. tPanel: TRectangle; . Nazwa pola sugeruje że to obiekt klasy Tpanel ...

1
Rafał Kapłon napisał(a):

Próbuję stworzyć metodę **OnClick **dla dynamicznego obiektu:

Jakoś w tym kodzie nie widzę, abyś tego próbował. ;)


Jeśli chcesz podpiąć zdarzenie pod dynamicznie tworzoną kontrolkę, to wystarczy zadeklarować metodę w klasie-rodzicu, określić parametry pasujące do zdarzenia i np. w konstruktorze klasy-rodzica przypisać zdarzenia do kontrolek.

Zdarzenie OnClick to typ TNotifyEvent, czyli metoda klasy posiadająca jeden parametr typu TObject. Tak więc należy taką metodę zadeklarować w klasie TTempBlok:

type
  TTempBlok = class(TSelection)
  {..}
  private
    FNode: TSelectionPoint;
  private
    procedure SubControlClick(ASender: TObject);
  {..}
  end;

i podpiąć ją w konstruktorze klasy do wewnętrznej kontrolki, np.:

constructor TTempBlok.Create(AOwner: TComponent);
begin
  {..}

  FNode := TSelectionPoint.Create({..});
  FNode.OnClick := @Self.SubControlClick;
  
  {..}
end;
0
grzegorz_so napisał(a):

utwórz jedną metodę do obsługi onClick i podepnij ją pod oba zdarzenia, TtempBook.onclick oraz tNode.onClick.
Senderem będzie obiekt wywołujący metodę więc na podstawie klasy Sendera możesz w kodzie metody zrobić dwie różne obsługi zdarzenia ...

Próbowałem już tak, niby kompilator nie widzi błędów, lecz przy kliknięciu w tNode wsykakuje komunikat -Invalid class typecast-

0

@Rafał Kapłon: pokaż ten kod, przecież nie będziemy wróżyć z fusów…

Jeśli zrobiłeś tak jak pokazałem w swoim poprzednim poście, to wyjątek leci z zupełnie innego powodu.

0
Rafał Kapłon napisał(a):
grzegorz_so napisał(a):

utwórz jedną metodę do obsługi onClick i podepnij ją pod oba zdarzenia, TtempBook.onclick oraz tNode.onClick.
Senderem będzie obiekt wywołujący metodę więc na podstawie klasy Sendera możesz w kodzie metody zrobić dwie różne obsługi zdarzenia ...

Próbowałem już tak, niby kompilator nie widzi błędów, lecz przy kliknięciu w tNode wsykakuje komunikat -Invalid class typecast-

Kompilator może nie widzieć błędów w rzutowaniu, ale to jeszcze nie świadczy że kod jest prawidłowy, Bo kod może być kompilowalny ale niekoniecznie prawidłowy, a jego wykonanie może rzucać wyjątkami

0

@Rafał Kapłon: jak już koniecznie chcesz mieć jedeną metodę podłączoną do kilku kontrolek to nie rzutuj Sender-a na siłę – użyj operatora is i najpierw sprawdź czym on jest.

0

Klasa:

TTempBlok = class(TSelection)
  private
  {}
  protected
  {}
  public
    tPanel: TRectangle;
    tLabel: TText;
    tIkona: TImage;
    tNode : TSelectionPoint;
    tLinia: TLine;
    tNumer: TText;
    tTYPE : string;

    procedure SubControlClick(ASender: TObject);

    constructor Create(Owner: TComponent); override;
  published
   {}
  end;

Konstruktor:

constructor TTempBlok.Create(Owner: TComponent);
begin
  inherited Create(Owner); 

  Width := 155;
  Height := 50;

  tPanel := TRectangle.Create(Self);
  tPanel.Parent := Self;

  tLinia := TLine.Create(Self);
  tLinia.Parent   := Self;
  tLinia.LineType := tLinia.LineType.ltTop;

  tLabel := TText.Create(Self);
  tLabel.Parent := Self;

  tNumer := TText.Create(Self);
  tNumer.Parent := Self;

  tNode := TSelectionPoint.Create(Self);
  tNode.Parent  := Self;

  tNode.OnClick := Self.SubControlClick;

  tIkona := TImage.Create(Self);
  tIkona.Parent := Self;
end;

Procedura:

procedure SubControlClick(ASender: TObject);
begin
  pPT100.tLabel.Text := 'Kliknięto mnie...';
end;
0

Metoda SubControlClick jest zła, bo powinna operować na parametrze ASender, uprzednio upewniając się (za pomocą operatora is), że to faktycznie obiekt klasy TText.

procedure SubControlClick(ASender: TObject);
begin
  if ASender is TText then
    TText(ASender).Text := 'Kliknięto mnie...';
end;

To są podstawy programowania obiektowego – musisz o tym poczytać.

0

musisz sprawdzić czy sender jest obiektem klasy Tlabel

if sender is Tlabel  then 
   Tlabel(sender).text:='Kliknięto mnie...';
0

Wybaczcie mi, zrobiłem nowy projekt, testowy.

Zrobiłem tak jak proponowaliście, ale pomimo wszelkich starań, Delphi rzuca się o deklarację tej procedury obsługi przerwania :/

Jeżeli ktoś ma jeszcze siłę :)

1

W ciemno (otwarty w notatniku) to widzę że w sekcji implementation masz:

procedure SubControlClick(ASender: TObject);

EDIT
powinieneś:

procedure TBlok.SubControlClick(ASender: TObject);
begin
if (ASender is TText)  then
   TText(ASender).Text:='Kliknięto mnie...';
end;

Poza tym było pisać od początku że to FMX a nie VCL.

0

Dziękuje za pomoc.
Wszystko pięknie, ładnie

1 użytkowników online, w tym zalogowanych: 0, gości: 1