Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Komponenten schnell dynamisch erzeugen


Flamefire - Di 18.12.12 22:18
Titel: Komponenten schnell dynamisch erzeugen
Ich erstelle in einer Schleife mehrere Panels und Labels af ein Form. Nur leider dauert das doch ca 3s für 200 Elemente auf meinem PC. Die Anwendung wird auf einem deutlich langsameren PC laufen.
Wie kann man das also beschleunigen?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
  for i := 0 to Codes.Count - 1 do begin
    tmpPnl := TPanel.Create(nil);
    tmpPnl.Parent := Self;
    tmpPnl.AutoSize := true;
    tmpPnl.BorderStyle := bsSingle;
    tmpPnl.ShowCaption := false;
    tmpLbl := TLabel.Create(tmpPnl);
    tmpLbl.Parent := tmpPnl;
    tmpLbl.Caption := Codes[i].Code;
    tmpLbl.Hint:='HINT!';
    tmpLbl.ShowHint:=true;
    if (cx + tmpPnl.Width > Width-25then begin
      cx := 0;
      Inc(cy, tmpPnl.Height + 2);
    end;
    tmpPnl.Top := cy;
    tmpPnl.Left := cx;
    Inc(cx, tmpPnl.Width + 3);
  end;


bummi - Di 18.12.12 22:37


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
procedure TForm6.Button1Click(Sender: TObject);
var
 i,cx,cy:Integer;
 tmpPnl:TPanel;
 tmpLbl:TLabel;
 tc:Cardinal;
begin
  cx := 0;
  cy := 0;
  tc := GetTickCount;
  LockWindowUpdate(handle);  // bringt ca 50% Zeitersparnis
  for i := 0 to 500 do begin
    tmpPnl := TPanel.Create(nil);
    //tmpPnl.Parent := Self; später setzen bringt beim testen ca. 40%
    tmpPnl.AutoSize := true;
    tmpPnl.BorderStyle := bsSingle;
    tmpPnl.ShowCaption := false;
    tmpLbl := TLabel.Create(tmpPnl);
    tmpLbl.Parent := tmpPnl;
    tmpLbl.Caption := IntToStr(i);
    tmpLbl.Hint:='HINT!';
    tmpLbl.ShowHint:=true;
    tmpPnl.Parent := Self; // erst hier setzen
    if (cx + tmpPnl.Width > Width-25then begin
      cx := 0;
      Inc(cy, tmpPnl.Height + 2);
    end;
    tmpPnl.Top := cy;
    tmpPnl.Left := cx;

    Inc(cx, tmpPnl.Width + 3);
  end;
  LockWindowUpdate(0); // nicht vergessen

  Showmessage(IntToStr(GetTickCount-tc));
end;


Flamefire - Di 18.12.12 23:43

Danke für den Tipp.
Das spätere Setzen des Parents bringt 40%. Das LockWindow leider gar nichts. Aber 40% sind erst mal echt gut!


bummi - Di 18.12.12 23:58

Hast Du das richtige handle erwischt? Form oder Parent der Panels, ich nehme an das war nur eine Demoauszug.


Nersgatt - Mi 19.12.12 07:10

@Bummi: Kannst Du mir erklären, warum das spätere Setzen des Parents eine Zeitersparnis bringt? Das würde mich interessieren.


bummi - Mi 19.12.12 07:29

Weil (fast) jede Propertyänderung ein "Neuzeichnen" bewirkt, wenn der Parent nicht gesetzt ist entfällt dieses.


Tastaro - Mi 19.12.12 07:47

Eine Möglichkeit wäre auch auf das Formular ein großes Panel und dieses als Parent für die neuen Panels zu verwenden. Dieses kann man dann vor dem Erzeugen der vielen Panels unsichtbar und danach wieder sichtbar machen.

Beste Grüße


jaenicke - Mi 19.12.12 09:06

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Ich erstelle in einer Schleife mehrere Panels und Labels af ein Form. Nur leider dauert das doch ca 3s für 200 Elemente auf meinem PC. Die Anwendung wird auf einem deutlich langsameren PC laufen.
Dann hast du dort aber auch generell mit vielen Komponenten vielleicht ein Performanceproblem. Zumindest, wenn dann noch gescrollt wird z.B.

Bist du wirklich sicher, dass sich das nicht anders lösen lässt? So viele Komponenten sehen für mich erst einmal wie das Problem und nicht wie die Lösung aus. :gruebel:

// EDIT:
Als Beispiel nenne ich wieder einmal mein Periodensystem, dass selbst auf älteren PCs noch performant läuft:
http://www.entwickler-ecke.de/viewtopic.php?t=91534&postorder=asc&start=0


Flamefire - Mi 19.12.12 23:53

Ja habe ich auch schon überlegt ein Canvas oder wenigstens DrawGrid zu nehmen. Aber war mir dann zu aufwändig... Mal sehn ob ich das noch mache ;)