listIcongadget() et removegadgetitem()

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

listIcongadget() et removegadgetitem()

Message par blendman »

Salut

Toujours pour mon application (level editor 2D), j'utilise une listviewgadget pour afficher une liste des sprites de mon niveau (avec des options pour en afficher certains ou pas).

Le problème, c'est lorsque je supprime un sprite, je mets à jour cette liste avec removeGadgetItem(), et là, bam, ça me fait un trou dans ma liste (lignes vides) :

Image


Vous savez comment je peux résoudre ça ?

Au départ, j'effaçais tous les éléments et je recréais la liste en fonction de la liste de sprites, mais le problème, c'est que sur des maps contenant des centaines voire milliers de sprites, c'est beaucoup trop long de recréer les gadgetitem dès que je supprime un sprite.

Un code pour illustrer le problème :

Code : Tout sélectionner

If OpenWindow(0,0,0,270,140,"ListViewGadget",#PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
  ListIconGadget(0,10,10,250,120,"",250)
  If LoadImage(0, #PB_Compiler_Home+"Examples\Sources\Data\File.bmp")     ; changez le chemin/fichier contenant votre image 32x32 pixel
    SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon)
    For a=1 To 12
      AddGadgetItem (0,-1,"Elément "+Str(a)+" de la boîte à liste",ImageID(0))   ; défini le contenu de la boîte de liste
    Next
  EndIf
  RemoveGadgetItem(0,2)
  RemoveGadgetItem(0,4)
  RemoveGadgetItem(0,5)
  RemoveGadgetItem(0,7)
  
  ; SetGadgetState(0,9)    ; sélectionne le dixième élément (la numérotation commmence à 0)
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
j'avais testé en faisant ça quand je supprime un element :
SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon)

Mais le problème, c'est que si j'ai plusieurs centaines de sprites, c'est aussi extrêmement long à recalculer...

Une idée de ce que je pourrais faire pour éviter ces lignes vides ?


EDIT :
bon, en utilisant TreeGadget() à la place, je n'ai plus ce problème.
Donc, finalement, je vais utiliser un TreeGadget() au lieu d'un LIstIconGadget(), en plus, je pourrais ajouter des dossier pour les types de sprites si besoin :)
c'te classe :D

Cependant, si vous avez une technique avec les listIconGadget() ça m'intéresse ;)

Par contre, visiblement, on ne peut pas changer la taille des icones (imageID()) des treegadgets avec AddgadgetItem() ?
boby
Messages : 261
Inscription : jeu. 07/juin/2007 22:54

Re: listIcongadget() et removegadgetitem()

Message par boby »

Code : Tout sélectionner

Structure sprites
  name.s
  img.l
EndStructure
Global NewList sprites.sprites()
Declare RemoveListItem(List liste.sprites(),item)

If OpenWindow(0,0,0,270,140,"ListViewGadget",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0,10,10,250,120,"",250)
  If LoadImage(0, #PB_Compiler_Home+"Examples\Sources\Data\File.bmp")     ; changez le chemin/fichier contenant votre image 32x32 pixel
    SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon)
    For a = 0 To 12
      AddElement(sprites())
      sprites()\name = "Elément "+Str(a)+" de la boîte à liste"
      sprites()\img = ImageID(0)
    Next a
  EndIf
  RemoveListItem(sprites(),2)
  RemoveListItem(sprites(),4)
  RemoveListItem(sprites(),5)
  RemoveListItem(sprites(),7)
 
  ; SetGadgetState(0,9)    ; sélectionne le dixième élément (la numérotation commmence à 0)
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf

Procedure RemoveListItem(List liste.sprites(),item)
  SelectElement(liste(),item)
  DeleteElement(liste())
  ClearGadgetItems(0)
  ForEach liste()
    AddGadgetItem(0,-1,liste()\name,liste()\img)
  Next
EndProcedure
A adapter selon tes besoins
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: listIcongadget() et removegadgetitem()

Message par blendman »

Merci boby ;)
C'est ce que je faisais au départ, mais quand on a plusieurs centaines de sprites, ça devient vite très lent (pour la listicongadget), alors qu'avec le treegadget, plus besoin d'actualiser la liste et de combler les lignes vides ;).
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: listIcongadget() et removegadgetitem()

Message par Shadow »

Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
El Papounet
Messages : 57
Inscription : mer. 09/juin/2010 23:47

Re: listIcongadget() et removegadgetitem()

Message par El Papounet »

Si tu es sous Windows tu peux essayer d'ajouter après la suppression de tes items le code suivant:

Code : Tout sélectionner

SendMessage_(GadgetID(0), #LVM_ARRANGE, #LVA_ALIGNTOP, 0)
Ou sinon, toujours après la suppression:

Code : Tout sélectionner

SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_List)
SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon)
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: listIcongadget() et removegadgetitem()

Message par Mesa »

Sous Windows, pour accelerer un listicon, on peut faire comme ça (c'est très efficace):

Code : Tout sélectionner

EnableExplicit

Define EventID
Define a
Define StartTime
Define ElapsedTime

If OpenWindow(0,0,0,500,400,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ListIconGadget(1,10,10,480,380,"",400,0)
  SendMessage_(GadgetID(1),#WM_SETREDRAW,0,0) ; le gadget n'est pas redessiné après un changement

  StartTime = ElapsedMilliseconds()

  For a=1 To 10000
    AddGadgetItem(1,-1,"Item "+Str(a),0,0)
  Next

  SendMessage_(GadgetID(1),#WM_SETREDRAW,1,0) ; on redessine

  ElapsedTime = ElapsedMilliseconds()-StartTime
 
  MessageRequester("",Str(ElapsedTime)+" ms. après 10.000 entrées.",0)
 
  Repeat
    EventID=WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      End
    EndIf
  ForEver
EndIf

Code : Tout sélectionner

If OpenWindow(0,0,0,270,140,"ListViewGadget",#PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
  ListIconGadget(0,10,10,250,120,"",250)
  If LoadImage(0, #PB_Compiler_Home+"Examples\Sources\Data\File.bmp")     ; changez le chemin/fichier contenant votre image 32x32 pixel
    SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon)
    For a=1 To 12
      AddGadgetItem (0,-1,"Elément "+Str(a)+" de la boîte à liste",ImageID(0))   ; défini le contenu de la boîte de liste
    Next
  EndIf
  SendMessage_(GadgetID(0),#WM_SETREDRAW,0,0) ; le gadget n'est pas redessiné après un changement
  RemoveGadgetItem(0,2)
  RemoveGadgetItem(0,4)
  RemoveGadgetItem(0,5)
  RemoveGadgetItem(0,7)
  ; 	SendMessage_(GadgetID(0), #LVM_ARRANGE, #LVA_ALIGNLEFT, 0); bug sous xp
  ;astuce de El Papounet http://www.purebasic.fr/french/viewtopic.php?f=1&t=16915&p=195008#p195008
  SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_List)
  SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon)
  SendMessage_(GadgetID(0),#WM_SETREDRAW,1,0) ; on redessine
  ;SetGadgetState(0,9)    ; sélectionne le dixième élément (la numérotation commmence à 0)
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
M.
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: listIcongadget() et removegadgetitem()

Message par Kwai chang caine »

Je sais pas si ça peut t'aider, mais autrement tu as aussi la ListIcon virtuelle 8)
Un truc de dingue au niveau de la rapidité, je l'utilise souvent pour les très longues listes...c'est imbattable. 8O
En fait le tableau est intimement lié à la ListIcon, des que tu modifies le tableau la ListIcon le reproduit..truc de ouf
Le seul bémol, c'est que certaines fonctions de PB sur les ListIcons ne fonctionnent plus :|

Pour gérer ta ListIcon, tu dois désaprendre tout ce que tu as appris

Image

et ne travailler QUE avec le tableau "myItems()" :mrgreen:

Code du grand RASHAD (4e code)
http://www.purebasic.fr/english/viewtop ... 05#p403305

Code : Tout sélectionner

#ItemCount = 35000

#LVSICF_NOINVALIDATEALL = 1
#LVN_ODCACHEHINT = #LVN_FIRST - 13

Global Dim myItems.s(#ItemCount,1)

Procedure WinCallback(hwnd, msg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  Select msg
    Case #WM_NOTIFY
      *pnmh.NMHDR = lParam
      Select *pnmh\code
        Case #LVN_ODCACHEHINT
          result = 0
        Case #LVN_GETDISPINFO                ;
          *pnmlvdi.NMLVDISPINFO = lParam
          If *pnmlvdi\item\mask & #LVIF_TEXT
            *pnmlvdi\item\pszText = @myItems(*pnmlvdi\item\iItem,*pnmlvdi\item\iSubItem)
            SetGadgetText(1,Str(#ItemCount))
          EndIf
               ;
      EndSelect
  EndSelect
  ProcedureReturn result
EndProcedure
;
If OpenWindow(0, 0, 0, 300, 430, "Virtual ListIconGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowCallback(@WinCallback())
  Licon = ListIconGadget(0,5,5,290,390,"Name",50,#LVS_OWNERDATA)
  StringGadget(1,5,405,85,20,"")
  SendMessage_(Licon, #LVM_SETITEMCOUNT, #ItemCount, #LVSICF_NOINVALIDATEALL)
  AddGadgetColumn(0,2,"Address",300)
  For i=0 To #ItemCount
    myItems(i,0) = Str(i)
    myItems(i,1) = "PureBasic Road, BigTown, CodeCity"
  Next i
 
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Marc56
Messages : 2196
Inscription : sam. 08/févr./2014 15:19

Re: listIcongadget() et removegadgetitem()

Message par Marc56 »

sur des maps contenant des centaines voire milliers de sprites, c'est beaucoup trop long de recréer les gadgetitem dès que je supprime un sprite
Il y a une raison.
Les gadgets ne sont pas conçus pour faire du stockage mais pour afficher une quantité limitée de données stockée dans une liste, un tableau, une map.
Quand cette quantité dépasse quelques centaines, il faut filtrer.
Dans tous les cas, penser à l'utilisateur final qui en informatique, a horreur de prendre l’ascenseur :mrgreen:
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: listIcongadget() et removegadgetitem()

Message par Kwai chang caine »

Marco a écrit : a horreur de prendre l’ascenseur
Et qu'est ce que ce serait si c'était l'escalier :?
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: listIcongadget() et removegadgetitem()

Message par Mesa »

@Blendman
C'est un bug que tu peux mettre sur le forum anglais, car ce qui marche sans icones ne marche pas avec, et il n'y a pas de raison.


Code : Tout sélectionner

If OpenWindow(0,0,0,270,340,"ListViewGadget",#PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
  ListIconGadget(0,10,10,250,120,"",250)
  ListIconGadget(1,10,150,250,120,"",250)
  If LoadImage(0, #PB_Compiler_Home+"Examples\Sources\Data\File.bmp") 
    SetGadgetAttribute(0, #PB_ListIcon_DisplayMode, #PB_ListIcon_SmallIcon)
    For a=1 To 12
      AddGadgetItem (0,-1,"Elément "+Str(a)+" de la boîte à liste",ImageID(0)) 
      AddGadgetItem (1,-1,"Elément "+Str(a)+" de la boîte à liste") 
    Next
  EndIf
  
  RemoveGadgetItem(0,2)
  RemoveGadgetItem(0,4)
  RemoveGadgetItem(0,5)
  RemoveGadgetItem(0,7)
  
  RemoveGadgetItem(1,2)
  RemoveGadgetItem(1,4)
  RemoveGadgetItem(1,5)
  RemoveGadgetItem(1,7)
  
  
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
M.
Répondre