[..] Performance ajout de lignes dans Listview

Aide sur les Interfaces Graphique Utilisateurs (GUI).
Règles du forum
.
Répondre
jpascal
Niveau 5
Niveau 5
Messages : 183
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

[..] Performance ajout de lignes dans Listview

#1

Message par jpascal »

Bonjour,

Tout d'abord veuillez m'excuser si je ne fournis pas de script complet.
Ma question fait appel à votre expérience de codeur. ;-)

Soit un tableau à deux dimensions $g_aArray
un tableau $g_aCol_Name avec le nom des colonnes
une liste Enum avec le numéro des colonnes $g_eCol_xxx
une listview $idListview
des combobox $idCombo_XXX
$g_sSep = '|'

Si par exemple ma combo $idCombo_Etat propose les valeurs Ouvert et Fermé, je ne veux qu'afficher les lignes dont l'Etat est "Ouvert" si je sélectionne "Ouvert" dans la combo.

Je souhaite avoir l'affichage le plus rapide des données de mon tableau dans la listview après avoir sélectionné un filtre à l'aide de mes combobox.

Pour gérer le(s) filtre(s), j'utilise ce code :
For $sCombo In $g_aCombo
      If GUICtrlRead(Eval('idCombo_' & $sCombo)) <> '' And GUICtrlRead(Eval('idCombo_' & $sCombo)) <> ' ' Then ; Existe et différent de l'espace ' '
         $sFilters &= '$g_aArray[$iRow][' & Eval('g_eCol_' & $sCombo) & '] = "' & GUICtrlRead(Eval('idCombo_' & $sCombo)) & '" And '
      EndIf
   Next
   $sFilters &= True ; Si tous les filtres sont à blanc, alors il faut au moins un filtre pour que le if fonctionne

Pour afficher les lignes, j'ai testé trois codes possibles.

1. Avec GUICtrlCreateListViewItem(), le traitement avec un filtre X s'exécute en 660 ms :
   For $iRow = 0 To UBound($g_aArray) - 1
      If Execute($sFilters) Then
         $sLine = $g_aArray[$iRow][0]
         For $iCol = 1 To UBound($g_aCol_Name) - 1 ; 650 msec
            $sLine &= $g_sSep & $g_aArray[$iRow][$iCol]
         Next
         GUICtrlCreateListViewItem($sLine, $idListview)

         GUICtrlSetBkColor(-1, $g_sBkColor)
      EndIf
   Next

2. Avec GUICtrlCreateListViewItem() et en fixant en dur les colonnes utilisées, le traitement avec un filtre X s'exécute en 450 ms :
   For $iRow = 0 To UBound($g_aArray) - 1
      If Execute($sFilters) Then
         GUICtrlCreateListViewItem($g_aArray[$iRow][0] & $g_sSep & $g_aArray[$iRow][1] & $g_sSep & $g_aArray[$iRow][2] & $g_sSep & $g_aArray[$iRow][3] & _
               $g_sSep & $g_aArray[$iRow][4] & $g_sSep & $g_aArray[$iRow][5] & $g_sSep & $g_aArray[$iRow][6], $idListview)

         GUICtrlSetBkColor(-1, $g_sBkColor)
      EndIf
   Next

3. Avec _GUICtrlListView_AddItem(), le traitement avec un filtre X s'exécute en 500 ms :
   For $iRow = 0 To UBound($g_aArray) - 1
      If Execute($sFilters) Then
         $iIndex = _GUICtrlListView_AddItem($idListview, $g_aArray[$iRow][0])
         For $iCol = 0 To UBound($g_aCol_Name) - 1 ; 500 ms
            _GUICtrlListView_AddSubItem($idListview, $iIndex, $g_aArray[$iRow][$iCol], $iCol)
         Next
      EndIf

         GUICtrlSetBkColor(_GUICtrlListView_GetItemParam($idListview, $iIndex), $g_sBkColor) ; Ne fonctionne pas
   Next

Mes conclusions :
Si j'utilise _GUICtrlListView_AddItem(), le traitement est rapide mais je ne peux pas différencier une ligne sur deux avec GUICtrlSetBkColor()
Si j'utilise GUICtrlCreateListViewItem(), les lignes sont différenciées mais le temps de traitement est plus important.

Je suis donc obligé de mettre en dur le nombre de colonnes pour obtenir le meilleur temps de traitement au détriment d'un code "statique".
En effet si j'ajoute une colonne à mon tableau dynamiquement (j'ajoute une valeur à mon tableau $g_aCol_Name), je suis obligé d'aller ajouter manuellement :
& $g_sSep & $g_aArray[$iRow][7]

Autant dire qu'aucune solution ne me convient à 100%.
Auriez-vous une autre piste/astuce à me proposer ?
AutoIt 3.3.15.1 / 3.3.15.4 - AutoIt3Wrapper 21.316.1639.0.0
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2034
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: [..] Performance ajout de lignes dans Listview

#2

Message par TommyDDR »

Je ne comprends pas votre façon de nommer vos variable, vous avez l'air de connaitre les tableaux, mais vous utilisez quand même :
Eval('idCombo_' & $sCombo)
Pourquoi ne pas avoir un tableau pour $idCombo et y accéder de cette façon : $idCombo[$sCombo] ?

Je pense que votre code est généré avec Koda, je vous conseille fortement de renommer vos variables, utiliser Eval est une très mauvaise façon de programmer (en tout cas pour le cas que vous décrivez).

Sinon, comme vous ne fournissez pas de code testable, c'est compliqué de pouvoir tester une solution pour vous la proposer, mais je pense que si vous utilisiez _GUICtrlListView_BeginUpdate() avant de créer vos items puis _GUICtrlListView_EndUpdate() après la création des items, vous devriez améliorer les performances de votre programme.
Cependant, avec _GUICtrlListView_AddItem, vous ne pourrez pas colorier facilement le background d'un item.

Pour votre méthode utilisant GUICtrlCreateListViewItem(), remplacez votre ligne GUICtrlCreateListViewItem(xxxxx) par :
Local $text = ""
For $i = 0 To UBound($g_aArray, 2) - 1
   If($i > 0) Then
      $text &= $g_sSep
   EndIf
   $text &= $g_aArray[$iRow][$i]
Next
GUICtrlCreateListViewItem($text, $idListview)
De cette façon, vous n'aurez pas besoin de rajouter à la main les nouvelles colonnes, le code s'adaptera à la taille du tableau
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
jpascal
Niveau 5
Niveau 5
Messages : 183
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [..] Performance ajout de lignes dans Listview

#3

Message par jpascal »

Je suis totalement d'accord avec vous, utiliser Eval() est une source d'erreur car on ne peut pas utiliser #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 pour vérifier le code.

Je m'en sers donc car je n'avais pas d'alternative.
La syntaxe $idCombo[$sCombo] est appelée Maps dans l'aide d'AutoIt.
Je m'y suis intéressé il y a longtemps mais cela me posait d'autress problèmes, j'avais donc décidé de ne pas l'utiliser.
Il est d'ailleurs indiqué, toujours dans l'aide d'AutoIt :
 ! Message de : jpascal
Warning: This feature is experimental. It may not work, may contain bugs or may be changed or removed without notice.

DO NOT REPORT BUGS OR REQUEST NEW FEATURES FOR THIS FEATURE.

Je n'utilise pas Koda et je ne l'ai jamais utilisé pour tout vous dire.

Vous ne pouviez pas le savoir mais j'utilise bien _GUICtrlListView_BeginUpdate() suivi de _GUICtrlListView_DeleteAllItems() avant de créer les items puis _GUICtrlListView_EndUpdate() après.

Pour le filtrage, je viens de faire la modification pour remplacer les Eval() par des maps.
Je conserve pour l'instant ma ligne Global Enum $g_eCol_XX1, $g_eCol_XXY, $g_eCol_XYX, $g_eCol_XYY et continue d'utiliser un Eval('g_eCol_' & $sCombo) & ']
   ; Création du filtre
   For $sCombo In $g_aCombo
      If GUICtrlRead($midCombo[$sCombo]) <> '' And GUICtrlRead($midCombo[$sCombo]) <> ' ' Then  ; Existe et différent de l'espace ' '
         $sFilters &= '$g_aArray[$iRow][' & Eval('g_eCol_' & $sCombo) & '] = "' & GUICtrlRead($midCombo[$sCombo]) & '" And '
      EndIf
   Next
   $sFilters &= True ; Si tous les filtres sont à blanc, alors il faut au moins un filtre pour que le if fonctionne

Concernant la modification du code de création des items, le code que vous proposez correspond à mon premier code.
Comme indiqué, il est plus lent que le code n°2 qui a le désavantage d'être "statique".
         $sLine = $g_aArray[$iRow][0]
         For $iCol = 1 To UBound($g_aCol_Name) - 1
            $sLine &= $g_sSep & $g_aArray[$iRow][$iCol]
         Next
         GUICtrlCreateListViewItem($sLine, $idListview)

Si je n'arrive pas à gagner en performances, ce sujet aura eu le mérite de me refaire découvrir les maps et pour cela je vous en remercie. :-)
AutoIt 3.3.15.1 / 3.3.15.4 - AutoIt3Wrapper 21.316.1639.0.0
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2252
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Performance ajout de lignes dans Listview

#4

Message par jchd »

La syntaxe $idCombo[$sCombo] est appelée Maps dans l'aide d'AutoIt.
Ou une Array ! Tout dépend de la forme utilisée lors de la déclaration :

Code : Tout sélectionner

Local $m[]   ; c'est un type Map
Local $a[4]   ; c'est un type Array
Local $a = [1,2,3]   ; c'est aussi un type Array
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
Nine
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 70
Enregistré le : ven. 17 avr. 2020 01:23
Status : Hors ligne

Re: [..] Performance ajout de lignes dans Listview

#5

Message par Nine »

La meilleure performance d'affichage d'une ListView est en utilisant une vue virtuelle. Recherche sur le site anglo (Virtual Listview)...
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2034
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: [..] Performance ajout de lignes dans Listview

#6

Message par TommyDDR »

Tiens, je ne connaissais pas la syntaxe : Local $var[] pour déclarer une map

@jchd
Je viens de tester l'exemple de l'aide :
Local $mInternal[] ; Declare a Map
$mInternal["Internal"] = "AutoIt3" ; Assign an element
Local $mContainer[] ; Declare a container Map
$mContainer.Bin = $mInternal ; Assign the first Map as an element
; All of these return "AutoIt3"
$sString = $mContainer["Bin"]["Internal"]
$sString = $mContainer.Bin.Internal
$sString = $mContainer["Bin"].Internal
$sString = $mContainer.Bin["Internal"]
Et j'obtiens l'erreur :
Local $mInternal[]
Local $mInternal[^ ERROR
Ma version d'autoit (3.3.14.5) correspond pourtant bien à la version affichée dans l'aide.
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2252
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Performance ajout de lignes dans Listview

#7

Message par jchd »

Il faut utiliser la version beta pour le support du type Map.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2034
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: [..] Performance ajout de lignes dans Listview

#8

Message par TommyDDR »

C'est donc pour ça ! merci ;)
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Répondre