Zdarzenie OnClick w dynamicznie tworzonym obiekcie?

0

Hej.
Piszę sobie taki program i w pewnym momencie dynamicznie tworzony jest obiekt TImage. Chciałbym utworzyć do niego zdarzenie OnClick, ale nie bardzo wiem dlaczego dostaję błąd.

Stworzyłem procedure btnClick(Sender: TObject) i próbuję go przypisać do zdarzenia:

procedure TForm1.Test(Sender: TObject);
begin
  Test:= TImage.Create(Self);
  with Test do
    Picture.LoadFromFile('img\Test.png');
    Height := 600;
    Width:= 600;
    Left := 150;
    Top := 50;
    OnClick := btnClick;
    Parent := Self;
end;                  

To pewnie jakiś głupi błąd więc wybaczcie ignorancje. W internecie znalazłem, gdzieś, że btnClick musi być metodą obiektu, ale nie bardzo wiem jak to zaimplementować u siebie. Czy muszę tworzyć nową klasę?

1

Twoja metoda, którą chcesz przypisać do zdarzenia OnClick dynamicznie tworzonego komponentu, musi się znajdować wewnątrz jakiejś klasy, aby przypisanie było możliwe – o tym informuje sufiks of object nagłówka-wzorca podanego w treści błędu. A Ty zadeklarowałeś zwykłą procedurę, dlatego dostajesz błąd.

Tak więc zadeklaruj swoją metodę wewnątrz klasy, np. w klasie formularza. I pamiętaj, że poprawnym opisem problemu nie jest stwierdzenie, że „mam błąd”, bo nikt nie będzie zgadywał jaki to błąd. Jeśli chcesz otrzymać szybką i rzeczową pomoc to podawaj jak najwięcej szczegółów, w tym problematyczny kod i skopiowaną treść błędów.

0

Mógłbyś to objaśnić jakoś bardzie łopatologicznie, bo wydaje mi się, że robię dobrze, a ciągle mam błąd.

Tak zadeklarowałem metodę:

type

  { TForm1 }

  TForm1 = class(TForm)
// Zmienne i procedury
  private
  public

    type
      TBtnClick = class(TForm)
      public
        procedure TestClick(Sender: TObject);
        end;
  end;                            

a tak wygląda w kodzie

procedure TBtnClick.TestClick(Sender: TObject); // jak tutaj nie dodam TForm1. przed TBtnClick to mam bład ze nie rozpoznaje TBtnClick
begin
  (Sender as TImage).Visible:= false;
end;   

i dalej

  TestImg := TImage.Create(Self);
  with TestImg do
  begin
    Picture.LoadFromFile('img\Test.png');
    Height := 600;
    Width:= 600;
    Left := 150;
    Top := 50;
    OnClick := TBtnClick.TestClick;
    Parent := Self;
  end;

Dostaję komunikat "unit1.pas(271,33) Error: Wrong number of parameters specified for call to "TestClick"". Nie wiem co wpisać w nawiasie.Próbowałem róznych rzeczy jak Self czy TImage ale ciągle cos jest nie tak.

0

Znalazłem w interencie że pomaga zmiana na dyrektywe $mode delphi
Mam nadzieje, ze nie spowoduje to bledu potem

Jeśli mógłby ktoś wyjaśnić co zmienia ta dyrektywa?

0

Użyj Google ;)

Pierwszy wynik z wyszukiwania błędu rzucanego przez kompilator prowadzi do strony http://free-pascal-general.1045716.n5.nabble.com/got-quot-untyped-quot-expected-quot-lt-procedure-variable-type-of-procedure-TObject-of-object-Regist-td5719757.html

gdzie masz ładnie wyjaśnione:

You are calling the function SpeedButton1Click here (with the parameter
"button") and trying to assign its result to button.OnClick. Since
SpeedButton1Click is a procedure, it does not return a value (= "void"),
hence the error message.

What you want/need to do instead, is assign the address of the
SpeedButton1Click procedure to button.OnClick. How this is done, depends
on the syntax mode. In ObjFPC mode (the default in Lazarus), it's
"button.OnClick:=@SpeedButton1Click;". In Delphi mode, it's
"button.OnClick:=SpeedButton1Click;".

Poza tym źle napisałeś pierwszego posta. W tagu masz Delphi, a z błędów wynika, że używasz Lazarusa. Nieładnie ;)

Co do tego co zmienia tryb Delphi nie mam pojęcia, bo znam tylko Delphi. Niech inni się wypowiedzą, będą wiedzieć więcej.

2
soob napisał(a):

Znalazłem w interencie że pomaga zmiana na dyrektywe $mode delphi

Jeśli ktoś sugeruję użycie trybu {$MODE DELPHI} jako rozwiązanie tego typu problemów, to… jest idiotą. :]

Jeśli mógłby ktoś wyjaśnić co zmienia ta dyrektywa?

Ogólnie rzecz ujmując, tryby ustalane za pomocą dyrektyw {$MODE} i {$MODESWITCH} służą do określenia składni rozumianej przez kompilator i ich zasięg obejmuje cały moduł, w którym są zadeklarowane. Pierwsza dyrektywa pozwala ustalić standard języka, natomiast druga służy do rozszerzania wachlarza różnych konstrukcji, niedozwolonych w podstawowej wersji języka.

Wykorzystanie trybu {$MODE DELPHI} w Twoim przypadku może rozwiązać problem przypisania metody, ale jednocześnie może zepsuć masę innych rzeczy, które w trybie {$MODE DELPHI} dozwolone nie są. Mowa tutaj np. o inicjalizacji zmiennych lokalnych w linii ich deklaracji. To działa również w drugą stronę – pewne konstrukcje (np. te dotyczące typów generycznych) są dozwolone tylko w trybie kompatybilności z Delphi.

Podsumowując – nie zmieniaj trybu, jeśli nie wiesz czego on dotyczy, natomiast w miejscu przypisania skorzystaj z operatora @, bo ten jest domyślnie wymagany we Free Pascalu.


Mr.YaHooo napisał(a):

Co do tego co zmienia tryb Delphi nie mam pojęcia, bo znam tylko Delphi. Niech inni się wypowiedzą, będą wiedzieć więcej.

Cyganka prawdę Ci powie, standardowo. :d

1

OnClick to property, którego typ jest method pointer'em, i do tego property należy przypisać zwykłą metodę zgodną z wymaganą sygnaturą (w tym wypadku procedure(Sender: TObject) of object - czyli przypisywana metoda musi posiadać wskazany argument o danym typie i należeć do klasy). I nie musisz tej metody wsadzać do kolejnej klasy - po co? Po prostu dodajesz metodę procedure btnClick(Sender: TObject) do klasy TForm1, a więc:

procedure TForm1.btnClick(Sender: TObject);
begin
    // some code here...
end;   

I tyle.

Innymi słowy, robisz to samo co zrobiło by RAD Studio kiedy klikasz dwa razy w Object Inspector.

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