Форум: "Основная";
Текущий архив: 2003.11.27;
Скачать: [xml.tar.bz2];
ВнизВремя создания динамических компанентов Найти похожие ветки
← →
Pattern (2003-11-17 13:53) [0]Столкнулся с одним принеприятнейшим моментом, что уходит очень много времени на создание, перестроение и уничтожение динамических компанент. Вот на данном примере, у меня есть массив из 500 TPanel"ей, которые размещаются в TScrollBox"е. Число создаваемых панелей может быть разным от 0 до 500, но я решил проверить сколько времени уйдёт на все 500 панелей. От полученного времени я, честно говоря, офигел. Создание и уничтожение примерно 2,5 секунды, перестроение ~5 секунд. То есть, на изначальное построение и показ панелей на форме уходит примерно 7,5 секунд!!! При этом я же ещё никак эти панели не обрабатывал, а при обработке, я так понимаю, оно и того выше будет! При увеличении массива до 1000, эксперимент с 1000 панелями возрос примерно чуть больше, чем в 2 раза. d8-(
Так вот у меня вопрос. Можно ли как то ускорить процесс создания, уничтожения, а тем более перестроения панелей? Код прилагаю ниже, может снова что то в нём намудрил? Изначально, все приведённые функции являются процедурами, просто я их переделал в функции, чтобы отследить время, затраченное на каждую обработку. Заранее благодарю всех откликнувшихся!
var
panels: array[0..500] of TPanel;
//Создание панелей
function TForm1.ConstrucPanels_(CountPanels: Integer): Cardinal;
var
Num_: Integer;
begin
Result := GetTickCount;
for Num_ := 0 to (CountPanels - 1) do
begin
panels[Num_] := TPanel.Create(ScrollBox1);
panels[Num_].Parent := ScrollBox1;
panels[Num_].Visible := False;
end;
RebuildPanels_(CountPanels);
Result := GetTickCount - Result;
end;
//Перестроение панелей
function TForm1.RebuildPanels_(CountPanels: Integer): Cardinal;
var
left_, top_, Num_: Integer;
begin
Result := GetTickCount;
SendMessage(ScrollBox1.Handle, WM_VSCROLL, SB_TOP, 0);
left_ := 0;
top_ := 0;
for Num_ := 0 to (CountPanels - 1) do
begin
if (left_ * panels[Num_].Width + panels[Num_].Width) > ScrollBox1.ClientWidth then
begin
left_ := 0;
Inc(top_);
end;
panels[Num_].Left := left_ * panels[Num_].Width;
panels[Num_].Top := top_ * panels[Num_].Height;
panels[Num_].Visible := True;
Inc(left_);
end;
Result := GetTickCount - Result;
end;
//Уничтожение панелей
function TForm1.DestructPanels_(CountPanels: Integer): Cardinal;
var
Num_: Integer;
begin
Result := GetTickCount;
for Num_ := 0 to (CountPanels - 1) do
panels[Num_].Destroy;
Result := GetTickCount - Result;
end;
← →
Hooch (2003-11-17 13:58) [1]если не секрет, а для чего нужно на одной форме от 500 до 1000 панелей ?
← →
Reindeer Moss Eater (2003-11-17 14:02) [2]Все без исключения компоненты создаются динамически. В Delphi нет статических объектов.
Как ускорить процесс? Уменьшить кол-во создаваемых экземпляров.
← →
Danilka (2003-11-17 14:04) [3]вероятно, панели можно заменить чем-то другим, например, наследником грида? :))
← →
Pattern (2003-11-17 14:10) [4]
> Hooch
Это будет что то на подобии просмоторщика картинок... Просто у меня компанента сделана на основе TPanel, в неё встроена TImage и несколько TLabel (для информации). Но чтобы объяснить суть моего вопроса я решил применить обыкновенный TPanel.
> Reindeer Moss Eater
Это я понимаю, но ведь нельзя предугадать, сколько конечный пользователь выберет этих панелей. Ведь может и все 500. Не уже ли никак нельзя оптимизировать код?
← →
Radionov Alexey (2003-11-17 14:13) [5]Повыкидывать инварианты из циклов и кое-что еще.
У меня ускорилось в 5 раз по сравнению с тем, что было:
Function TForm1.ConstrucPanels_(CountPanels: Integer): Cardinal;
Var
Num_: Integer;
Tmp: TPanel;
Begin
Result := GetTickCount;
For Num_ := 0 To (CountPanels - 1) Do
Begin
Tmp := TPanel.Create(ScrollBox1);
With Tmp Do
Begin
Visible := False; - сначала гасим, а потом родителя назначаем (чтобы не повадно рисоваться было).
Parent := ScrollBox1;
End;
panels[Num_] := tmp;
End;
RebuildPanels_(CountPanels);
Result := GetTickCount - Result;
End;
Function TForm1.RebuildPanels_(CountPanels: Integer): Cardinal;
Var
left_, top_, Num_,Ws,Wp: Integer;
Begin
Result := GetTickCount;
SendMessage(ScrollBox1.Handle, WM_VSCROLL, SB_TOP, 0);
left_ := 0;
top_ := 0;
Ws := ScrollBox1.ClientWidth;
ScrollBox1.Visible := False;
For Num_ := 0 To (CountPanels - 1) Do
With panels[Num_] Do
Begin
Wp := Width;
If (left_ +1 )* Wp > Ws Then
Begin
left_ := 0;
Inc(top_);
End;
Left := left_ * Wp;
Top := top_ * Height;
Visible := True;
Inc(left_);
End;
ScrollBox1.Visible := True;
Result := GetTickCount - Result;
End;
← →
Danilka (2003-11-17 14:18) [6]>но ведь нельзя предугадать
ошибаешся, можно. он наберет столько, сколько ты ему позволишь набрать.
кроме того, использовать панели для каждой картинки... по-моему лучше нарисовать их на канвасе будет намного быстрее.
да и вообще, панель это виндявый контрол, зачем тратить ресурсы, когда можно все сделать проще.
← →
Radionov Alexey (2003-11-17 14:21) [7]>Pattern © (17.11.03 14:10)
Для того, чтобы показать много картинок не обязательно все показывать сразу. Например, делай контроль за скроллингом и подгружай только нужные картинки, а старые - выгружай.
← →
Reindeer Moss Eater (2003-11-17 14:22) [8]Это я понимаю, но ведь нельзя предугадать, сколько конечный пользователь выберет этих панелей. Ведь может и все 500. Не уже ли никак нельзя оптимизировать код?
Код оптимизировать - можно. Время создания экземпляра - нет (кроме как поменять компьютер на более мощный)
← →
Zergling (2003-11-17 14:42) [9]Panel произошла от TWinControl следовательно отжирают ресурсы у системы. Может заменить чем производным от TGraphicControl?
P.S.
Эксперементы по созданию такого количесива компонент не ставил, поэтому утверждать неберусь.
← →
Pattern (2003-11-17 14:43) [10]
> Radionov Alexey
Да ты прав! Спасибо за помощь, действительно этот код работает намного быстрее!
← →
Pattern (2003-11-17 14:46) [11]А вот ещё вопросик. Как я могу узнать создана сейчас хоть одна панель из массива или массив пуст?
← →
Семен Сорокин (2003-11-17 14:49) [12]Как я могу узнать создана сейчас хоть одна панель из массива или массив пуст?
при уничтожении приравнивай Nil и проверяй на Assigned
← →
Radionov Alexey (2003-11-17 14:51) [13]>Pattern © (17.11.03 14:46)
сначала занилить массив. А уничтожать через FreeAndNil.
Но лучше идею пересмотреть, ибо она порочна ;)
← →
Pattern (2003-11-17 15:21) [14]
> при уничтожении приравнивай Nil и проверяй на Assigned
Если честно сказать, то ничего не понял. Будьте так любезны, киньте примерчик. Самое интересное, что когда пошагово просматриваю работу программы, он говорит что
panels = (nil, nil, nil, ..., nil)
Но когда я пытаюсь дать на простую проверку
if panels[0] = nil then
он до запуска программы ругается, что нельзя применять этот метод. Где грабли?
← →
Семен Сорокин (2003-11-17 15:26) [15]Pattern © (17.11.03 15:21) [14]
лучше всего (имхо) использовать не массив, а TList, тогда вместе с удалением контрола - удаляешь Item в списке TList и проблем не будет.
← →
Pattern (2003-11-17 16:42) [16]
> лучше всего (имхо) использовать не массив, а TList, тогда
> вместе с удалением контрола - удаляешь Item в списке TList
> и проблем не будет
Хм. И как это всё будет выглядеть?
И всё таки, да простят меня модераторы данного форума за назойливость, как узнать пуст массив или нет?
← →
Digitman (2003-11-17 16:47) [17]
> как узнать пуст массив или нет
если все эл-ты массива, являющегося массивом ссылок на нечто, равны nil, то массив "пуст")
← →
Anatoly Podgoretsky (2003-11-17 16:52) [18]Удобнее использовать список
← →
vl_chel (2003-11-17 17:08) [19]при создании компонента рекомендую в качестве параметра передавать в конструктор nil сразу заблокирует перерисовку
а для хранения єкземпляров пока лучше чем TObjectList не придумано
обращение к панелиTPanel(ObjectList[I]).имя_свойства
← →
Малиновский Владимир (2003-11-17 17:15) [20]Посмотрите в сторону ACDSee. Там показывают только то, что можно увидеть сразу, остальное создается и заполняется в отдельных потоках и показывается по готовности. Все равно нормальный юзер сразу все элементы не обозрит (если только не создавать мозаику)
← →
sts (2003-11-17 17:25) [21]2 Pattern © (17.11.03 13:53)
Еще нужно не забывать отключать перерисовки всякие:
ScrollBox1.DisableAlign;
ScrollBox1.DisableAutoRange;
ConstrucPanels_(500);
ScrollBox1.EnableAutoRange;
ScrollBox1.EnableAlign;
например, ускоряет в 2 раза
2 vl_chel (17.11.03 17:08) [19]
> а для хранения єкземпляров пока лучше чем TObjectList не
> придумано
придумано : TComponentList :)
← →
sts (2003-11-17 17:36) [22]Вдогонку:
а ежели еще и Visible := false; ... Visible := true;
то и вовсе 150 мс на 500 панелей.
← →
Pattern (2003-11-17 18:02) [23]2 sts © (17.11.03 17:25)
> придумано : TComponentList :)
Вот это уже более привлекательно звучит. Только вот никак не могу сообразить, как можно сочетать его с моим примером? Если у меня
var
panels: array[0..500] of TPanel;
то как это описать для TComponentList или TObjectList?
← →
SkyRanger (2003-11-18 02:46) [24]TComponentList.Items
Lists the component references.
property Items[Index: Integer]: TComponent; default;
Description
Use Items to access components in the list. Items is a zero-based array: The first component is indexed as 0, the second component is indexed as 1, and so forth. You can read or change the value at a specific index, or use Items with the Count property to iterate through the list.
If OwnsObjects is True, reassigning an Items value frees the component that previously occupied that position in the list.
Items can contain nil references. To remove nil references and reduce the size of the array, call the Pack method.
Используй свойства этих классов для хранения... Там как написанно выше они храняться в массиве... Так что переписывать много не придется...
← →
KSergey (2003-11-18 09:52) [25]И все же использовать под каждую картинку отдельную панельку - очень плохо. Это же окно!!!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.11.27;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.008 c