Announcement

Collapse
No announcement yet.

TListView - Geschwindigkeit zu langsam

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • TListView - Geschwindigkeit zu langsam

    Hallo!

    Ich arbeite mit ListView und lese in das Ding ca. 5000 Zeilen ein. Wenn das Objekt leer ist, dauert es 4-5 sec. Wenn das Objekt gefüllt ist, dauert es dopelt so lange. In ein StringGrid werden die Daten unter 1 sec eingelesen. Weiss jemand, wie das Problem mit ListView gelöst werden kann?

    PS: Die Methoden "BeginUpdate" und "EndUpdate" setze ich ein.

  • #2
    Dieses Problem kenne ich. Die TListView-Komponente ist nicht gerade
    bekannt dafür schnell zu sein, wenn viele Einträge vorhanden sind.

    Es gibt zwei (mir spontan einfallende) Möglichkeiten:

    1, Unter http://www.turbopower.com ->Orpheus gibt es eine Komponente TVirtualListBox, welche auch mit sehr vielen Einträgen sehr schnell umgehen kann. Man muß jedoch selbst die Einräge verwalten und das Aussehen kann nicht in der Art und weise wie bei TListview geändert werden.

    2, Unter http://www.lischke-online.de/VirtualTreeview.html findest Du eine sehr schnelle TTreeView-Komponente, welche man auch als ListView verwenden kann. Sieht sehr vielversprechend aus

    Comment


    • #3
      Hallo Bernhard,

      Vielen Dank für deine Tips. Die VirtualTreeview-Komponente scheint mir eine "eierlegende Wollmilchsau" zu sein. Ich werde mich mit dieser Komponente befassen

      Comment


      • #4
        <p>Hallo,<br>
        <br>
        in Delphi ist ein Beispiel einer "virtuellen Listview" im Verzeichnis "..\Borland\Delphi5\Demos" vorhanden.<br>
        <br>
        Ich selber nutze schon seit langem nur noch virtuelle Listen. Somit ist es möglich über 20.000 Einträge in einer vernünftigen Zeit darzustellen.<br>
        <br>
        Gruß Thomas</p&gt

        Comment


        • #5
          Hallo Thomas,
          kannst du mir bitte sagen, in welcher Procedure in Borlands Virtual ListView das schnelle Füllen der ListView enthalten ist? Mein Rechner (Athlon 700) tut sich sehr schwer, 4000 Einträge aus einer Stringlist in eine ListView zu kopieren - interessanterweise geht es mit dem Füllen schneller, wenn es nicht als secondary Thread, sondern im Main Thread passiert; wahrscheinlich weil fürs Synchronisieren Rechenleistung drauf geht.
          Gerhar

          Comment


          • #6
            Mir würden für Listviews mit sehr vielen Einträgen 2 Möglichkeiten einfallen:

            1, Unter http:/TurboPower.com -> Orpheus gibt es eine VirtualListBox mit sehr hoher Geschwindigkeit

            2, Unter http://www.lischke-online.de gibt es eine sehr interessante Komponente, welche sowohl als TreeView als auch ListView arbeiten kan

            Comment


            • #7
              <p>Hallo Gerhard,<br>
              <br>
              ich benutze eine TList, die mit der ListView korrespondiert. In der OnData-Methode der Listview (Ownerdata=True), werden dann nur die benötigten Datensätze am Bildschirm angezeigt.

              Auf meinem Rechner K6-400 dauert eine TList mit 2000 Einträgen zu füllen und dann darzustellen nicht einmal 1 Sekunde.

              Gruß Thoma

              Comment


              • #8
                Hallo Thomas,

                kannst du mir mit ein paar Zeilen Code auf die Sprünge helfen? Ich zeige dir mal meinen Code:
                <pre>
                procedure TSearchThread.FillLV;
                {...}
                begin
                if FoundList.Count > 0 then
                begin
                Form1.ListView1.Items.BeginUpdate;
                Form1.ListView1.Items.Count:=FoundList.Count;
                for i:=0 to FoundList.Count -1 do
                begin
                ListItem:=Form1.ListView1.Items.Add;
                ListItem.Caption:=FoundList.Strings[i];
                end;
                Form1.ListView1.Items.EndUpdate;
                end;
                end;
                </pre>
                Das Ganze wird als Synchronize(FillLV)in einem Thread aufgerufen. Damit brauche ich mehrere Minuten für 5000 Einträge (getestet auf 3 PCs).
                Danke im voraus
                <p>Gerhar

                Comment


                • #9
                  <p>
                  Hallo Thomas,<br><br>
                  bezüglich dieses Themas hätte ich auch eine Frage und zwar verwende ich auch eine TList und gebe sie in einer Listview aus. Allerdings habe ich eine Prozedur updateLV, welche ich z.B. im onShow Ereignis meines Formulars aufrufe. In dieser Prozedur sage ich dann li:= listItem.add usw. <br><br>Was ist nun der Unterschied, wenn ich die OnData-Methode benutze (um meine Einträge auszugeben)? Ist es nicht unwichtig, von welchem Ereignis ich aus meine ListView fülle(onShow/onData)?<br><br>
                  Gruß Alex</p&gt

                  Comment


                  • #10
                    Hallo Gerhard,

                    ich kann Dein Problem leider nicht nachvollziehen. An Deinem Bsp habe ich nur die Zeile <b>Form1.ListView1.Items.Count:=FoundList.Count; </b> weggelassen (dürfte er eigentlich gar nicht kompilieren:-) - Und das ganze dauert weniger als 3 sec (PII 400).
                    Hier mein Test:<br>
                    <br>
                    procedure Testt.FillV;<br>
                    var<br>
                    ListItem: TListItem;<br>
                    I: Integer;<br>
                    List: TStringList;<br>
                    begin<br>
                    List := TStringList.Create;<br>
                    for i:=0 to 4999 do<br>
                    List.Add('Neuer Eintrag');<br>
                    Form1.ListView1.Items.BeginUpdate;<br>
                    {Form1.ListView1.Items.Count:=5000;}<br>
                    for i:=0 to List.Count - 1 do<br>
                    begin<br>
                    ListItem:=Form1.ListView1.Items.Add;<br>
                    ListItem.Caption:=List.Strings[i];<br>
                    end;<br>
                    Form1.ListView1.Items.EndUpdate;<br>
                    List.Free;<br>
                    end;<br>
                    <br>
                    Gruß Fal
                    Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

                    Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

                    Comment


                    • #11
                      Hallo Gerhard, Hallo Alex, Hallo Leute!

                      Ich habe da ein kleines Beispiel:

                      type
                      TForm1 = class(TForm)
                      ListView1: TListView;
                      procedure FormCreate(Sender: TObject);
                      procedure FormDestroy(Sender: TObject);
                      procedure ListView1Data(Sender: TObject; Item: TListItem);
                      private
                      Spalten:array [0..2] of TStringList;{um Daten der 3 Spalten zu speichern}
                      end;
                      var
                      Form1: TForm1;
                      implementation
                      {$R *.DFM}
                      {ListView1: ViewStyle=vsReport;OwnerData=True; Anzahl der Spalten ist 3}
                      procedure TForm1.FormCreate(Sender: TObject);
                      const max:Integer=5000;
                      var
                      i,j:Integer;
                      begin
                      for i:=0 to High(Spalten) do begin
                      Spalten[i]:=TStringList.Create;{Spalte erzeugen}
                      for j:=0 to max do
                      Spalten[i].Add('Spalte'+intToStr(i)+'_Zeile'+intToStr(j));{S palte mit Werten füllen}
                      end;
                      ListView1.Items.Count:=max+1;{Platz in Listview schaffen}
                      end;
                      procedure TForm1.FormDestroy(Sender: TObject);
                      var
                      i,j:Integer;
                      begin
                      for i:=0 to High(Spalten) do
                      Spalten[i].Free;{Spalte zerstören}
                      end;
                      procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
                      var
                      i:Integer;
                      begin
                      Item.Caption:=Spalten[0][Item.Index];{mit 0 wird auf die erste Spalte zugegriffen}
                      for i:=1 to High(Spalten) do
                      Item.SubItems.Add(Spalten[i][Item.Index]);
                      end;

                      end

                      Comment


                      • #12
                        Hallo Gerhard, Hallo Alex, Hallo Leute!

                        Ich habe da ein kleines Beispiel:

                        type
                        TForm1 = class(TForm)
                        ListView1: TListView;
                        procedure FormCreate(Sender: TObject);
                        procedure FormDestroy(Sender: TObject);
                        procedure ListView1Data(Sender: TObject; Item: TListItem);
                        private
                        Spalten:array [0..2] of TStringList;{um Daten der 3 Spalten zu speichern}
                        end;
                        var
                        Form1: TForm1;
                        implementation
                        {$R *.DFM}
                        {ListView1: ViewStyle=vsReport;OwnerData=True; Anzahl der Spalten ist 3}
                        procedure TForm1.FormCreate(Sender: TObject);
                        const max:Integer=5000;
                        var
                        i,j:Integer;
                        begin
                        for i:=0 to High(Spalten) do begin
                        Spalten[i]:=TStringList.Create;{Spalte erzeugen}
                        for j:=0 to max do
                        Spalten[i].Add('Spalte'+intToStr(i)+'_Zeile'+intToStr(j));{S palte mit Werten füllen}
                        end;
                        ListView1.Items.Count:=max+1;{Platz in Listview schaffen}
                        end;
                        procedure TForm1.FormDestroy(Sender: TObject);
                        var
                        i,j:Integer;
                        begin
                        for i:=0 to High(Spalten) do
                        Spalten[i].Free;{Spalte zerstören}
                        end;
                        procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
                        var
                        i:Integer;
                        begin
                        Item.Caption:=Spalten[0][Item.Index];{mit 0 wird auf die erste Spalte zugegriffen}
                        for i:=1 to High(Spalten) do
                        Item.SubItems.Add(Spalten[i][Item.Index]);
                        end;

                        end

                        Comment


                        • #13
                          Hallo Gerhard, Hallo Alex, Hallo Leute!

                          Ich habe da ein kleines Beispiel:

                          <bre>
                          type
                          TForm1 = class(TForm)
                          ListView1: TListView;
                          procedure FormCreate(Sender: TObject);
                          procedure FormDestroy(Sender: TObject);
                          procedure ListView1Data(Sender: TObject; Item: TListItem);
                          private
                          Spalten:array [0..2] of TStringList;{um Daten der 3 Spalten zu speichern}
                          end;
                          var
                          Form1: TForm1;
                          implementation
                          {$R *.DFM}
                          {ListView1: ViewStyle=vsReport;OwnerData=True; Anzahl der Spalten ist 3}
                          procedure TForm1.FormCreate(Sender: TObject);
                          const max:Integer=5000;
                          var
                          i,j:Integer;
                          begin
                          for i:=0 to High(Spalten) do begin
                          Spalten[i]:=TStringList.Create;{Spalte erzeugen}
                          for j:=0 to max do
                          Spalten[i].Add('Spalte'+intToStr(i)+'_Zeile'+intToStr(j));{S palte mit Werten füllen}
                          end;
                          ListView1.Items.Count:=max+1;{Platz in Listview schaffen}
                          end;
                          procedure TForm1.FormDestroy(Sender: TObject);
                          var
                          i,j:Integer;
                          begin
                          for i:=0 to High(Spalten) do
                          Spalten[i].Free;{Spalte zerstören}
                          end;
                          procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
                          var
                          i:Integer;
                          begin
                          Item.Caption:=Spalten[0][Item.Index];{mit 0 wird auf die erste Spalte zugegriffen}
                          for i:=1 to High(Spalten) do
                          Item.SubItems.Add(Spalten[i][Item.Index]);
                          end;

                          end.

                          </bre&gt

                          Comment


                          • #14
                            Hallo Gerhard, Hallo Alex, Hallo Leute!

                            Ich habe da ein kleines Beispiel:

                            <pre>

                            type
                            TForm1 = class(TForm)
                            ListView1: TListView;
                            procedure FormCreate(Sender: TObject);
                            procedure FormDestroy(Sender: TObject);
                            procedure ListView1Data(Sender: TObject; Item: TListItem);
                            private
                            Spalten:array [0..2] of TStringList;{um Daten der 3 Spalten zu speichern}
                            end;
                            var
                            Form1: TForm1;
                            implementation
                            {$R *.DFM}
                            {ListView1: ViewStyle=vsReport;OwnerData=True; Anzahl der Spalten ist 3}
                            procedure TForm1.FormCreate(Sender: TObject);
                            const max:Integer=5000;
                            var
                            i,j:Integer;
                            begin
                            for i:=0 to High(Spalten) do begin
                            Spalten[i]:=TStringList.Create;{Spalte erzeugen}
                            for j:=0 to max do
                            Spalten[i].Add('Spalte'+intToStr(i)+'_Zeile'+intToStr(j));{S palte mit Werten füllen}
                            end;
                            ListView1.Items.Count:=max+1;{Platz in Listview schaffen}
                            end;
                            procedure TForm1.FormDestroy(Sender: TObject);
                            var
                            i,j:Integer;
                            begin
                            for i:=0 to High(Spalten) do
                            Spalten[i].Free;{Spalte zerstören}
                            end;
                            procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
                            var
                            i:Integer;
                            begin
                            Item.Caption:=Spalten[0][Item.Index];{mit 0 wird auf die erste Spalte zugegriffen}
                            for i:=1 to High(Spalten) do
                            Item.SubItems.Add(Spalten[i][Item.Index]);
                            end;

                            end.

                            </pre&gt

                            Comment


                            • #15
                              <p>Hallo Eduard,<br>
                              <br>
                              folgendes Beispiel benötigt auf meinem Rechner in der Firma (Pentium 600), 20 Millisekunden.<br>
                              Auf den 1. Blick scheint der Aufwand relativ groß zu sein. Dieser relativiert sich, wenn man den Geschwindigkeitsvorteil sieht.<br>
                              <br>
                              Auf der Form im Beispiel befindet sich eine Listview mit 4 Spalten. Folgende Eigenschaften müssen gesetzt werden:<br>
                              OwnerData:=True; ViewSyle:=vsReport;<br>
                              <pre>
                              unit ListViewTest;

                              interface

                              uses
                              Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
                              ComCtrls;

                              type
                              PMyRec=^TMyRec;
                              TMyRec=record
                              Text1,
                              Text2 :String;
                              Zahl1,
                              Zahl2 :Integer;
                              end; // TMyRec

                              TMyRecList=class(TList)
                              private
                              function GetDaten(aIndex:Integer):PMyRec;
                              procedure SetDaten(aIndex:Integer; aRec:PMyRec);
                              public
                              procedure AddRec(const aRec:TMyRec);
                              procedure Clear; override;
                              property Daten[aIndex:Integer]:PMyRec read GetDaten write SetDaten;
                              end; // TMyRecList

                              TForm1 = class(TForm)
                              ListView1: TListView;
                              procedure FormCreate(Sender: TObject);
                              procedure FormDestroy(Sender: TObject);
                              procedure ListView1Data(Sender: TObject; Item: TListItem);
                              private
                              { Private-Deklarationen }
                              fMyRecList:TMyRecList;
                              public
                              { Public-Deklarationen }
                              end;

                              var
                              Form1: TForm1;

                              implementation

                              {$R *.DFM}

                              // ----- TMyRecList
                              procedure TMyRecList.AddRec(const aRec:TMyRec);
                              var r:PMyRec;
                              begin
                              r:=AllocMem(SizeOf(TMyRec));
                              r^:=aRec;
                              Add(r);
                              end; // TMyRecList.AddRec

                              procedure TMyRecList.Clear;
                              var r:PMyRec;
                              i:Integer;
                              begin
                              for i:=0 to Count-1 do
                              begin
                              r:=Daten[i];
                              if (r<>nil) then FreeMem(r, SizeOf(TMyRec));
                              end; // for i
                              inherited Clear;
                              end; // TMyRecList.Clear

                              function TMyRecList.GetDaten(aIndex:Integer):PMyRec;
                              begin
                              if ((aIndex>=0) and (aIndex<Count)) then Result:=PMyRec(Items[aIndex])
                              else Result:=nil;
                              end; // TMyRecList.GetDaten

                              procedure TMyRecList.SetDaten(aIndex:Integer; aRec:PMyRec);
                              begin
                              if ((aIndex>=0) and (aIndex<Count)) then PMyRec(Items[aIndex])^:=aRec^;
                              end; // TMyRecList.SetDaten

                              // ----- TForm1
                              procedure TForm1.FormCreate(Sender: TObject);
                              var i:Integer;
                              r:TMyRec;
                              begin
                              fMyRecList:=TMyRecList.Create;
                              for i:=1 to 2000 do
                              begin
                              with r do
                              begin
                              Text1:=Format('Text %d, Spalte 1', [i]);
                              Text2:=Format('Text %d, Spalte 2', [i]);
                              Zahl1:=i;
                              Zahl2:=i+1;
                              end; // with
                              fMyRecList.AddRec(r);
                              end; // for i

                              // der Listview mitteilen, wieviele Einträge existieren
                              ListView1.Items.Count:=fMyRecList.Count;
                              ListView1.Repaint;
                              end;

                              procedure TForm1.FormDestroy(Sender: TObject);
                              begin
                              fMyRecList.Free;
                              end;

                              procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
                              var r:PMyRec;
                              begin
                              if (Item=nil) then Exit;
                              r:=fMyRecList.Daten[Item.Index];
                              if (r<>nil) then with Item do
                              begin
                              Caption:=r^.Text1;
                              SubItems.Add(r^.Text2);
                              SubItems.Add(IntToStr(r^.Zahl1));
                              SubItems.Add(IntToStr(r^.Zahl2));
                              end; // if
                              end;

                              end.
                              </pre>
                              Ich hoffe, Du kannst mit dem Beispiel etwas anfangen.<br>
                              Gruß Thomas</p&gt

                              Comment

                              Working...
                              X