Динамическое создание большого кол-ва контролов

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Re: Динамическое создание большого кол-ва контролов

Сообщение qivi » 09.10.2014 19:33:55

Вот список. Несколько предупреждений:
1. Компонент написан для личнх целей поэтому кондовый и имеет ряд условностей
2. Это точно работает при компиляции юникодовой версией FPC для Linux GTK, в других средах могут быть незначительные нюансы по отображению и проблемы с кодировкой.
3 Я принудительно определяю кодовую страицу {$codepage UTF8} и использую строки типа UnicodeString со всеми вытекающими (мне уже рассказывали какое это страшное зло но пока не устаканится ситуация со строками в FPC+Lazarus меня устраивает только этот вариант).
По этой части вроде всё.

Ещё, в первой версии списка количество отображаемых строк определялось динамически при ресайзе, но тогда высота строки была фиксированной, когда мне потребовалось автоопределение высоты полезли глюки и я убрал код динамического расчёта количества строк, теперь количество строк фиксированно и задаётся через проперти... если не устраивает се ля ви...
Вложения
Список.7z
(5.47 КБ) Скачиваний: 560
Аватара пользователя
qivi
энтузиаст
 
Сообщения: 703
Зарегистрирован: 19.01.2009 13:45:54
Откуда: Россия

Re: Динамическое создание большого кол-ва контролов

Сообщение zub » 09.10.2014 23:34:33

>>А вот такой проект попробуйте:
Когда в руках молоток - всё кажется гвоздями. Это не тест, а не пойми что.
Простое правило - обрабатывай (в данном случае - создавай) только то что используется (в данном случае - видимо) и всё будет летать.
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Динамическое создание большого кол-ва контролов

Сообщение Sharfik » 10.10.2014 02:04:42

Роняю молоток себе на ногу....

Тест: выполнение создания 800 панелей.
Алгоритм автора:
Время генерации 6225,00000000001 мс
Добавление в исходный код функции с SendMessage(c.Handle, WM_SETREDRAW, 0, 0)
Время генерации 5389,00000000053 мс
Добавление в исходный код ScrollBox1.Visible:=false/true
Время генерации 327,999999999751 мс

Вся фигня в том, что ScrollBox1 съедает 800 штук, но 1000 уже сам по себе не переваривает и виснит, даже при 327мс генерации. Точнее 820 он тянет, но не 821.
Почему так и в чем крутость ScrollBox1.Visible=false предлагаю разобраться автору тему и рассказать нам позже :roll:

Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  i,w : integer;
  BufPanel : TPanel;
  t1, t2 : TTime;
  kList:TList;
begin
  t1 := Time;
  w:=ScrollBox1.Width;
  ScrollBox1.Visible:=false;
  for i := 0 to CtrlsNumSpinEdit.Value - 1 do
  begin
    BufPanel := TPanel.Create(Self);
    BufPanel.SetBounds(0, i*40 + 1, w, 40);
    BufPanel.Align := alTop;
    BufPanel.Caption := 'Панель #' + IntToStr(i+1);
    ScrollBox1.InsertControl(BufPanel);
  end;
  ScrollBox1.Visible:=true;
  t2 := Time;
  Memo1.Lines.Add('Время генерации ' + FloatToStr((t2 - t1)*3600*24*1000) + ' мс');
end;
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 791
Зарегистрирован: 20.07.2013 01:04:30

Re: Динамическое создание большого кол-ва контролов

Сообщение sign » 10.10.2014 06:19:40

Граница - 820 элементов.
До этого - стреляет молниеносно, после - зависает.
Наверное, дело в некоторых внутренних ограничениях.
Вам 820 разом элементов хватит?

Код: Выделить всё
var BF: Array of Pointer;
    Cnt: Integer = 820;

procedure TForm1.Button3Click(Sender: TObject);
var i, aWidth: Integer;
    P: TPanel;
    t1, t2, t3, t4: TTime;
begin
  t1 := Time;
  SetLength(BF, Cnt);
  aWidth := ScrollBox1.Width;
  for i := 0 to Cnt-1 do begin
    P := TPanel.Create(Self);
    P.Visible := False;
    P.SetBounds(0, 0, aWidth, 40);
    P.Align := alTop;
    P.Caption := 'Панель #' + IntToStr(i + 1);
    ScrollBox2.InsertControl(P);
    BF[i] := P;
  end;
  ScrollBox2.Visible := False;
  for i := 0 to Cnt-1 do begin
    TPanel(BF[i]).Visible := True;
  end;
  ScrollBox2.Visible := True;
  t2 := Time;
  ShowMessage(Format('Запуск: %s.  Окончание: %s', [TimeToStr(t1), TimeToStr(t2)]));
end;
1.jpg


И разумеется!!!
Размещать при Visible = True сотни элементов - стрелять себе в ногу. Зачем?
Разместили в невидимом элементе всё что нужно, включили этот элемент на показ.
sign
энтузиаст
 
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Re: Динамическое создание большого кол-ва контролов

Сообщение ya_vanka » 10.10.2014 11:02:30

Да, про Visible я стормозил, и в случае с генерацией только панелей это выход.

Но в реальном проекте (где на панели еще 30 контролов) это, увы, не особо помогает. При том, что у ScrollBox.Visible := false и у панели на которой создаются контролы тоже Visible := false и панелей 100 штук отображение занимает секунд 10.

В целом думаю сменить концепцию на использование списка с OwnerDraw и использование контролов только для текущего редактируемого элемента.
ya_vanka
новенький
 
Сообщения: 89
Зарегистрирован: 07.08.2013 14:28:41

Re: Динамическое создание большого кол-ва контролов

Сообщение pupsik » 10.10.2014 12:15:29

qivi весьма нормальная реализация. Решил проверить: 50 к боксиков - легко рисуются. Единственная задержка - если боксы не сильно загружены строками (при 1к + начинаются глюки с движением по списку).

ya_vanka никто не знает что вы хотите реализовать. Хотя, уже более менее понятно (со второй стр....) Но то что вы начали пересматривать ваш вариант - гуд. Только вот "держать" можно около 10 -+ панелей (видимых), а остальное, показывать по мере возможности и необходимости. Своеобразный dbCtrlGrid delphi.
Но это варианты, а по сути вам писать (решать).
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

Re: Динамическое создание большого кол-ва контролов

Сообщение MiniQ » 10.10.2014 13:20:29

Может обратите внимание на VirtualTreeView? там примеры и на 100 тыс. записей и все летает
MiniQ
новенький
 
Сообщения: 81
Зарегистрирован: 28.01.2013 16:31:55

Пред.

Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11

Рейтинг@Mail.ru