Параметр Sender DelphiРабота с Sender в обработчиках компонентов |
Уроки Delphi
1. Первая программа
2. Использование компонентов
3. События Delphi
4. Типы данных Delphi
5. Создание своих типов данных
6. Выражения и операторы
7. Работа с файлами в Delphi
8. Дополнительные формы
9. Подпрограммы в Delphi
10. Исключительные ситуации
11. Взаимодействие приложения с пользователем
12. Указатели в Delphi
13. Обзор компонентов
14. Работа со строками
15. Создание интерфейса
16. Графика в Delphi
17. Многопоточность в Delphi
18. Динамическое создание
компонентов Поиск по сайту Это важно:
Метод Application.ProcessMessages;
Это полезно:
Параметр Sender в обработчиках событий;
Бояться не надо |
Параметр Sender в Delphi-программе присутствует в каждом обработчике событий любого компонента. Однако, поскольку в использовании параметра Sender часто нет необходимости, новички про него "забывают" и часто даже не догадываются о его предназначении. В этой статье я хочу рассказать о том, для чего предназначен параметр Sender Delphi и как работать с таким, как оказывается, важным и удобным параметром как Sender. Обзор компонентов Delphi
В начало урока
Компонент Delphi SpeedButtonВопросы и комментарии (34) Решение задач в Delphi
Николай, добавлено 21.04.12, 14:41:07
отличная статья, выручила. 5+ Ольга, добавлено 28.05.12, 23:07:55 если создаешь свой компонент Tlabel в кнопке. Созданный компонент становится невидимым если щелкаешь по нему 2 раза lb.OnDblClick:=label2.OnDblClick; а в Label2 пишем if sender is Tlabel then tlabel(sender).Visible:=false; Как узнать при проверке какой из созданных компонентов был стерт. Автор, добавлено 29.05.12, 05:45:27 При какой проверке? В этой же процедуре? if Sender=Label2 then Caption:='Был стёрт Label2'; else Caption:='Был стёрт lb'; Я же это показал в статье, читали её? Сравните: if Sender = Button1 then Caption:='Щелчок по кнопке №1' else Caption:='Щелчок по кнопке №2'; Ольга, добавлено 29.05.12, 11:40:00 Я это читала. Загвоздка в том что lb будет не один при каждом нажатии кнопки создается новый и если придавать каждому имя с цифрой или использовать tag все равно запоминается последний, а как сделать чтобы программа узнавала какой lb был стерт первый второй или например третий из созданных? Автор, добавлено 29.05.12, 12:08:37 Не понимаю. Sender указывает на источник, какая разница какой он по счёту? Выяснить что за компонент - не проблема. И даже через Tag, почему нет? А вы пробовали, или умозрительно сомневаетесь? Ольга, добавлено 29.05.12, 12:17:33 Пробовала. не получается. если было создано 5 компонентов lb потом стираю один из них и в Label2.caption хочу чтоб написал lb.tag стертого он пишет последний то есть 5 а не один или 2 который был стерт Автор, добавлено 29.05.12, 12:30:41 Давайте, скопируйте сюда процедуры создания компонентов и щелчка по ним, я скопирую себе и посмотрим вместе что не так. Автор, добавлено 29.05.12, 12:45:24 Отмена. Вообще не понимаю в чём проблема. Вот я не создавал, просто поставил 5 лабелей, каждому таг от 1 до 5. Процедура OnDblClick: Caption:=IntToStr((Sender as TLabel).Tag); Ольга, добавлено 29.05.12, 12:47:06 {$R *.dfm} var lb:Tlabel;b:boolean;i:byte; procedure TForm1.SpeedButton1Click(Sender: TObject); begin lb:=tlabel.Create(self); lb.Parent:=self; lb.Font.Color:=clnavy; lb.Font.Name:='Arial'; lb.Font.Size:=26; lb.Caption:='('; inc(i); if b then lb.Tag:=i-1 else lb.Tag:=i; lb.OnDblClick:=label1.OnDblClick; lb.Left:= 20+random(100); lb.Top:=20+random(100); end; procedure TForm1.Label1DblClick(Sender: TObject); begin b:=true; if sender is Tlabel then begin tlabel(sender).Visible:=false; label1.Caption:=inttostr(lb.tag); end else label1.Caption:='net'; end; procedure TForm1.FormCreate(Sender: TObject); begin b:=false; i:=0; end; end. Автор, добавлено 29.05.12, 13:02:46 Всё ясно. Проблема в том, что у вас все лабели создаются одной переменной, и фактически вы присваиваете таг не компоненту а этой переменной lb. Естественно, она и будет иметь таг последний. А исчезновение вы делаете не этой переменной, а как раз компонента типа TLabel - источника события, поэтому это получается. Ольга, добавлено 29.05.12, 13:05:54 А как присваивать таг компоненту в моем случае? Автор, добавлено 29.05.12, 13:21:02 Пойдём методом последовательного приближения 1. Присваивать нужно ведь не переменной а компоненту, который вы создали. А обращение к компоненту происходит ВСЕГДА с указанием его имени. 2. Или использовать для каждого компонента собственную переменную. Но и тогда вы будете использовать таг не компонента а переменной, просто они будут совпадать. Ольга, добавлено 29.05.12, 13:36:59 А по конкретнее можно? в моем случае мне менять создавать вектор переменных но и тогда будет запоминаться конечная переменная. помогите пожалуйста! Ольга, добавлено 29.05.12, 13:57:10 с вектором тоже не получается Ольга, добавлено 29.05.12, 14:24:45 как присваивать компоненту? lb из переменной после строк lb:=tlabel.Create(self); lb.Parent:=self; становится компонентом логически?! или нет? и что делать? куда и как присваивать? Автор, добавлено 29.05.12, 15:14:18 Создаётся динамический массив - вы это называете вектором? Ну пусть. var lb: Array of Tlabel; Впрочем, вот вам весь проект. Только не копируйте слепо, а посмотрите в чём разница: var Form1: TForm1; b:boolean;i:byte; lb: Array of Tlabel; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin SetLength(lb, i+1); lb[i]:=tlabel.Create(Self); lb[i].Parent:=Self; lb[i].Font.Color:=clnavy; lb[i].Font.Name:='Arial'; lb[i].Font.Size:=26; lb[i].Caption:='('; if b then lb[i].Tag:=i else lb[i].Tag:=i+1; lb[i].OnDblClick:=label1.OnDblClick; lb[i].Left:= 20+random(100); lb[i].Top:=20+random(100); inc(i); end; procedure TForm1.Label1DblClick(Sender: TObject); begin b:=true; if (sender is Tlabel) then begin tlabel(sender).Visible:=false; label1.Caption:=inttostr(tlabel(sender).tag); end else label1.Caption:='net'; end; Ольга, добавлено 29.05.12, 16:07:13 Спасибо!я не списывала тупо. в моем массиве были две ошибки и я их исправила! setlength(lb,10) на setlength(lb,i-1) но это не такая большая загвозка была в этом: label1.Caption:=inttostr(i-1);я афищировала только и label1.Caption:=inttostr(tlabel(sender).tag); Спасибо большое! и извените за беспокойство! Ольга, добавлено 29.05.12, 16:33:04 кстати уничтожать компонент этим же способом не получается!или только у меня? выдает ошибку Access violation of adress... if (sender is Tlabel) then tlabel(sender).Free; и на это тоже if (sender is Tlabel) then freeandnil(tlabel(sender)); Автор, добавлено 29.05.12, 17:36:24 Да, что-то ничего пока не получается. Так что вам спасибо - буду думать. Как придумаю - допишу способ уничтожения к статье "Динамическое создание компонентов". А то там пока тоже Free, а это оказывается на компоненты созданные в массиве не действует. Вернее, действует - компонент уничтожается, но тут же появляется неустранимая ошибка. Ольга, добавлено 29.05.12, 17:51:26 Спасибо! Ваши статьи очень помогают! Автор, добавлено 29.05.12, 19:49:34 Касаемо уничтожения компонентов. Ошибка возникает потому, что "нельзя уничтожать компонент в его же событии" - цитирую ответ на программистском форуме. Поэтому берём таймер, передаём в него по щелчку параметр Tag, а по его срабатыванию разыскиваем на Форме компонент типа TLabel с Tag'ом равным переданному - и уничтожаем. Евгений, добавлено 1.06.12, 08:09:51 на сайте статьи очень полезные, но можете ли вы мне помочь в такой ситуации: я создал динамически кнопки и у них есть порядковые номера(массив) вот как бы мне узнать индекс той кнопки на которую я нажал? что нужно наипсать для процедуры proc: mas[i].onclik:=proc; // вот нужно узнать число i кнопки на которой я нажал Тот же Евгений, добавлено 1.06.12, 08:11:42 способ уничтожения таков : Sender.Free(); я его применял для onclick Снова Евгений, добавлено 1.06.12, 08:17:32 удалять компонент вполне возможно внутри себя, я создавал динамически множество кнопок и для каждой из них писал процедуру на onclick sender.free(); получаетсья что при нажатии каждой кнопки он удаляет саму себя но ввиду того что на идекс динамической кнопки ассоциируються в других массивах у м еня возник вопрос (св.выше) Автор, добавлено 1.06.12, 08:38:01 Без использования дополнительного признака не обойтись. Можно номер сунуть в имя, но лучше, я думаю, использовать свойство Tag - при создании приравнивать индексу. Евгений, добавлено 1.06.12, 21:24:58 Была мысль о теге но как тогда узнать индекс элемента(у нажатой кнопки)? Автор, добавлено 1.06.12, 21:38:06 при создании приравнивать индексу Дмитрий, добавлено 8.05.13, 17:01:53 Здравствуйте! Статья доходчивая. Но у меня не получается сохранять разные экземпляры TValueListEditor единственным PopupMenu с созданным пунктом меню Save. Обработчик меню: procedure TForm1.SaveVLEClick(Sender: TObject); begin SaveDialogVLE.Execute; if (Sender is TValueListEditor) then (Sender as TValueListEditor).SaveToCSVFile(SaveDialogVLE.FileName) else memo1.Lines.Add(Sender.ClassName); // memo1 - это лог end; в мемо1 вываливается TMenuItem. Как подобраться к ValueListEditor вызвавшему PopupMenu ? Подскажите пожалуйста. Автор, добавлено 8.05.13, 22:19:31 Потому что источник события в данном случае - не ValueListEditor, а тот пункт меню, который вы нажимаете.Вам нужно при щелчке по нему правой кнопкой (да неважно какой) помечать его как-то, например его номер, записанный в свойстве Tag, присваивать некой переменной. А вот уже источник этого события (щелчка) будет ValueListEditor, можно использовать один обработчик. А в процедуре нажатия меню анализировать номер ValueListEditor'а. Игорь, добавлено 26.01.14, 09:06:06 Как же вовремя заметил эту статью :) Спасибо Антон, добавлено 8.02.14, 18:30:08 Не совсем понятно зачем нужна конструкция Sender as TComponent. Почему нельзя использовать просто переменную Sender? (например Sender.Text:='Текст в компоненте Edit' вместо (Sender as TEdit).Text:='Текст в компоненте Edit') Автор, добавлено 8.02.14, 20:41:08 Я в тексте статьи это специально написал, что тоже не понимаю, зачем не просто Sender, а (Sender as TObject). Но тем не менее, приходится так писать. Это не мы придумали. Антон, добавлено 8.02.14, 22:15:43 Нет, вы не поняли, я не понимаю именно почему у вас в статье это так написано. У меня, вроде как все прекрасно работает именно через просто Sender. Антон, добавлено 8.02.14, 23:13:47 А нет, прошу прощения. Это я ошибся, видимо запутался в собственном коде. |
|