Bonsoir,
J'ai déjà partiellement abordé le sujet dans une autre discussion, mais je trouve le fonctionnement des StringGrids extrêmement lent... et j'essaye de le comprendre pour optimiser.
Je cherchais la meilleure méthode pour filtrer "visuellement" une StringGrid et d'une manière plus large pour les utiliser au mieux. Comme j'ai déjà rencontré récemment un problème de lenteur sur les tris de ce composant, j'ai fait quelques tests.
La StringGrid de référence que j'ai utilisée est une StringGrid par défaut modifiée ainsi :--> 00:00:00 (~4 x 10^-7)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 var Deb, Fin : TTime; sTmp : string; i : integer; begin Deb := now(); with SG1 do begin RowCount := 10000; for i:=1 to 9999 do Cells[1,i] := intToStr(i); end; Fin := now(); Showmessage(TimeToStr(Fin-Deb)+' ( '+FloatTostr(Fin-Deb)+' )'); end;
J'ai utilisé 3 méthodes pour filtrer "visuellement" les nombres pairs.
Méthode 1 : Je parcours la SG1 et cache les lignes impaires :
--> 00:00:03 (~441 x 10^-7). Et à l'utilisation, c'est en effet très "perceptible"...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 var Deb, Fin : TTime; i : integer; begin Deb := now(); with sg1 do for i := 1 to RowCount -1 do if i mod 2 <> 0 then RowHeights[i] := 0; Fin := now(); Showmessage(TimeToStr(Fin-Deb)+' ( '+FloatTostr(Fin-Deb)+' )'); end;
Méthode 2: Je parcours SG1 et place les lignes paires dans une SG2 dont les propriétés sont définies par défaut dans l'IDE.
--> 00:00:03 (~462 x 10^-7)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 var Deb, Fin : TTime; i, iRow : integer; begin Deb := now(); iRow := 0; with sg1 do for i := 1 to RowCount -1 do if i mod 2 = 0 then begin iRow := iRow+1; sg2.RowCount := iRow +1; sg2.cells[1,iRow] := cells[1,i]; end; Fin := now(); Showmessage(TimeToStr(Fin-Deb)+'('+FloatTostr(Fin-Deb)+')'); end;
Troisème méthode, identique à la seconde mais programmée différemment : le RowCount de SG2 n'est pas modifié 5000 fois mais défini une fois avant le traitement.
--> 00:00:00 (~2 x 10^-7)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 var Deb, Fin : TTime; iRow, i : integer; begin Deb := now(); sg2.RowCount := 5000; iRow := 0; with sg1 do for i := 1 to RowCount -1 do if i mod 2 = 0 then begin iRow := iRow+1; sg2.cells[1,iRow] := cells[1,i]; end; Fin := now(); Showmessage(TimeToStr(Fin-Deb)+' ( '+FloatTostr(Fin-Deb)+' )'); end;
Si je peux éventuellement expliquer la différence entre la méthode 3 et la méthode 2 (la modification du RowCount donc l'ajout d'une ligne semble extrêmement lent*), pourquoi la méthode 1 est-elle si lente ? Entre les 2 méthodes également lentes et la plus rapide, il y a un facteur 200. Même si éventuellement on peut considérer que ce facteur n'est pas "significatif" et reste finalement acceptable, l'attente de l'utilisateur du résultat du filtre est désagréable... et donc s'il est possible de l'optimiser...
Bref, si vous avez de la documentation sur l'optimisation des StringGrids, je suis preneur... Cela m'évitera -même si c'est très intéressant et formateur- de m'engager dans des méthodes peu performantes.
Cordialement. Gilles
Rq : le code suivant est équivalent à la méthode 2
--> 00:00:03 (~458 x 10^-7). C'est donc la permière utilisation de sg2.RowCount à chaque itération de la boucle qui ralentit le processus. Ensuite sa réutilisation, mémorisée, ne pénalise plus...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 var Deb, Fin : TTime; i : integer; begin Deb := now(); sg2.RowCount := 1; with sg1 do for i := 1 to RowCount -1 do if i mod 2 = 0 then begin sg2.RowCount := sg2.RowCount +1; sg2.cells[1,sg2.RowCount -1] := cells[1,i]; end; Fin := now(); Showmessage(TimeToStr(Fin-Deb)+'('+FloatTostr(Fin-Deb)+')'); end;
Partager