Jump to content
Stano

Rendering form content

Recommended Posts

I dynamically generate components. Rendering was very slow. I managed to solve it.
I asked on forum.delphi.cz. I didn't get an answer. So I ask here
This is interesting. I used:

  • the ScrollBox on form
  • on it TAdvSmoothPanel - it has a canvas. I draw the lines
  • now panels on it, on which I store the generated components

The rendering is thus instantaneous. Without those panels it was for a maximum number of components with a time of ~12-13 sec. Now I estimate 1-1.5 sec 
Why is that?

Share this post


Link to post

@Stano

let's remember that "default Delphi components it's not necessary the better code than other libs on market", for sure, TAdvSmoothPanel have a code more performatic (for that it exists not?)

 

look this:   Lines: 1001 (1000 controls created on-the-fly), Time: 00:00:01.6594270    ... later, 3 click on change parent!
-------------
Changing Parent of ScrollBox1, Time: 00:00:02.2364219, New Parent: Panel1
-------------
Changing Parent of ScrollBox1, Time: 00:00:02.2367827, New Parent: Form1
-------------
Changing Parent of ScrollBox1, Time: 00:00:02.2283093, New Parent: Panel1
-------------

 

implementation

{$R *.dfm}

uses
  System.Diagnostics;

var
  SW     : TStopWatch;
  LWidth : integer = 50;
  LHeight: integer = 50;
  LLeft  : integer = 0;
  LTop   : integer = 0;

procedure NewPositionAndSize;
begin
  LWidth  := random(50 + random(200));
  LHeight := random(50 + random(50));
  LLeft   := random(Form1.ScrollBox1.Width - LWidth);
  LTop    := random(Form1.ScrollBox1.Height - LHeight);
end;

procedure TForm1.BtnCreate_Many_WinControlsClick(Sender: TObject);
var
  LClass     : TArray<TClass>;
  LWinControl: TWinControl;
  LText      : string;
  LIndex     : integer;
begin
  Memo1.Text := '';
  LClass     := [TButton, TComboBox, TListBox, TPanel, TEdit, TMemo];
  //
  NewPositionAndSize;
  //
  SW.Reset;
  SW.Start;
  //
  for var i: integer := 1 to 1000 do
    begin
      LIndex      := random(length(LClass));
      LWinControl := TWinControlClass(LClass[LIndex]).Create(Form1);
      LText       := LText + slinebreak + LWinControl.ClassName;
      //
      NewPositionAndSize;
      LWinControl.Width       := LWidth;
      LWinControl.Height      := LHeight;
      LWinControl.Left        := LLeft;
      LWinControl.Top         := LTop;
      LWinControl.Brush.Color := random($FFFF);
      //
      LWinControl.Parent := ScrollBox1;
    end;
  //
  SW.Stop;
  //
  Memo1.Lines.Add(LText);
  Memo1.Lines.Add('Lines: ' + Memo1.Lines.Count.ToString + ', Time: ' + SW.Elapsed.Duration.ToString);
end;

procedure TForm1.Btn_Put_ScrollBox_into_PanelClick(Sender: TObject);
begin
  SW.Reset;
  SW.Start;
  //
  if ScrollBox1.Parent = Panel1 then
    begin
      ScrollBox1.Parent := Form1;
      Label2.Caption    := 'ScrollBox1 Parent = ' + ScrollBox1.Parent.Name;
      ScrollBox1.Top    := 72;
      ScrollBox1.Left   := 32;
    end
  else begin
      ScrollBox1.Parent := Panel1;
      Label2.Caption    := 'ScrollBox1 Parent = ' + ScrollBox1.Parent.Name;
      ScrollBox1.Top    := 22;
      ScrollBox1.Left   := 12;
    end;
  //
  SW.Stop;
  //
  Memo1.Lines.Add('-------------');
  Memo1.Lines.Add('Changing Parent of ScrollBox1, Time: ' + SW.Elapsed.Duration.ToString + ', New Parent: ' + ScrollBox1.Parent.Name);
  Memo1.Lines.Add('-------------');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Label2.Caption := 'ScrollBox1 Parent = ' + ScrollBox1.Parent.Name;
end;

initialization

ReportMemoryLeaksOnShutdown := true;
randomize;
//
SW := TStopWatch.Create;

end.

 

bds_RSD8zx1Is5.gif

Edited by programmerdelphi2k

Share this post


Link to post

You didn't read carefully, or I wrote it my way. Unintelligibly. So again.
I'm making a chart (spider) for the teams in the KO system (football). There can be a maximum of 128 nodes in the first level. The total is 255 nodes. For interest. One node consists of:

  • TCurvyPanel and on it
  1. TAdvEdit
  2. TAdvOfficeCheckBox
  3. TLabel

That's a total of 1020 components. All components are already created. It's just a matter of rendering them. For example, when you change the Tab in TPager.

Case 1.

  • ScrollBox on a form
  1. TAdvSmoothPanel on ScrollBox

All components have the owner TAdvSmoothPanel
Time 12 seconds

 

2nd case

  • ScrollBox on form
  1. TAdvSmoothPanel on ScrollBox
  2. Panels on TAdvSmoothPanel

All components have an owner any of the panels
Time 1 - 1.5 seconds

What interests me is why the first case is so incredibly slow. And the second one is basically instantaneous.

Placing components on a panel generally speeds up rendering! That's why I was able to find out by accident.
Unfortunately, your demonstration makes me think of two things.

Share this post


Link to post

well, if the ScrollBox render the Panel, then, it dont need render the objects in Panel. all job is done by Panel.... and the panel dont needs create "scrollbars" for example, resize, etc...

Share this post


Link to post

I don't buy that argument. The rendering speed of a single node depends only on its owner. It does not affect it:
the number of nodes
whether it is on a ScrollBox or on a SmoothPanel
they are rendered quickly on the form itself. But not that fast.
I am attaching the files here. Maybe this will suggest more. You don't need to notice those panels on the left. You can throw them away.

For comparison, just change the Parent.

I also welcome comments for improvement. But nothing complicated. Just such simple things:classic_smile:

Do internetu.rar

Share this post


Link to post

Change TjstAdvPanel to TAdvPanel or TPanel

Share this post


Link to post

Replace them with classic components if you feel like it. 
Open dfm as text. Replace all TjstAdvPanel with TPanel and the others needed. TAdvOfficeCheckBox....
You can also draw it with ScrollBox.
Then open the form. You'll need to confirm everything. That's the fastest way I know.

I'll take a look here tomorrow.

Share this post


Link to post

Are these all windowed controls? Seems like something like this might be better as a single custom control. I'd expect that to have much better performance. 

Share this post


Link to post

so much actions, I pass it!

you dont need buy nothing, just review your code: exists many similar objs, maybe needs a "Design Pattern" here not?

 

changes: Panel now is the "Parent" of my 1000 objects, and the Panel will be accomodate in ScrollBox1  ...

  • Lines: 1001, Time: 00:00:01.3179827  // of course, needs remove lines not necessary like "LText...  re-position of object,  etc..."
  • Changing Parent of Panel1, Time: 00:00:01.6891914, New Parent: ScrollBox1  ->> as said, ScrollBox needs more actions than Panel!
  • Changing Parent of Panel1, Time: 00:00:01.4804362, New Parent: Form1
  • Changing Parent of Panel1, Time: 00:00:01.7900458, New Parent: ScrollBox1

-------------
 

Edited by programmerdelphi2k

Share this post


Link to post

new time to create 1000 object into Panel1:  

  • Creating object: Lines: 1001, Time: 00:00:00.0439193
  • -------------
  • Changing Controls of Panel1 to Show, Time: 00:00:01.4996190, New Parent: Form1
  • -------------
  • Hiding controls, Time: 00:00:00.5445169, New Parent: Form1
  • -------------
  • Changing Parent of Panel1, Time: 00:00:00.0936809, New Parent: ScrollBox1
  • -------------
  • Showing controls, Time: 00:00:01.4349263, New Parent: ScrollBox1
  • -------------
  • Hiding controls, Time: 00:00:00.5135471, New Parent: ScrollBox1
  • -------------
  • Changing Parent of Panel1, Time: 00:00:00.0948245, New Parent: Form1
  • -------------
  • Showing controls, Time: 00:00:01.4588028, New Parent: Form1
     
Edited by programmerdelphi2k

Share this post


Link to post
31 minutes ago, David Heffernan said:

Are these all windowed controls? Seems like something like this might be better as a single custom control. I'd expect that to have much better performance. 

Yes. But I don't understand the second part of the answer. I don't need to address it because 1.5 seconds is about nothing.

Share this post


Link to post

many USES was commented,, now I need know "  OddCorr        = CPnlHeight - Trunc(CPnlSpaceVer / Idx2);  ---> IDx2 and IDx6   what value use?

Share this post


Link to post
16 minutes ago, programmerdelphi2k said:

new time to create 1000 object into Panel1:  

  • Creating object: Lines: 1001, Time: 00:00:00.0439193
  • -------------
  • Changing Controls of Panel1 to Show, Time: 00:00:01.4996190, New Parent: Form1
  • -------------
  • Hiding controls, Time: 00:00:00.5445169, New Parent: Form1
  • -------------
  • Changing Parent of Panel1, Time: 00:00:00.0936809, New Parent: ScrollBox1
  • -------------
  • Showing controls, Time: 00:00:01.4349263, New Parent: ScrollBox1
  • -------------
  • Hiding controls, Time: 00:00:00.5135471, New Parent: ScrollBox1
  • -------------
  • Changing Parent of Panel1, Time: 00:00:00.0948245, New Parent: Form1
  • -------------
  • Showing controls, Time: 00:00:01.4588028, New Parent: Form1
     

I'm not talking about creating components. Those are already created before the actual display/rendering.
I'm only talking about rendering.
Put your components on the ScrollBox and then on the panels. You'll see the difference.

Share this post


Link to post
1 minute ago, programmerdelphi2k said:

many USES was commented,, now I need know "  OddCorr        = CPnlHeight - Trunc(CPnlSpaceVer / Idx2);  ---> IDx2 and IDx6   what value use?

Idx2 = const 2, etc.

Share this post


Link to post
12 minutes ago, Stano said:

Put your components on the ScrollBox and then on the panels. You'll see the difference.

I did, the time is minimum! the time is above

 

11 minutes ago, Stano said:

Idx2 = const 2, etc.

I did, but your Form dont do nothing... just have some panels and nothing of code...  "MatchesByRound" is not called  ???

  • picture deleted (not really necessary so)

 

Edited by programmerdelphi2k

Share this post


Link to post

The form doesn't do anything.
You just have to create the components and place them as needed.
If I have any unnecessary functions left in there, ignore them.

 

I did, the time is minimum!

For me the difference is >10 sec.

Share this post


Link to post

well, then the problem really is with you no?  

  • here  is  < 1.5s -> TO SHOW 1000 object, of course!
Edited by programmerdelphi2k

Share this post


Link to post

I'll try it tomorrow. If I have a long time, I'll make a sample application.

I've tried all sorts of things. Always with the same result.

Share this post


Link to post

I copied the files to the pitch.
I only made the necessary editing.
No matter what I do, I get almost no responses.
Could the fact that it's a subform in the project have something to do with this? On the pitch the main form.

Share this post


Link to post

I finally found the cause. It's TCurvyPanel. If I replace it with another panel, it's lightning fast.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×