| « Поставить закладку » « Сделать стартовой » | |||
|
|||
|
Массив из элементов - как с ним бороться или как с ним дружить
Автор: Ижогин Ян Валерьевич Однажды я опубликовал на статью, в которой создавались массивы из различных компонентов, вплоть до форм. Письма, полученные мною после опубликования, были посвящены зачастую не основной теме статьи, а вопросам по созданию массивов из объектов. Здесь я постараюсь ответить на задаваемые вопросы «оптом». Я не претендую на истину в последней инстанции, но, думаю, что этот материал может быть кому-то полезен:). Здесь информация о
Создание массива Ну тут всё просто. Объявляем var Arr: array[1..n] of TEdit; //к примеруи можно работать! Так-же можно объявить и многомерный и даже динамический массив. var Arr1: array [1..7, 1..5] of TEdit; var Arr2: array of TEdit; Работа с массивомОпасно не падать, а биться о землю, скалы и другие твёрдые
предметы. Итак, с созданным массивом надо что-то делать. Ну, для начала, чем-то заполнить. А, в отличие от чисел и строк, которые задаются в виде констант и выражений, объекты, помещаемые в наш массив, нужно создавать. Т.е. если мы описали var ByteArr: array[1..2] of byte;то можно написать ByteArr[1]:=3; Что же писать после := для массива из объектов?
Их же как-то создать надо? (из форума) Заполнение массива во время работы программы.Этот способ удобен в том случае, когда нужно создать много объектов или число и свойства их заранее неизвестны (в одной программе мне нужно было разбросать по экрану случайным образом все буквы алфавита, а потом еще что-то с ними делать). Действия довольно стандартны. В цикле создаём объекты и присваиваем их элементам массива с помощью следующей конструкции.
For i:=<начальное значение> to<конечное значение> do begin
<имя массива>[i]:=<имя класса>.Create(Self);
<имя массива>[i].Parent:=Self; //за объект ответит форма, на которой он создан
//<присвоение других свойств - по необходимости>
end;
После этих действий у нас на форме появятся необходимые компоненты, к которым
можно обращаться, используя индекс массива, например так: <имя массива>[i].
В следующем примере по щелчку по кнопке будет предложено ввести требуемое количество полей, которое и будет создано в центре формы. procedure TForm1.Button1Click(Sender: TObject);
var c: string;
i,n:integer;
begin
c := InputBox('Введите','число:','7');
try
n := StrToInt(c);
except
on EConvertError do ShowMessage('Что-то не срослось...');
end;//Try
SetLength(Arr2, n);
for i:=0 to n-1 do begin
Arr2[i] := TEdit.Create(Self);
Arr2[i].Parent := Self;
//Эти две строки создают компонент, далее произвольные действия.
Arr2[i].Top:=i*Arr2[i].Height;
Arr2[i].Left:=(ClientWidth-Arr2[i].Width)div 2 ;
Arr2[i].Text:='Поле '+IntToStr(i);
end;//for
Button1.Visible:=FormArraylse;
end;
При заполнении многомерного массива компонентов таким способом никаких подводных камней нет - организуем несколько циклов. procedure TForm1.FormCreate(Sender: TObject); var i, j: byte; begin for i:=1 to 7 do for j:=1 to 5 do begin Arr1[i,j]:=TEdit.Create(Self); Arr1[i,j].Parent := Self; //Эти две строки создают компонент, далее произвольные действия. Arr1[i,j].Top:=(i-1)*Arr1[i,j].Height; Arr1[i,j].Left:=(j-1)*Arr1[i,j].Width; Arr1[i,j].Text:='Поле '+ IntToStr(i*j); end;//for j end; Результат - таблица из Edit`ов, с индексированными ячейками. Таким образом можно создать даже массив из форм. Разместим форму для создаваемого массива в Unit2. uses Unit2;//задействуем его var FormArray: array [1..5] of TForm2; //Теперь нам нужно создать массив FormArray, разместить его на главной форме и заполнить его изображениями. //Делать это лучше не во время создания формы, а например во время активации. procedure TForm1.FormActivate(Sender: TObject); var i: byte; begin for i:=1 to 5 do begin FormArray[i]:=TForm2.Create(Self); FormArray[i].Parent:=Self;// Создание формы // и что-то с ней делаем FormArray[i].Visible:=True; //Вывод формы на экран FormArray[i].Top:=i*50//Выбор места расположения (здесь ставятся ваши значения) end;//for end; Данный способ подойдёт тем, кто не боится большого кода - ведь все требующиеся свойства создаваемых объектов придётся определять вручную и представляет себе как расположатся на форме созданные объекты. В противном случае придётся потратить немало времени на подбор различных свойств. Впрочем, есть и другой путь... Использование объектов, созданных во время проектирования формыРаньше как было - код, компиляция, запуск, а лицо невесты можно увидеть только после свадьбы. Сейчас всё намного гуманнее. Есть проект, в нём форма, а на форму ставишь компоненты. И почему бы их не «объединить» в массиве? Итак, на вашу форму во время проектирования помещено
несколько Edit`ов, и вы хотите присвоить их элементам массива Arr. procedure TForm1.FormCreate(Sender: TObject);
var i, j: byte;
begin
j:=1;
for i:=0 to ComponentCount-1 do //просматриваем
if (Components[i] is TEdit) then begin //если подходит
Arr[j]:=(Components[i] as TEdit);//помещаем
j:=j+1;
end;//if
// а теперь посмотрим, в каком порядке они попали в массив
for i:=1 to 5 do
Arr[i].Text:='Arr['+IntToStr(i)+']';
end;
На самом деле, такой способ не намного менее коряв,
чем присваивание «напрямую». В массив попадут все Edit`ы, присутствующие на
форме, причём в порядке их создания. А как быть, если хочется поместить их не
все и в своём порядке? procedure TForm1.FormCreate(Sender: TObject);
var i: byte;
begin
for i:=0 to ComponentCount-1 do
if Components[i].Tag>0 then //Tag больше нуля
Arr[Components[i].Tag]:=(Components[i] as TEdit);//Значит клиент наш!
end.
Смотрится значительно лучше. Для организации двух массивов пронумеруйте (протагируйте) компоненты, предназначенные для помещения в первый из массивов как обычно, а во второй, например, с десяти (или с любого другого числа, желательно с круглого - проще считать). Затем напишите что нибудь вроде var Arr1: array [1..3] of TEdit;
Arr2: array [1..3] of TEdit;
procedure TForm1.FormCreate(Sender: TObject);
var i: byte;
begin
for i:=0 to ComponentCount-1 do
if Components[i].Tag>0 then
if Components[i].Tag<10 then
Arr1[Components[i].Tag]:=(Components[i] as TEdit)
else
Arr2[Components[i].Tag-10]:=(Components[i] as TEdit);
end;
При создании многомерного массива используем тот-же приём - немного поработаем с тагом. Edit`ы протагированы 11.12.13.21.22.23: var Arr1: array [1..3,1..2] of TEdit; procedure TForm1.FormCreate(Sender: TObject); var i, j: byte; begin for i:=0 to ComponentCount-1 do if Components[i].Tag>0 then Arr1[Components[i].Tag mod 10,Components[i].Tag div 10 ]:=(Components[i] as TEdit); //убедимся, что всё получилось for i:=1 to 3 do for j:=1 to 2 do arr1[i,j].text := IntToStr(i)+' '+IntToStr(j); end; Если вам надо создать два массива из разных компонентов, то не напрягайтесь со сложным извлечением индекса из тага, а организуйте проверку типа. var ArrE: array [1..3] of TEdit;
ArrC: array [1..8] of TComboBox;
procedure TForm1.FormCreate(Sender: TObject);
var i: byte;
begin
for i:=0 to ComponentCount-1 do
if Components[i].Tag>0 then begin
if (Components[i] is TEdit)
then ArrE[Components[i].Tag]:=(Components[i] as TEdit);
if (Components[i] is TComboBox)
then ArrC[Components[i].Tag]:=(Components[i] as TComboBox);
end;//if
end;
При необходимости создания более сложных массивов - комбинируйте эти способы. Лирическое отступление. Присвоение объектов происходит не совсем так, как у «обычных» переменных. Если у переменных присваивние не отоджествляет переменные т.е. после a:=3;b:=a;a:=5; в переменной b находится 3, а не 5, то с объектами всё наоборот. После ArrL[1]:=Label1; ArrL[1] и Label1 cтановятся одним объектом, и например ArrL[1].Caption:='Вася'; изменит надпись Label1. В некоторых языках для разруливания этой ситуации для блондинок введён специальный оператор присваивания объектов (Vb, set). Ну мы то, Дельфийцы, народ умный... Получение номера элемента массива в процедуре обработки событияЧтобы узнать индекс элемента массива, с которым произошло событие придётся придётся сравнить переменную Sender, использующуюся обработчиком события, со всеми элементами массива и при совпадении извлечь индекс. Похоже только так... Впрочем, может кто знает и лучший способ. var ArrB: array [1..3] of TButton;
n: byte;// Здесь будет храниться индекс
procedure TForm1.Clicker(Sender:TObject);
var i: byte;
begin
for i:=1 to 3 do
if Sender = ArrB[i] then n:=i;
//находим индекс компонента, к которому относится событие
ShowMessage('Нажата кнопка '+IntToStr(n)); //что-то делаем
end;
procedure TForm1.FormCreate(Sender: TObject);
var i: byte;
begin
for i:=0 to ComponentCount-1 do
if Components[i].Tag > 0
then ArrB[Components[i].Tag]:=(Components[i] as TButton);//наполняем массив
for i:=1 to 3 do
ArrB[i].OnClick:=Clicker; //устанавливаем обработчик
end;
Ну, как говорится, спасибо за внимание. Ижогин Ян Валерьевич. Рубрика: Разные статьи
Вышел MySQL 5.1.30, первый стабильный рели....
После публикации 29 тестовых версий анонсирован первый стабильный релиз MySQL 5.1, пригодный для промышленной эксплуатации и обеспечивающий увеличение производительности для "тяжелых" SQL запросов, по сравнению с MySQL 5.0, примерно на 15-20%. Главные новшества появившиеся в MySQL 5.1:
Подробнее... |
Рубрика: MySQL
| Добавлено: 28.11.2008
Тестирование параллельных программ.
Тестирование параллельного программного обеспечения представляет собой более сложную задачу по сравнению с тестированием последовательной программы. Программист должен знать о подводных камнях при тестировании параллельного кода, имеющихся методологиях и инструментарии.
Подробнее... |
Рубрика: Тестирование
| Добавлено: 28.11.2008
Архитектура AMD64 (EM64T).
Аннотация. В статье кратко рассматривается архитектура AMD64 компании AMD и ее реализация EM64T компании Intel. Описаны особенности архитектуры, ее возможности, достоинства и недостатки.
Подробнее... |
Рубрика: Архитектура AMD
| Добавлено: 27.11.2008
Остальные статьи: |
Цитата дня (все,добавить):
|
Realcoding.NET
© 2003-2008 |
Контакты |
Реклама на сайте
|