Вопрос по классам, обработчикам событий...

Тема в разделе "Delphi - FAQ", создана пользователем Vadik(R), 31 окт 2010.

  1. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Начал изучать классы в C++, столкнулся с понятиями слота и сигнала. Прочитал про connect, SIGNAL и SLOT, и стало интересно, как было все реализовано в Delphi, где я раньше кодил и уютнее себя чувствал :welcome:
    Первый пример, который я решил разобрать - это событие Button1.OnClick.
    Я так понимаю, в Delphi C-подобный код создается автоматически:
    Код (Text):
    connect(Button1, SIGNAL(OnClick()), Form1, SLOT(Button1Click(TObject)))
    Просто этот код Delphi пишет автоматически и мы его не видем. Далее, почитав, что при вызове connect SLOT может принимать параметры только из SIGNAL'а, я решил, что connect Delphi пишет так:
    Код (Text):
    connect(Button1, SIGNAL(OnClick(TObject)), Form1, SLOT(Button1Click(TObject)))
    Вот. Далее, я решил поэксперементировать, а какого черта Button1Click должен принимать параметр TObject? Ведь, он может принимать не все параметры из SIGNAL'а. Решил написать код:
    Код (Text):
    type
    TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click;
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.Button1Click;
    begin
    ShowMessage('1');
    end;

    end.
    На что получил ругательство Delphi (The Button1Click method referenced by Button1.OnClick has an incompatible parameter list. Remove the reference? - No), но тем не менее программу он всё равно скомпилировал и запустил. Далее, я рассуждал так. На лишние параметры в SLOT'е Delphi ругается - правильно делает. А на их недостаток - тоже. Странно. И я решил, что Delphi в обработчик события всегда будет передавать Sender'а, вызвавшего это событие, например, чтобы выполнять разный код при различных Sender'ах, или не выполнять ничего при определённых Sender'ах.
    Тогда я решил создать свой класс, сделать событие, и привязать обработчик к этому событию. Если бы он ругался бы на обработчик без параметров, а на обработчик с параметром TObject - нет, тогда всё ясно, Delphi всегда передает в обработчик Sender'а, независимо ни от чего другого. То есть, даже если SIGNAL будет без параметров. Однако, я такое только попытался сделать, и тут же возникли проблемы. Вот код, при нажатии на кнопку вылетает AccessViolation, из-за чего он возникает и как его исправить - я не знаю. Код:
    Код (Text):
    unit Unit1;

    interface

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

    type
    TMyObj = class(TObject) //Свой класс
    summ: integer;
    procedure sum(a, b: integer);
    end;
    TForm1 = class(TForm)
    Button1: TButton;
    MyObj: TMyObj;
    procedure sumsum(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    /* Какое-то событие, которое в будущем хочу использовать как сигнал. Знаю, что оно
    не должно иметь тела кода, но тем не менее, оно даже сейчас пока не работает. :( */
    procedure TMyObj.sum(a, b: integer);
    begin
    summ := a + b;
    end;

    /* Обработчик будущего события. Чтобы убедиться, что Sender передается всегда, независимо от параметров
    функции-сигнала. */
    procedure TForm1.sumsum(Sender: TObject);
    begin
    ShowMessage(IntToStr((Sender as TMyObj).summ));
    end;

    /* Нажатием на кнопку изначально хотел породить сигнал, но потом пришёл к еще одной проблеме -
    ошибка AccessViolation, хотя не понимаю, откуда она возникает, вроде же все правильно?
    Если написать Button1 и какое-то свойство/метод - всё работает, а если MyObj - то никак.
    Думал, проблема в том, что прежде надо создать объект, но видимо, тоже не в этом дело. :( */
    procedure TForm1.Button1Click(Sender: TObject);
    begin
    //Пробовал разные варианты - все равно возникает ошибка :(
    //Form1.MyObj.Create;
    //Form1.MyObj.sum(1, 3);
    Form1.MyObj.summ := 1;
    //Form1.MyObj.Free;
    end;

    end.
    . Собственно, объясните, пожалуста, из-за чего возникает ошибка и как её исправить? А заодно может и найдёте ошибки в моих рассуждениях и избавите от кучи работы, которую я, возможно, делаю впустую.
    P.S. Классы начал изучать в C++, потому что в универе мы их проходим. А почему вспомнил про Delphi? Потому что за ним сижу уже 4 года, а за C++ - только полгода, поэтому и интересуюсь, как это устроено в Delphi.

    Ааа, может надо писать:
    Код (Text):
    Form1.MyObj := TMyObj.Create;
    ?? Тогда, объясните, почему такой вариант не работает:
    Код (Text):
    Form1.MyObj.Create;
    , и чем они различаются?
     
  2. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    На другом форуме подсказали, что я не могу назначить обработчик события с другим прототипом, потому что спецификация обработчика такая, и ничего с этим поделать нельзя. Не получится присвоить на OnClick обработчик, описанный отличнительно от типа TNotifyEvent.
    Да, жаль в Delphi нет некоторых возможностей C.
     
  3. etc

    etc Гость

    А что не понятно то?
    1 конструктор это грубо говоря class function
    2 с событиями, вы просто почитайте как они устроены тут
     
Загрузка...
Похожие Темы - Вопрос по классам
  1. ApplePen
    Ответов:
    0
    Просмотров:
    63
  2. gURaBA_N
    Ответов:
    3
    Просмотров:
    94
  3. kartaman
    Ответов:
    0
    Просмотров:
    128
  4. Peter
    Ответов:
    4
    Просмотров:
    524
  5. di0d_
    Ответов:
    1
    Просмотров:
    440

Поделиться этой страницей