Модераторы: Snowy, MetalFan, bems, Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> создание обьекта, каксоздать 
:(
    Опции темы
Gromover
Дата 19.6.2008, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 28.2.2008

Репутация: нет
Всего: нет



Помогите как заставить приложение самому создавать внутри себя обьекты
Ну это типа button1.create(какие тут должны быть параметры)
и где эти параметры можно найти.
PM MAIL   Вверх
Virtuals
Дата 19.6.2008, 09:59 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 1
Всего: 11



не помню где нашел...

25.2. Компоненты в runtime
десь я опишу маленький пример, который ответит сразу на два поставленных
мне вопроса: как создавать компоненты во время выполнения программы и как
ими управлять. Что такое runtime? Твоя прога может находиться в двух
состояниях - designtime (время создания проекта) и realtime (время выполнения проекта).
Мы сегодня будем создавать компоненты не рисованием на форме, а чистым кодом уже во
время выполнения программы.
Рис 25.2.1. Форма будущей программы
Создай новый проект и брось на него два компонента TLabel рисунок 25.2.1. Всё
остальное будем делать ручками. Для начала, в разделе private объявим переменную
CompList типа TList. TList - это "объект-контейнер", который может хранить в себе кучу
других. Точнее сказать, он хранит только ссылки, но это не главное. Главное - TList
позволяет хорошо управлять хранящимися в нём объектами.
На событие OnCreate напиши:
613
procedure TForm1.FormCreate(Sender: TObject);
begin
CompList:=TList.Create;
end;
Здесь мы инициализируем нашу переменную CompList с помощью объекта TList. Во
время инициализации выделяется память под нашу переменную. Сразу же на событие
OnDestroy пишем:
procedure TForm1.FormDestroy(Sender: TObject);
begin
CompList.Free;
end;
Здесь мы освобождаем выделенную память для переменной CompList.
Теперь создадим обработчик события нажатия мышкой OnMouseDown. По нажатию
кнопкой, мы будем создавать на форме новый компонент TPanel. Давай в нём напишем
следующий код:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
TempPanel:TPanel;//Объявляю переменную для панели
begin
//Создаю панель. В скобках у Create указан будущий владелец
TempPanel:=TPanel.Create(Form1);
TempPanel.Left:=X; //Устанавливаю левую и правую координату
TempPanel.Top:=Y; //в X и Y позицию, где нажата кнопка мыши
TempPanel.Width:=20; //Устанавливаю ширину
TempPanel.Height:=20; //Устанавливаю высоту
//Далее устанавливаю обработчик нажатия на эту панель
TempPanel.OnMouseDown:=PanelMouseDown;
//Добавляю панель в контейнер CompList (CompList.Add)
//и сохраняю результат в TempPanel.Tag
TempPanel.Tag:=CompList.Add(TempPanel);
Form1.InsertControl(TempPanel); //Вставляю панель на форму
end;
Для начала вспомним, что это за свойство Tag у компонента TPanel. Это просто
целое значение, которое ты можешь использовать по своему усмотрению. Именно этим
свойством мы и будем часто пользоваться во время программирования нашего примера.
Теперь разберём написанный код. В разделе var я объявил одну переменную
TempPanel типа TPanel. Это временная переменная, в которой будет инициализироваться
новая панель. В первой же строчке кода обработчика я инициализирую эту переменную,
как панель. В качестве параметра методу Create я должен передавать имя объекта,
614
который будет являться родителем создаваемого компонента. Я передаю нашу главную
форму, потому что компонент будет размещаться именно на нём.
Следующим этапом, я устанавливаю левую и правую позицию панели в координаты,
где мы щёлкнули мышкой (X и Y, которые нам переданы в обработчике, указывают на
точку, в которой была нажата кнопка мышки). Далее, я устанавливаю ширину и высоту
панели. Я решил занести туда значение 20 (просто так захотелось).
Теперь об обработчике события TempPanel.OnMouseDown. Я туда засунул имя
функции PanelMouseDown. Но такой функции нет среди стандартных функций и среди
моего проекта. Поэтому мы должны её создать сами. Как это сделать эффективно? Вот
тебе мой совет:
1. Мы создаём обработчик для TPanel, поэтому временно поставь один экземпляр
панели на форму в произвольное место.
2. Создай для него обработчик на OnMouseDown и переименуй его в
PanelMouseDown.
3. Напиши нужный текст (я его покажу ниже) и можно удалять временно созданный
на форме экземпляр TPanel.
Таким образом, ты можешь быть уверен, что ошибок не будет, потому что Delphi
сама пропишет функцию PanelMouseDown где надо и укажет все необходимые
параметры.
Если захочешь объявлять эту функцию вручную, то напиши в разделе private:
procedure PanelMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Объявлять можно и до private, там где объявляет Delphi обработчики событий. А
ниже опиши саму функцию
procedure TForm1.PanelMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
end;
Обязательно нужно следить, чтобы количество и тип параметров точно совпадали с
необходимыми. У каждого обработчика свои параметры и при объявлении процедуры
вручную, нужно относиться к этому вопросу очень внимательно. Именно поэтому я
советую тебе первый способ, с временной панелью, когда Delphi сам создаст обработчик
для одной панели, а ты будешь использовать его для других.
Всё, панель готова и её надо сохранить в нашем контейнере CompList. Для этого
нужно выполнить метод Add нашего контейнера, в качестве параметра передать ему нашу
панель:
CompList.Add(TempPanel)
Этот метод добавит панель в контейнер и вернёт нам индекс компонента в
контейнере. Этот индекс я сохраняю в свойстве Tag нашей панели TempPanel. Это
свойство абсолютно не влияет на сам компонент, а мне этот индекс пригодится.
Теперь давай посмотрим на функцию PanelMouseDown, которая должна быть такой:
procedure TForm1.PanelMouseDown(Sender: TObject; Button: TMouseButton;
615
Shift: TShiftState; X, Y: Integer);
begin
Label1.Caption:=IntToStr(TPanel(CompList.Items[TPanel(Sender).Tag]).Left);
Label2.Caption:=IntToStr(TPanel(Sender).Left);
end;
Здесь две строки. Обе строки выполняют одно и тоже, но по-разному. Обе строки
записывают в свой ТLabel левую позицию панели, по которой ты щёлкнул.
Первая строка, чтобы получить левую позицию панели использует CompList, а
вторая работает с панелью напрямую. Рассмотрим сначала вторую строку. В ней
основным является выражение TPanel(Sender).Left. Sender - передаётся нам процедурой
обработчиком PanelMouseDown. В нём записан указатель на объект, который
сгенерировал событие OnMouseDown. В нашем случае это будет указатель на панель, по
которой ты щёлкнул. Так как мы точно уверены, что это панель, то мы так и показываем
TPanel(Sender). Этим мы приводим Sender к TPanel и теперь ты можешь использовать все
свойства и методы панели, для примера нам достаточно свойства Left. Если бы мы знали
точное имя панели, то этого писать не пришлось бы. Но это невозможно, потому что все
создаваемые в Runtime панели (а их можно создать любое количество) у нас используют
один обработчик нажатия мышкой, и мы не знаем, по какой именно панели был
произведён щелчок. Получив значение левой позиции, мы переводим целое значение
левой позиции в строку с помощью IntToStr.
Первоя строка очень похожа на вторую, только внутри TPanel() мы используем не
Sender, а CompList.Items[TPanel(Sender).Tag], т.е. значение из конейнера. Чтобы получить
первое значение из контейнера, нужно написать CompList.Items[0], для второго
CompList.Items[1], для третьего CompList.Items[2] и т.д. Но по какой именно панели
произведён щелчок? Чтобы это узнать я пишу TPanel(Sender).Tag, то есть получаю
свойство Tag (там хранятся индекс панели) панели сгенерировавшей событие. Далее, всё
происходит так же.
Запусти пример и пощёлкай по форме. По каждому щелчку будут создаваться
панели. Потом попробуй пощёлкать по самим панелям. На двух TLabel будут появляться
значения левой позиции панель, по которым ты щёлкал.
Рисунок 25.2.2 Пример работы программы.
Теперь я хочу тебе показать ещё несколько интересных свойств и методов, которые
есть у контейнера TList:
Count – в этом свойстве храниться количество элементов в контейнере.
616
Items – здесь хранятся ссылки на элементы контейнера. Для доступа к ссылкам
нужно написать Items[Индекс элемента].
Clear – очистить список.
Delete – удалить элемент из списка. В качестве единственного параметра нужно
указать индекс удаляемого элемента.
Exchange – поменять в контейнере местами два элемента. Здесь два параметры –
индексы меняемых местами компонентов.
First – получить указатель на первый элемент списка. Это то же самое, что и
записать Items[0].
IndexOf – получить индекс указанного в качестве параметра объекта. Допустим, что
ты знаешь объект (TPanel) и хочешь узнать, под каким индексом он расположен в
контейнере. В этом случае ты можешь написать следующий код:
CompList.IndexOf(Panel1). Если такой панели не найдено в списке, то тебе будет
возвращено значение –1, иначе правильный индекс указанной панели.
Insert – вставить новый элемент. У этого метода два параметра – индекс, под
которым надо вставить элемент и сам элемент.
Last – получить последний элемент списка. Это то же самое, что использовать
свойство Items[Count - 1].
Move – переместить элемент в новое место. У метода два параметра – индекс
элемента, который надо переместить и индекс, который должен получить элемент.
Pack – при удалении элементов из контейнера, они просто помечаются, как нулевые.
Выполняя этот метод, все нулевые элементы уничтожаются, и занятая ими память
освобождается.
Remove – удалить элемент. В качестве параметра нужно указывать элемент, который
надо удалить, например CompList.Remove(Panel1).
Давай добавим в наш пример возможность удаления панели с формы и из
контейнера. Это будет происходить по нажатию правой кнопки мышки по компоненту.
Добавь с конец процедуры PanelMouseDown следующий код:
if Button=mbRight then
begin
index:=TPanel(Sender).Tag;
TPanel(CompList.Items[index]).Free;
CompList.Delete(index);
for i:=index to CompList.Count -1 do
TPanel(CompList.Items[i]).Tag:=TPanel(CompList.Items[i]).Tag-1;
end;
В разделе var этой процедуры нужно объявить две переменные index и i. Обе они
будут числами целого типа.
Теперь разберём код. Сначала я проверяю, если нажата правая кнопка мыши, то
нужно удалить компонент, по которому щёлкнули. Для этого, я сначала сохраняю индекс
компонента TPanel(Sender).Tag в переменной index. Это необходимо, потому что после
уничтожения компонента TPanel(Sender) не будет существовать, и я не смогу получить
доступ к его свойству Tag.
Следующим этапом происходит удаление. Сначала я уничтожаю сам компонент -
TPanel(CompList.Items[index]).Free, а после это уничтожаю ссылку на него в контейнере -
CompList.Delete(index). Вроде бы всё удалили, но программа после этого будет работать
неправильно. Допустим, что у нас в контейнере было 5 элементов, и мы удалили 3-й. По
идее, в контейнере должны остаться элементы с индексами 1, 2, 4, 5, а 3-й должен
отсутствовать. Но реально индексы перестроятся, и мы увидим индексы 1, 2, 3, 4. Если мы
попытаемся оставить всё так, как есть, то программа будет нестабильна. Если ты
щёлкнешь, по последней созданной панели, то программа обратиться к элементу в
контейнере под номером 5, потому что в свойстве Tag панели находиться цифра 5. Но
такого элемента не существует и произойдёт ошибка. Поэтому нам надо
подкорректировать свойства Tag у всех панелей начиная с удаляемой. Для этого я
запускаю цикл от индекса удаляемой панели до последнего элемента списка и уменьшаю
их свойство Tag:
for i:=index to CompList.Count -1 do
TPanel(CompList.Items[i]).Tag:=TPanel(CompList.Items[i]).Tag-1;
Вот теперь у меня в контейнере будут элементы с индексами от 1 до 4 и у всех
панелей на форме в свойстве Tag будут правильные значения.

Добавлено через 5 минут и 58 секунд
вот код

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  Runtime.rar 2,36 Kb
PM MAIL ICQ   Вверх
pseud
Дата 19.6.2008, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 10
Всего: 40



Virtuals, -1 за оформление

Gromover

допустим у тебя переменная Button1 в Form1:
Код

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  public
    Button1: TButton;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1 := TButton.Create(Self);
  Button1.Name := 'Button1';
  Button1.Left := 100;
  Button1.Top := 100;
  Button1.Parent := Self;
end;

end.



--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
Beltar
Дата 19.6.2008, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 0
Всего: 7



Если коротко, то как правило у компонентов конструктор такой: Create(AOwner:TComponent); Владельцем обычно является форма или датамодуль. Для графических компонентов нужно указать Parent. И главное Free не забудь.

По-моему этот вопрос заслуживает статуса запрещенного, как сделали на Delphikingdom для часто задаваемых элементарных вопросов возникающих от неумения\нежелания читать книжки и юзать поиск.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
pseud
Дата 19.6.2008, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 10
Всего: 40



Цитата(Beltar @  19.6.2008,  13:35 Найти цитируемый пост)
Владельцем обычно является форма или датамодуль

а своя фабрика или свой мусоросборщик или TPageControl и много другое?

Цитата(Beltar @  19.6.2008,  13:35 Найти цитируемый пост)
 И главное Free не забудь.

если владельца не назначил, то конечно не забудь.
а если назначил, то можешь не Free, т.к. владелец для того и назначается, чтоб за детками прибирать.



--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
Beltar
Дата 19.6.2008, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 0
Всего: 7



Цитата

а своя фабрика или свой мусоросборщик или TPageControl и много другое?


А оно надо? Когда вы в последний раз создавали компонент в рун-тайм не считая тестирования своего компонента до его регистрации в VCL? TPageControl\TPanel\и т. д. в этом плане ничем от формы не отличаются.

Добавлено через 3 минуты и 40 секунд
Цитата

а если назначил, то можешь не Free, т.к. владелец для того и назначается, чтоб за детками прибирать.


Угу. smile Мораль, нефиг слушать всех подряд на форуме, они могли книжки очень давно читать. smile


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
pseud
Дата 19.6.2008, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 10
Всего: 40



Цитата(Beltar @  19.6.2008,  14:31 Найти цитируемый пост)
А оно надо? Когда вы в последний раз создавали компонент в рун-тайм 


если коротко, то ответ "сегодня"
если подробно, то слушай и я расскажу тебе эту грустную историю:
Цитата

была у меня задача, в которой было 50 справочников.
и надо было мне реализовать интерфейс пользователя по управлению этими справочниками.
а лень мне было рисовать 50 гридов, 50 форм для редактирования.
и сделал я механизм динамического построения всей этой штуки согласно параметрам зашитым в БД.
... здесь должна быть куча текста о реализации ...


Добавлено через 8 минут и 14 секунд
и это самый безобидный пример.


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
Beltar
Дата 19.6.2008, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 0
Всего: 7



LOL. smile Моя грустная история с рун-тайм созданием: Тоже справочники. Начал я кодить. Сделал на работе свою первую софтину, была это БД с кучкой справочников. Все справочники в одном окошке с минимальным функционалом. Очевидно, что в следующем проекте оно тоже понадобиться. Решил я сделать компонент, которй бы содержал эту форму, а я просто в обджект инспекторе таблички добавлял. И делал нужной Show. Сделал в Delphi 7. Все работало. Потом я поставил себе BDS 2006, поначалу все было нормально, но потом начали появляться глюки при бросании этого компонента на форму. Проблему решить не удалось, и я пошел по пути наименьшего сопротивления. Создавать компонент в рун-тайме.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0871 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.