Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Richedit schnell viele farbige Zeilen einfügen zu langsam (https://www.delphipraxis.net/129214-richedit-schnell-viele-farbige-zeilen-einfuegen-zu-langsam.html)

NICK447 14. Feb 2009 20:09


Richedit schnell viele farbige Zeilen einfügen zu langsam
 
Hallo Forum ich verwende eine D7 eine Richedit Komponente und eine Listbox. Die Listbox hat ca 200.000 Zeilen die ich in einen Report in die Richedit komponente eintragen will. Die Listbox Daten sind eingefärbt um TX und RX Strings unterscheiden zu können. (Die Farbe wird in Listbox.Items.Objects gespeichert) Geht soweit alles wird aber ab 100.000 Zeilen sehr langsam. Ich glaube ich arbeite sehr umständlich um die Zeilen in die Richedit reinzubekommen. Hat jemand eine Idee wie man schnell viele VERSCHIEDEN gefärbte Textzeilen in eine Richedit Kompo. eintragen kann.

Danke fürs darüber schauen

Nick

Delphi-Quellcode:
 
procedure TFmain.TntButton_generate_ReportClick(Sender: TObject);
Var i,j,k,o : Integer;
    st1 : String;
begin
  o := 0; k := 0;
  j := ListBox_HEX.Items.Count - 1;
  RichEdit1.Lines.BeginUpdate;
  for i:= 0 to j do Begin
    with RichEdit1 do Begin
      st1 := ListBox_HEX.Items[i];
      SelStart := GetTextLen;
      SelAttributes.Color := TColor(ListBox_HEX.Items.Objects[i]);
      SelText := st1 + #13#10;
    end;
  end;
  RichEdit1.Lines.EndUpdate;
end;

sx2008 15. Feb 2009 00:25

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
Das Problem liegt wahrscheinlich an dem Aufruf von GetTextLen.
Diese Funktion zählt immer wieder von Vorne durch und braucht dadurch immer länger.
Das führt dann zu einem quadratischen Anwachsen der benötigten Zeit.
Delphi-Quellcode:
procedure TFmain.TntButton_generate_ReportClick(Sender: TObject);
Var i  : Integer;
    st1 : String;
  ins_pos : integer;
  list : TStrings;
begin
  RichEdit1.Lines.BeginUpdate;
  // Zwischenvariable - spart Zeit und bringt Klarheit in den Code
  list := ListBox_HEX.Items;

  ins_pos := RichEdit1.GetTextLen; // am Anfang einmal die Einfügeposition ermitteln
  for i:= 0 to list.Count - 1 do Begin
    with RichEdit1 do Begin
      st1 := list.Items[i];
      SelStart := ins_pos;
      SelAttributes.Color := TColor(list.Objects[i]);
      SelText := st1 + #13#10;
     
      {
      Einfügeposition weiterzählen.
      Hier bin ich mir nicht sicher, ob man den Zeilenumbruch als 2 Zeichen
      zählen muss oder nicht.
      Bitte selbst herausfinden.
      }
      Inc(ins_pos, Length(st1) + 2);
    end;
  end;
  RichEdit1.Lines.EndUpdate;
end;

NICK447 15. Feb 2009 08:34

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
moin moin SX2008,
ich habe heute morgen mal Tests mit jeweils 50.000 Zeilen gemacht.

Routine 1: 256 344 ticks ==> erst mal Strings reinkopieren dann Zeilen färben
Routine 2: 33.797 ticks ==> Rückwärts zählen letzte Zeile zuerst einfügen die EinfügePos bleibt immer auf 0
Routine 3: 56.078 ticks ==> Dein Vorschlag ohne lokale Tstrings

tja alles zu langsam z.B. Das erzeugen der Stringlist mit 50.0000 dauert nur ca. 2-3 sec.

Im Moment ist das noch keine Lösung

Grüsse Nick
Delphi-Quellcode:
procedure TFmain.TntButton_generate_ReportClick(Sender: TObject);
Var i,j,k,o : Integer;
    st1 : String;
    tick1,tick2 : Dword;
begin
  tick1 := GetTickCount;
  j := ListBox_HEX.Items.Count - 1;
  RichEdit1.Lines.BeginUpdate;
  RichEdit1.Lines := ListBox_HEX.Items;
  for i:= 0 to j do Begin
    with RichEdit1 do Begin
      SelStart := SendMessage(Handle, EM_LINEINDEX, i, 0);
      SelLength := Length(Lines[i]);
      SelAttributes.Color := TColor(ListBox_HEX.Items.Objects[i]);
    end;
  end;
  RichEdit1.Lines.EndUpdate;
  tick2 := GetTickCount;
  tick2 := tick2 - tick1;
  Fmain.Memo_Status.Lines.Add('Tick : ' + inttostr(Tick2));
end;

// Routine 2
procedure TFmain.TntButton_generate_ReportClick(Sender: TObject);
Var i,j,k,o : Integer;
    st1 : String;
    tick1,tick2 : Dword;
begin
  tick1 := GetTickCount;
  j := ListBox_HEX.Items.Count - 1;
  RichEdit1.Lines.BeginUpdate;
  for i:= j downto 0 do Begin
    with RichEdit1 do Begin
      st1 := ListBox_HEX.Items[i];
      SelStart := 0;
      SelAttributes.Color := TColor(ListBox_HEX.Items.Objects[i]);
      SelText := st1 + #13#10;
    end;
  end;
  RichEdit1.Lines.EndUpdate;
  tick2 := GetTickCount;
  tick2 := tick2 - tick1;
  Fmain.Memo_Status.Lines.Add('Tick : ' + inttostr(Tick2));
end;

// Routine 3 

procedure TFmain.TntButton_generate_ReportClick(Sender: TObject);
Var i,j,k,o,ins_Pos : Integer;
    st1 : String;
    tick1,tick2 : Dword;
begin
  tick1 := GetTickCount;
  j := ListBox_HEX.Items.Count - 1;
  RichEdit1.Lines.BeginUpdate;
  for i:= 0 to j do Begin
    with RichEdit1 do Begin
      st1 := ListBox_HEX.Items[i];
      SelStart := ins_Pos;
      SelAttributes.Color := TColor(ListBox_HEX.Items.Objects[i]);
      SelText := st1 + #13#10;
      inc(ins_Pos,length(st1) + 2);
    end;
  end;
  RichEdit1.Lines.EndUpdate;
  tick2 := GetTickCount;
  tick2 := tick2 - tick1;
  Fmain.Memo_Status.Lines.Add('Tick : ' + inttostr(Tick2));
end;

himitsu 15. Feb 2009 10:07

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
Wenn du z.B. in einer StringList erstmal alles selber im RTF-Format erzeugst und das dann auf einmal an das Richedit übergibst?

NICK447 15. Feb 2009 16:19

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
ja darüber habe ich auch schon nachgedacht !! Das gespeicherte RTF in einen standard Editor geladen man sieht schön die "Tags" für Farbe.

{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl {\f0\fnil\fcharset0 Courier New;}}
{\colortbl ;\red255\green0\blue0;\red0\green0\blue255;}
\viewkind4\uc1\pard\b\f0\fs16 Report
\par \cf1 00166: 12 02 31 0a 00 00 00 00
\par \cf2 00176: f1 03 71 0a 01 00 00 00
\par \cf1 00189: 12 03 22 25 06 00 00 00
\par \cf2 00196: f1 05 62 25 06 00 fe 00 usw. usw.

Die \cf1 \cf2 sind die Farben denke ich. Habe ich dann einfach voran gestellt und die Stringliste zeilenwesie kopiert.
st1 := '\par \cf2 ' + st1 + #$0d + #$0a;

aber das Resultat ist ... na ja ... beeindruckend.

\\par \\cf1 00155: 12 02 31 0a 00 00 00 00 \\par \\cf2 00161: f1 03 71 0a 01 00 00 00 \\par \\cf1 00174: 12 03 22 25 06 00 00 00
Das Richedit control erkennt die '\' und ersetzt durch doppelte .. richtig schlau..

ne ich weis da im Moment nicht weiter ....

Grüsse Nick

mjustin 15. Feb 2009 16:47

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
Zitat:

Zitat von NICK447
Das Richedit control erkennt die '\' und ersetzt durch doppelte

Quick & Dirty Lösung: die zusammengebauten Daten erst als Datei speichern und dann einlesen. Das wird wahrscheinlich schon ein vielfaches schneller sein.

Es gibt aber sicher noch eine Möglichkeit, den String im Speicher zusammenzubauen und dann dem RichEdit zuzuweisen (als StringStream oder MemoryStream), denn auslesen geht ja auch ...

himitsu 15. Feb 2009 17:00

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
LoadFromStream sollte dann wohl besser sein.

NICK447 15. Feb 2009 17:53

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
ja hört sich gut an Stream basteln rein mit den Daten und wieder raus in die Richedit...

und schon probiert ...

Zeilen zusammensetzten mit Formatierung versehen in einen TStringStream schreiben. Wenn fertig komplett vom Stream in RichEdit laden. Ich mache da irgendetwas falsch die Formatierung wird so nicht genommen es werden wieder die '\ durch doppelt '\\ ersetzt. (Der Code ist nur mal quick & dirty zusammengenagelt)

das Ergebniss ist alles in schwarz und meine \par \cf1 wieder mit doppelten '\\' und damit keine Formatierung im RTF

da fehlt mir das Wissen wie das in den RTF gespeichert wird und wie die Komponente arbeitet.

Danke für Eure Ideen.

Gruss Nick



Delphi-Quellcode:
procedure TFmain.TntButton_generate_ReportClick(Sender: TObject);
Var i,j : Integer;
    st1,st2  : String;
    StrS : TStringStream;
    col : Tcolor;
begin
  StrS := TStringStream.Create('');
  j := ListBox_HEX.Items.Count - 1;
//  st1 := '{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Courier New;';
//  StrS.WriteString(st1);
//  st1 := '{\colortbl ;\red255\green0\blue0;\red0\green0\blue255;';
//  StrS.WriteString(st1);
  st1 := '\viewkind4\uc1\pard\b\f0\fs16 Report';
  StrS.WriteString(st1);
  try
    for i:= 0 to j do Begin
      st1 := ListBox_HEX.Items[i];
      col := TColor(ListBox_HEX.Items.Objects[i]);
      case col of
        clRED : st2 := '\par \cf1 ';
        clBLUE : st2 := '\par \cf2 ';
      end;
      StrS.WriteString(st2);
      StrS.WriteString(st1);
    end;
    StrS.Position := 0;
    RichEdit1.Lines.LoadFromStream(StrS);
  finally
    StrS.Free;
  end;
end;

Namenloser 15. Feb 2009 18:16

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
Zitat:

Zitat von himitsu
LoadFromStream sollte dann wohl besser sein.

Kann man, muss man aber gar nicht. Über eine Zuweisung an die Eigenschaft Text wird er RTF-Code auch angenommen.

toms 17. Feb 2009 13:06

Re: Richedit schnell viele farbige Zeilen einfügen zu langsa
 
Auf delphiforfun gibt es ein Beispiel für ein schnelles Highlighten von Wörtern.

Zitat:

Applying syntax formatting to a sizable Richedit file is quite slow. The technique used here is to intercept the WindowProc procedure used by TRichedit and let it paint the window which we then scan for words to by highlighted and rewrite them in the specified color.[...]


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:05 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz