Страница 1 из 2

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

СообщениеДобавлено: 08.10.2014 18:49:55
ya_vanka
В приложении есть диалог. В нем динамически создается много контролов.

Фактически "список" свойств некоего объекта. На 1 объект генерится около 30 контролов. Объектов может быть до 100.
Список обновляется (и соот. контролы пересоздаются) при показе окна диалога.

При этом прога скомпилированная в Lazarus генерит контролы на порядок (а то и больше) медленнее, чем та же прога скомпилированная в Delphi. Задержка появления окна - несколько секунд.

Почему так?
Можно ли ускорить создание контролов (это TPanel, TLabel, TEdit, TMaskEdit, TComboBox, TCheckBox, TButton, TSpeedButton)?

Когда элементов в списке больше 30, то даже Delphi вариант подтормаживает.

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

СообщениеДобавлено: 08.10.2014 19:14:30
pupsik
а если использовать чет более проще. К примеру: пересмотреть вариант отображения. К примеру, виртул тревью прикрутить, или в гриде?
А то чет оно, даже читая, страшненькое получается.

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

СообщениеДобавлено: 08.10.2014 20:04:28
zub
Зачем всё генерить? пользователи пока не многоядерные, и одновременно работать могут только с 1 контролом ввода))
Предлагаю элементы ввода просто рисовать, генерить их при необходимости - по клику, по наведению мышки и т.п, после необходимости (по ентеру, потере фокуса, уходу мышки) уничтожать и снова просто рисовать.

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

СообщениеДобавлено: 08.10.2014 20:24:34
ya_vanka
1. Даже если отбросить текущий вариант все равно хотелось бы понять почему Lazarus настолько медленнее.
2. Разве в гриде будет быстрее?
3. А есть простой способ отрисовки контрола один в один с системным видом?

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

СообщениеДобавлено: 08.10.2014 21:29:59
alexs
ya_vanka писал(а):Фактически "список" свойств некоего объекта.

Если это реальный объёект FPC - то можно RTTI грид использовать. Всё будет просто.

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

СообщениеДобавлено: 08.10.2014 21:35:48
Sharfik
ya_vanka писал(а):Когда элементов в списке больше 30, то даже Delphi вариант подтормаживает.

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

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

СообщениеДобавлено: 08.10.2014 21:43:23
ya_vanka
Если это реальный объёект FPC - то можно RTTI грид использовать


Нет, не объект FPC.


переписал его на рисование канвы


А как контролы рисовали?
Чтоб похоже на реальные контролы было?

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

СообщениеДобавлено: 08.10.2014 21:51:00
Sharfik
ya_vanka писал(а):А как контролы рисовали?
Чтоб похоже на реальные контролы было?

Я имел ввиду, что я рисую не контролы, а просто отрисовываю на канве сетку, надписи и кнопки. Потом обрабатываю положение и клики мышки с клавой, и если надо добавляю уже привычный тебе контрол по координатам. Долго и нудно такое делать. Попробуй сначала поискать как через winapi блокировать отрисовку. Типа методов beginupdate/endupdate. Может поможет.

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

СообщениеДобавлено: 08.10.2014 22:46:00
zub
>>3. А есть простой способ отрисовки контрола один в один с системным видом?
Да - модуль Themes. В gtk и qt могут быть небольшие отличия от системных контролов, емнип стрелка на комбобоксе рисуется несовсем так (или ее нет и приходится рисовать стрелку с скроллбара, непомню), наверно это зависит от используемой темы оформления. Но думаю мелочевку можно поправить багрепортами.
Как вариант - не рисовать контролы, рисовать значения - получится чтото вроде инспектора объектов

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

СообщениеДобавлено: 09.10.2014 06:27:35
sign
ya_vanka писал(а):В приложении есть диалог. В нем динамически создается много контролов.

Фактически "список" свойств некоего объекта. На 1 объект генерится около 30 контролов. Объектов может быть до 100.
Список обновляется (и соот. контролы пересоздаются) при показе окна диалога.

При этом прога скомпилированная в Lazarus генерит контролы на порядок (а то и больше) медленнее, чем та же прога скомпилированная в Delphi. Задержка появления окна - несколько секунд.

Почему так?
Можно ли ускорить создание контролов (это TPanel, TLabel, TEdit, TMaskEdit, TComboBox, TCheckBox, TButton, TSpeedButton)?

Когда элементов в списке больше 30, то даже Delphi вариант подтормаживает.

Создать массив с контролами заранее и выставлять их оттуда, по мере надобности.
Т.е. вместо создания каждый раз нужного контрола, просто переписываем ему свойства и показываем, где нужно.

Создание 10 тыс. панелей.
Win XP SP3
AMD Fx(tm)-4100 Quad-Core
3.61 ГГц. 3.25 ГБ ОЗУ
1.jpg


Добавлено спустя 8 минут 12 секунд:
Размещение одной тысячи панелей:

1.jpg

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

СообщениеДобавлено: 09.10.2014 11:10:33
pupsik
:D

и показываем, где нужно
вот вопрошающий и говорит что при показе где нужно лагает.

п.с.
Создание в памяти - это не отображение. Или я ошибаюсь?

кстати: х.з. как пытаются отобразить (нет примерного кода), или что хотят сделать.
Из вопроса я, к примеру, понял: необходимо вывести диалог на котором динамически размещены контролы (судя по вопросу - до 3к). А теперь итнересный момент: за сколько времени отрисует лазарь такое кол-во компонентов. Учитывая что потом надо форму перемещать или ресайзить.

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

СообщениеДобавлено: 09.10.2014 17:21:47
ya_vanka
sign писал(а):Создать массив с контролами заранее и выставлять их оттуда, по мере надобности.

Да, так можно, но проблема в том, что кол-во элементов списка меняется в процессе работы. Генерить сразу все (макс. кол-во) вроде как лишняя работа в большинстве случаев...

sign писал(а):Размещение одной тысячи панелей:


А вот такой проект попробуйте:

Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, Spin;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Panel1: TPanel;
    ScrollBox1: TScrollBox;
    CtrlsNumSpinEdit: TSpinEdit;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  i : integer;
  BufPanel : TPanel;
  t1, t2 : TTime;
begin
  t1 := Time;

  for i := 0 to CtrlsNumSpinEdit.Value - 1 do
  begin
    BufPanel := TPanel.Create(Self);
    BufPanel.SetBounds(0, i*40 + 1, ScrollBox1.Width, 40);
    BufPanel.Align := alTop;
    BufPanel.Caption := 'Панель #' + IntToStr(i + 1);
    BufPanel.Parent := ScrollBox1;
  end;

  t2 := Time;

  Caption := 'Время генерации ' + FloatToStr((t2 - t1)*3600*24*1000) + ' мс';
end;

end.


800 панелей генерит 3 секунды, а на 1000 уже просто подвисает. Я так и не дождался.

Win7 Pro
Intel Core i5-4570 3.2 ГГц
8 Гб ОЗУ

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

СообщениеДобавлено: 09.10.2014 17:55:34
qivi
Практиковал подобное велосипедостроение - создание списка методом динамического создания контролов в скролбоксе, порождает порядочные тормоза, прищёл к тому что создал динамичную структуру данных отделив её от контролов, а контролов вывожу заданное количество + скролбар. Наверное и это ещё то извращение, ну уж как умею.

И ещё, зачем столько панелей? В Лазарусе есть привязки.

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

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

СообщениеДобавлено: 09.10.2014 17:57:47
Sharfik
Нет среды проверить, попробуй так.
Код: Выделить всё
begin
  t1 := Time;
  ScrollBox1.BeginUpdateBounds;
  for i := 0 to CtrlsNumSpinEdit.Value - 1 do
  begin
    BufPanel := TPanel.Create(Self);
    BufPanel.SetBounds(0, i*40 + 1, ScrollBox1.Width, 40);
    BufPanel.Align := alTop;
    BufPanel.Caption := 'Панель #' + IntToStr(i + 1);
    BufPanel.Parent := ScrollBox1;
  end;
  ScrollBox1.EndUpdateBounds;
  t2 := Time;
  Caption := 'Время генерации ' + FloatToStr((t2 - t1)*3600*24*1000) + ' мс';
end;

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

СообщениеДобавлено: 09.10.2014 18:09:09
ya_vanka
qivi писал(а): могу его вечерком выложить

Давай, интересно посмотреть.


Sharfik писал(а):Нет среды проверить, попробуй так.

Ничего не изменилось.