Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Stringgrid Zeilen füllen (https://www.delphipraxis.net/171920-stringgrid-zeilen-fuellen.html)

Ego 1. Dez 2012 20:48

Stringgrid Zeilen füllen
 
Ich will aus einem Array mit ca. 100 Records ein Stringgrid füllen. Rowcount gebe ich mit 2 vor , da Fixedrows := 1
Wenn ich es so mache:
Delphi-Quellcode:
zeile := 0; tabelle.rowcount := 2;
for zaehler := low(xyarray) to high(xyarray) do
begin
  inc(zeile);
  tabelle.cells[1,zeile] := xyarray[zaehler].bezeichnung;
end;
tabelle.rowcount := length(xyarray);
dann wird die Tabelle nur mit genau 53 Einträgen gefüllt.
Erhöhe ich aber rowcount in der Schleife jeweils um 1,
Delphi-Quellcode:
zeile := 0; tabelle.rowcount := 2;
for zaehler := low(xyarray) to high(xyarray) do
begin
  inc(zeile);
  tabelle.rowcount := tabelle.rowcount + 1;
  tabelle.cells[1,zeile] := xyarray[zaehler].bezeichnung;
end;
wird brav das ganze Array eingelesen. Wie kommt es zu diesem Unterschied? Verstehen könnte ich ja, wenn bei der ersten Variante nur eine Zeile beschrieben würde (die erste ist ja fixed!) , oder die ersten 15 (die Abmessung des Stringgrids ist so, daß 15 Zeilen angezeigt werden können).
Warum 53? Was genau bewirkt eigentlich rowcount? Anzahl der angezeigten Zeilen? Oder Anzahl der benutzbaren Zeilen? Gibt es eine Art 'Voreinstellung' für die Zeilenanzahl eines Stringgrids?

Helmi 1. Dez 2012 21:00

AW: Stringgrid Zeilen füllen
 
Hallo,

Delphi-Quellcode:
RowCount
gibt die Anzahl aller Zeilen an, also die fixen Zeilen + die "normalen" Zeilen.

Was ich bei StringGrids vermute ist, dass es schon eine gewisse Anzahl Zeilen (im Hintergrund) gibt. Nur werden eben
durch die Zahl in RowCount nur die Zeilen angezeigt, die eben angezeigt werden sollen. Deswegen kann man auf Zeilen
zugreifen, die eigentlich nicht vorhanden sein sollen (da RowCount - FixRows kleiner als die Anzahl Zeilen).

Bummi 1. Dez 2012 21:03

AW: Stringgrid Zeilen füllen
 
ungetestet...
Delphi-Quellcode:
tabelle.rowcount := length(xyarray); // Zeilenanzahl incl. fixierter Zeile
for zaehler := low(xyarray) to high(xyarray) do
begin
  tabelle.cells[1,zaehler+1] := xyarray[zaehler].bezeichnung;
end;
Wenn Du nichts editieren, sondern nur anzeigen willst wäre ein Drawgrid IMHO die bessere Wahl.

Popov 1. Dez 2012 21:04

AW: Stringgrid Zeilen füllen
 
Sollte beides kein Problem sein. Problem liegt evtl. wo anders.

//Edit:

Ich hab es gerade noch mal getestet, bei mir funktioniert beides in etwa ähnlich

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
type
  Txyarray = record
    bezeichnung: string;
  end;
var
  xyarray: array[1..100] of Txyarray;
  zeile, zaehler: Integer;
begin
  for zaehler := low(xyarray) to high(xyarray) do
    xyarray[zaehler].bezeichnung := IntToStr(zaehler);

{  zeile := 0; tabelle.rowcount := 2;
  for zaehler := low(xyarray) to high(xyarray) do
  begin
    inc(zeile);
    tabelle.cells[1,zeile] := xyarray[zaehler].bezeichnung;
  end;
  tabelle.rowcount := length(xyarray);  }

  zeile := 0; tabelle.rowcount := 2;
  for zaehler := low(xyarray) to high(xyarray) do
  begin
    inc(zeile);
    tabelle.rowcount := tabelle.rowcount + 1;
    tabelle.cells[1,zeile] := xyarray[zaehler].bezeichnung;
  end;
end;

Ego 1. Dez 2012 21:26

AW: Stringgrid Zeilen füllen
 
@Helmi:
Den Verdacht habe ich auch: Stringgrid hat voreingestellt 50 Zeilen (möglicherweise habe ich mich um drei verzählt), wenn man mehr braucht, muß man sie explizit mit rowcount erzeugen.

@Bummi:
Zur Verdeutlichung habe ich etwas gekürzt. In meinem konkreten Fall werden nicht alle Arrayelemente übernommen, sondern nur bestimmte ausgewählt. Deswegen weiß ich vorher nicht, wieviele Zeilen im Stringgrid gebraucht werden. Dein Lösungsvorschlag geht hier also nicht; im Endeffekt kommt es auf das gleiche hinaus: Anscheinend müssen Zeilen oberhalb einer gewissen Anzahl (50?) extra angefordert werden.

@Popov
Bei dir funktionieren beide Varianten gleich? Es werden in beiden Fällen 100 Zeilen in der Tabelle angezeigt?
Vielleicht ist es von der Compilerversion abhängig? Ich habe mit D7 programmiert

Helmi 2. Dez 2012 08:52

AW: Stringgrid Zeilen füllen
 
Wenn man sich die (versteckte) Funktion "DeleteRow" vom StringGrid anschaut, wird beim löschen nur RowCount reduziert, das würde dafür sprechen, dass es eine feste Anzahl vorhandener Zeilen gibt. Bin deswegen schon mal auf die Schnauze gefallen.

In diesem Sinne möcht ich auch mal auf diesen Hack hinweisen: und zwar bei den Schweizern!

Nichts desto trotz find ich es richtiger wenn man explizit sagt wieviele Zeilen dass man braucht, sprich RowCount dementsprechend hochzählt, bzw. von vorn hinein, wenn man es weiss, bereits auf die gewünschte Anzahl setzt (inkl. FixRows)

hoika 2. Dez 2012 10:17

AW: Stringgrid Zeilen füllen
 
Hallo,

ich würde erst mal durch das Array gehen,
um die benötigte Zeilenzahl zu ermitteln und zu setzen.

Und ja, die Zeilenzahl erhöht sich nicht automatisch
und muss explizit gesetzt werden.


Heiko

Bummi 2. Dez 2012 11:13

AW: Stringgrid Zeilen füllen
 
@hoika :thumb:

hoika 2. Dez 2012 11:52

AW: Stringgrid Zeilen füllen
 
Hallo,

was das ganze so gemein macht:
Das Grid entfernt Zeilen nicht direkt, wenn man RowCount verringert.
Sie werden nur nicht angezeigt.
Der alte Inhalt ist noch da.
Vergrößert man RowCount wieder, ist der alte Inhalt
wieder da, ob das gewollt, sie dahingestellt.

Das läuft alles unter den Stichwort "Speicheroptimierung".


Heiko

Popov 2. Dez 2012 12:21

AW: Stringgrid Zeilen füllen
 
Nun, soweit ich weiß sind in beide Richtigen TStringLists oder TStrings. Man kann also füllen bis an die grenze. Das andere ist der sichtbare Bereich.

Ego 2. Dez 2012 19:57

AW: Stringgrid Zeilen füllen
 
@hoika:
Nein, ich halte es nicht für sinnvoll, zweimal das Array zu durchlaufen. Ist nicht gerade optimal. Jedesmal rowcount um einen erhöhen, wenn es gebraucht wird, klappt besser.
Das gemeine an der Sache ist, daß bei mir in den Probläufen mit der ersten Methode alles klappte, als ich immer nur relativ kurze Arrays mit ca. 10 bis 20 Komponenten benutzte(rowcount wird also 'automatisch' erhöht (bzw. ist vorgegeben) bis wohl 50.)
Deswegen nahm ich an, daß es immer gehen würde. Dann, im Ernstfall mit langen Arrays (> 200) klappte es eben nicht mehr, bei ca. 50 Einträgen war Schluß. Ein ganz böse Falle! Sinnvoller wäre es, wenn bei meiner ersten Methode eine - und nur ein - Zeile gefüllt würde. Dann wüßte man gleich Bescheid.

Recht hast du mit deinem zweiten Eintrag. Das ist auch so eine üble Sache beim Stringgrid, auf die ich schon mal reingefallen bin.

@ helmi:
Danke für den Hinweis, sehr interessant!

Helmi 2. Dez 2012 20:00

AW: Stringgrid Zeilen füllen
 
setz halt
Delphi-Quellcode:
RowCount := high(xyarray) + FixRows
Dann braucht das Array nur einmal durchlaufen

hoika 3. Dez 2012 05:03

AW: Stringgrid Zeilen füllen
 
Hallo,

auch ein guter Ansatz von helmi,
da hier ja die maximale Anzahl bekannt ist.
Dann noch mit BeginUpdate/EndUpdate arbeiten,
und der User bekommt vom Füllen nix mit.

Heiko

Ego 3. Dez 2012 07:10

AW: Stringgrid Zeilen füllen
 
Zitat:

Zitat von Helmi (Beitrag 1194038)
setz halt
Delphi-Quellcode:
RowCount := high(xyarray) + FixRows
Dann braucht das Array nur einmal durchlaufen

Nein, das ist Platzverschwendung; z.B. Array > 200 und nur 15 Einträge werden gebraucht, da mache ich doch kein riesengroßes Stringgrid!

Das, was ich als zweite Methode angegeben habe, ist schon optimal. Mein Problem ist ja nicht: 'Wie mache ich das?' sondern: 'Wieso verhält sich Stringgrid so tückisch, daß Methode 1 teilweise (aber eben nur teilweise!) funktioniert?'

Helmi 3. Dez 2012 07:40

AW: Stringgrid Zeilen füllen
 
Dann zähl halt die notwendigen Zeilen mit

(Pseudocode weil mir grad mein Delphi fehlt)

Delphi-Quellcode:
RowCount := high(xyarray) + FixRows;

j := 0;
for i := low(xyarray) to high(xyarray) do
  begin
    If xyarray[i] = 'text' then
      begin
        inc(j);
        MitIrgendEinerProcedureDasStringGridBefüllen; //hier das Grid befüllen, in der Zeile "j"
      end;
  end;

RowCount := j + FixRows;

Blup 3. Dez 2012 08:18

AW: Stringgrid Zeilen füllen
 
Zitat:

Zitat von Ego (Beitrag 1194065)
Zitat:

Zitat von Helmi (Beitrag 1194038)
setz halt
Delphi-Quellcode:
RowCount := high(xyarray) + FixRows
Dann braucht das Array nur einmal durchlaufen

Nein, das ist Platzverschwendung; z.B. Array > 200 und nur 15 Einträge werden gebraucht, da mache ich doch kein riesengroßes Stringgrid!

Das ist keine Platzverschwendung, Stringvariablen sind im Delphi nur Pointer.
Ein Array mit 200 Einträgen nimmt also ca. 200 * 4Byte in Anspruch.
Die einzelnen Zeilen werden intern auch nur in einem Array gespeichert.
Solange da nichts reingeschrieben wird, braucht man auch nicht mehr Speicher.

Sir Rufo 3. Dez 2012 08:40

AW: Stringgrid Zeilen füllen
 
Zitat:

Zitat von Ego (Beitrag 1194065)
Das, was ich als zweite Methode angegeben habe, ist schon optimal. Mein Problem ist ja nicht: 'Wie mache ich das?' sondern: 'Wieso verhält sich Stringgrid so tückisch, daß Methode 1 teilweise (aber eben nur teilweise!) funktioniert?'

Das StringGrid verhält sich nicht tückisch, sondern du benutzt es nicht as designed.

Du hast ein Verhalten beobachtet und daraus ein Standardverhalten abgeleitet, welches aber nicht zugesichert wird.

Somit bleibt nur die Möglichkeit des ständigen Setzens der Zeilenanzahl (deine Methode 2)

oder

die maximal benötigte Anzahl vor der Schleife setzen, und am Ende die tatsächlich benötigte Anzahl zu setzen. In den meisten Fällen sollte das auch die schnellste Möglichkeit sein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:16 Uhr.

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