0 просмотров

Динамическое создание компонентов (во время выполнения)

Зарко Гайич имеет опыт работы с SQL и практические знания систем баз данных, таких как MS SQL Server, Firebird, Interbase и Oracle. Он также владеет XML, DHTML и JavaScript.

Чаще всего при программировании в Delphi вам не нужно динамически создавать компонент. Если вы перетащите компонент на форму, Delphi автоматически создаст компонент при создании формы. В этой статье будет рассмотрен правильный способ программного создания компонентов во время выполнения.

Создание динамического компонента

Существует два способа динамического создания компонентов. Один из способов — сделать форму (или какой-либо другой TComponent) владельцем нового компонента.Это обычная практика при создании составных компонентов, когда визуальный контейнер создает подкомпоненты и владеет ими. Это гарантирует, что вновь созданный компонент будет уничтожен при уничтожении компонента-владельца.

Чтобы создать экземпляр (объект) класса, вы вызываете его метод «Создать». Конструктор Create — это метод класса, в отличие от практически всех других методов, с которыми вы столкнетесь в программировании Delphi, которые являются объектными методами.

Например, TComponent объявляет конструктор Create следующим образом:

конструктор Create(AOwner: TComponent) ; виртуальный;

Динамическое создание с владельцами
Вот пример динамического создания, где Себя является потомком TComponent или TComponent (например, экземпляром TForm):

с TTimer.Create(Self) сделать
начинать
Интервал := 1000;
Включено := Ложь;
OnTimer := MyTimerEventHandler;
конец;

Динамическое создание с явным вызовом Free
Второй способ создания компонента заключается в использовании ноль как владелец. Обратите внимание, что если вы сделаете это, вы также должны явно освободить созданный вами объект, как только он вам больше не понадобится (иначе вы вызовете утечку памяти). Вот пример использования nil в качестве владельца:

с TTable.Create(nil) сделать
пытаться
ИмяБазы Данных := 'МойПсевдоним';
ИмяТаблицы := 'МояТаблица';
Открытым;
Редактировать;
FieldByName('Busy').AsBoolean := True;
Почта;
в конце концов
Свободно;
конец;

Динамическое создание и ссылки на объекты
Можно улучшить два предыдущих примера, назначив результат вызова Create переменной, локальной для метода или принадлежащей классу. Это часто желательно, когда ссылки на компонент необходимо использовать позже или когда необходимо избежать проблем с областью видимости, потенциально вызванных блоками «С». Вот приведенный выше код создания TTimer, использующий переменную поля в качестве ссылки на экземпляр объекта TTimer:

FTimer := TTimer.Create(Self) ;
с FTimer сделать
начинать
Интервал := 1000;
Включено := Ложь;
OnTimer: = MyInternalTimerEventHandler;
конец;

В этом примере «FTimer» — это частная переменная поля формы или визуального контейнера (или чего-то еще «Я»). При доступе к переменной FTimer из методов этого класса рекомендуется перед использованием проверить, действительна ли ссылка. Это делается с помощью функции Delphi Assigned:

если Assigned(FTimer), то FTimer.Enabled := True;

Динамическое создание и ссылки на объекты без владельцев
Вариантом этого является создание компонента без владельца, но сохранение ссылки для последующего уничтожения. Код построения для TTimer будет выглядеть так:

FTimer := TTimer.Create(nil) ;
с FTimer сделать
начинать
.
конец;

А код уничтожения (предположительно в деструкторе формы) будет выглядеть примерно так:

FTimer.Free;
FTimer := ноль;
(*
Или используйте процедуру FreeAndNil (FTimer), которая освобождает ссылку на объект и заменяет ссылку на nil.
*)

Установка ссылки на объект на nil имеет решающее значение при освобождении объектов. Вызов Free сначала проверяет, является ли ссылка на объект нулевой или нет, и если это не так, вызывается деструктор объекта Destroy.

Динамическое создание и ссылки на локальные объекты без владельцев

Вот приведенный выше код создания TTable, использующий локальную переменную в качестве ссылки на экземпляр объекта TTable:

localTable := TTable.Create(nil) ;
пытаться
с localTable сделать
начинать
ИмяБазы Данных := 'МойПсевдоним';
ИмяТаблицы := 'МояТаблица';
конец;
.
// Позже, если мы хотим явно указать область действия:
локальная таблица.Открыть;
локальная таблица.Редактировать;
localTable.FieldByName('Busy').AsBoolean := True;
локальная таблица.Пост;
в конце концов
локальная таблица.Бесплатно;
локальная таблица: = ноль;
конец;

В приведенном выше примере «localTable» — это локальная переменная, объявленная в том же методе, содержащем этот код. Обратите внимание, что после освобождения любого объекта, как правило, рекомендуется устанавливать ссылку на nil.

Слово предупреждения

ВАЖНО: не смешивайте вызов Free с передачей действительного владельца конструктору. Все предыдущие методы будут работать и действительны, но следующие должны никогда не встречается в вашем коде:

с TTable.Create(self) сделать
пытаться
.
в конце концов
Свободно;
конец;

Приведенный выше пример кода вводит ненужные удары по производительности, незначительно влияет на память и может привести к появлению трудно обнаруживаемых ошибок. Узнайте, почему.

Примечание. Если у динамически созданного компонента есть владелец (указанный параметром AOwner конструктора Create), то этот владелец несет ответственность за уничтожение компонента. В противном случае вы должны явно вызывать Free, когда вам больше не нужен компонент.

Статья изначально написана Марк Миллер

В Delphi была создана тестовая программа для динамического создания 1000 компонентов с различным начальным количеством компонентов. Программа тестирования находится внизу этой страницы. На диаграмме показан набор результатов тестовой программы, сравнивающих время создания компонентов как с владельцами, так и без них. Обратите внимание, что это только часть хита. Аналогичную задержку производительности можно ожидать при уничтожении компонентов. Время динамического создания компонентов с владельцами составляет от 1200% до 107960% медленнее, чем создание компонентов без владельцев, в зависимости от количества компонентов в форме и создаваемого компонента.

Программа испытаний

Предупреждение. Эта тестовая программа не отслеживает и не освобождает компоненты, созданные без владельцев. Благодаря тому, что эти компоненты не отслеживаются и не освобождаются, время, измеренное для кода динамического создания, более точно отражает реальное время динамического создания компонента.

Скачать исходный код

Предупреждение!

Если вы хотите динамически создать экземпляр компонента Delphi и явным образом освободить его позже, всегда указывайте nil в качестве владельца. Невыполнение этого требования может привести к ненужному риску, а также к проблемам с производительностью и обслуживанием кода. Прочтите статью «Предупреждение о динамическом создании экземпляров компонентов Delphi», чтобы узнать больше.

голоса
Рейтинг статьи
Статья в тему:  Приветствую Божественную Правительницу, Королеву Киша
Ссылка на основную публикацию
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
Adblock
detector