Lenteurs d'affichage des gadgets avec WindowedScreen()

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Lenteurs d'affichage des gadgets avec WindowedScreen()

Message par Octavius »

Voici le problème : sans écran fenêtré les gadgets s'affichent immédiatement, par exemple lorsque l'on clique sur un onglet tous les gadgets correspondant s'affichent instantanément ; mais quand il y a un écran fenêtré, les gadgets sont lents à s'afficher, ils s'affichent au fur et à mesure les uns après les autres. Vous pourrez facilement constater la différence de rapidité en commentant les commandes de l'écran et des sprites. Avec ou sans le débogueur ça ne change rien.

Alors ma question est donc la suivante : comment résoudre ce problème de lenteur à l'affichage ?

Voici mon code :

Code : Tout sélectionner

InitSprite()

OpenWindow(0,0,0,860,572,"Programme",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))

PanelGadget(0,532,10,318,512)
AddGadgetItem(0,-1,"Panneau n°1")
ButtonGadget(1,10,10,120,25,"Bouton n°1")
ButtonGadget(2,10,45,120,25,"Bouton n°2")
ButtonGadget(3,10,80,120,25,"Bouton n°3")
AddGadgetItem(0,-1,"Panneau n°2")
ListViewGadget(4,10,10,120,70)
ButtonGadget(5,10,90,120,25,"Bouton n°4")
ButtonGadget(6,10,125,120,25,"Bouton n°5")
ButtonGadget(7,10,160,120,25,"Bouton n°6")

CreateStatusBar(0,WindowID(0))
CreateMenu(0,WindowID(0))
MenuTitle("Projet")
MenuItem(0,"Quitter")
OpenWindowedScreen(WindowID(0),10,10,512,512,0,0,0)

CreateSprite(0,128,128)
StartDrawing(SpriteOutput(0))
Circle(64,64,64,RGB(255,0,0))
StopDrawing()

For i=1 To 250
  AddGadgetItem(4,-1,"élément n°"+Str(i))
Next i

Procedure Display()
  Static X.f,Y.f,i.b,j.b
  If i=0 : X+2 : Else : X-2 : EndIf
  If j=0 : Y+0.6 : Else : Y-0.6 : EndIf
  DisplaySprite(0,X,Y)
  If X>384 : i=1 : EndIf
  If X<0 : i=0 : EndIf
  If Y>384 : j=1 : EndIf
  If Y<0 : j=0 : EndIf
EndProcedure

Repeat

Event=WaitWindowEvent(10)
Select Event
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Menu
    EventMenu=EventMenu()
    Select EventMenu
      Case 0
        End
    EndSelect
  Case #PB_Event_Gadget
    EventGadget=EventGadget()
    Select EventGadget
      Case 1 To 3
        MessageRequester("Information","Vous avez appuyé sur le bouton n°"+Str(EventGadget))
      Case 5 To 7
        MessageRequester("Information","Vous avez appuyé sur le bouton n°"+Str(EventGadget-1))
    EndSelect
EndSelect

ClearScreen(0)

Display()

FlipBuffers()

ForEver
PS: Il n'y a dans ce code que quelques gadgets, mais la lenteur d'affichage augmente avec le nombre de gadgets à afficher, ça devient très gênant quand il y en a vraiment beaucoup...
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

D'autres tests m'ont permis de montrer que tout ce qui se passe dans la fenêtre, genre changer des textes dans des StringGadgets, mettre à jour des listes, etc. est beaucoup plus lent quand il y a l'écran fenêtré.

Je n'y connais pas grand chose, mais est-ce qu'il n'y aurait pas une histoire de thread ? Peut-être que toutes les tâches de la fenêtre sont traitées avec une priorité très basse ? Comme faire pour changer ça ?
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

cela est due au flipbuffer !!

si tu le met en rem , ça pedale !!
donc la soluce serai de l'activer seulement lorsque personne ne touche au panel :)

si on touche au panel, on se reserve un peu de delay pour le temps d'affichage des gadget , mais cela bloquera l'affichage du sprite ... Normal :D

par exemple :)

Code : Tout sélectionner

  Declare Display()
  
  
  InitSprite()
  #Gadget=1000
  
  OpenWindow(0,0,0,860,572,"Programme",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  
  PanelGadget(0,532,10,318,512) 
    AddGadgetItem(0,-1,"Panneau n°1") 
    ButtonGadget(1,10,10,120,25,"Bouton n°1")
    ButtonGadget(2,10,45,120,25,"Bouton n°2")
    ButtonGadget(3,10,80,120,25,"Bouton n°3")
    AddGadgetItem(0,-1,"Panneau n°2")
    ListViewGadget(4,10,10,120,70)
    ButtonGadget(5,10,90,120,25,"Bouton n°4")
    ButtonGadget(6,10,125,120,25,"Bouton n°5")
    ButtonGadget(7,10,160,120,25,"Bouton n°6") 
    CreateStatusBar(0,WindowID(0))
    CreateMenu(0,WindowID(0))
    MenuTitle("Projet")
    MenuItem(0,"Quitter")
    
    
    For i=1 To 250
      AddGadgetItem(4,-1,"élément n°"+Str(i))
    Next i
    
    OpenWindowedScreen(WindowID(0),10,10,512,512,0,0,0) 
    CreateSprite(0,128,128)
    StartDrawing(SpriteOutput(0))
      Circle(64,64,64,RGB(255,0,0))
    StopDrawing()
    
  
    Repeat  
        panel=-1
      event=WaitWindowEvent(10)
      Select event
        Case #PB_Event_CloseWindow
          End
        Case #PB_Event_Menu
          EventMenu=EventMenu()
          Select EventMenu
            Case 0
              End
          EndSelect
        Case #PB_Event_Gadget
          EventGadget=EventGadget()
          Select EventGadget
            Case 1 To 3
              MessageRequester("Information","Vous avez appuyé sur le bouton n°"+Str(EventGadget))
            Case 5 To 7
              MessageRequester("Information","Vous avez appuyé sur le bouton n°"+Str(EventGadget-1)) 
          EndSelect 
           Delay(100)
          panel=GetGadgetState(0)   
         
    EndSelect 
    ClearScreen(0) 
    
    If panel=-1
    Display()  
      FlipBuffers(1) 
    EndIf 
    ForEver
    
    
    
    
    Procedure Display()
      Static X.f,Y.f,i.b,j.b
      If i=0 : X+2 : Else : X-2 : EndIf
      If j=0 : Y+0.6 : Else : Y-0.6 : EndIf
      DisplaySprite(0,X,Y)
      If X>384 : i=1 : EndIf
      If X<0 : i=0 : EndIf
      If Y>384 : j=1 : EndIf
      If Y<0 : j=0 : EndIf
    EndProcedure
    
    
    
    
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

[Reedit] le code ci dessus :)
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Oui ça résout en partie le problème. En fait "cliquer sur un onglet" n'est qu'un seul des événements qui peut se produire qui nécessite de traiter une tâche de la fenêtre. Par exemple, si je dois mettre à jour une série de StringGadget, la mise à jour est ralentie, et il faudrait que je fasse un système pour gérer tous les événements possible et stopper le FlipBuffers() à chaque fois... Ce n'est pas très satisfaisant.

J'ai pensé peut-être jouer avec SetFrameRate() et/ou SetFrameRefresh(), mais je n'arrive à rien en mettant des valeurs au hasard. Vous auriez une idée ?
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

C'est pour faire un jeu ou un éditeur ??

Code : Tout sélectionner

InitSprite()

OpenWindow(0,0,0,860,572,"Programme",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))

PanelGadget(0,532,10,318,512)
AddGadgetItem(0,-1,"Panneau n°1")
ButtonGadget(1,10,10,120,25,"Bouton n°1")
ButtonGadget(2,10,45,120,25,"Bouton n°2")
ButtonGadget(3,10,80,120,25,"Bouton n°3")
AddGadgetItem(0,-1,"Panneau n°2")
ListViewGadget(4,10,10,120,70)
ButtonGadget(5,10,90,120,25,"Bouton n°4")
ButtonGadget(6,10,125,120,25,"Bouton n°5")
ButtonGadget(7,10,160,120,25,"Bouton n°6")

CreateStatusBar(0,WindowID(0))
CreateMenu(0,WindowID(0))
MenuTitle("Projet")
MenuItem(0,"Quitter")
OpenWindowedScreen(WindowID(0),10,10,512,512,0,0,0)

CreateSprite(0,128,128)
StartDrawing(SpriteOutput(0))
Circle(64,64,64,RGB(255,0,0))
StopDrawing()

For i=1 To 250
  AddGadgetItem(4,-1,"élément n°"+Str(i))
Next i

Procedure Display()
  Static X.f,Y.f,i.b,j.b
  If i=0 : X+2 : Else : X-2 : EndIf
  If j=0 : Y+0.6 : Else : Y-0.6 : EndIf
  DisplaySprite(0,X,Y)
  If X>384 : i=1 : EndIf
  If X<0 : i=0 : EndIf
  If Y>384 : j=1 : EndIf
  If Y<0 : j=0 : EndIf
EndProcedure

Repeat

Event=WindowEvent()
Select Event
  Case 0
    Delay(1)
    ClearScreen(0)
    Display()
    FlipBuffers()
    
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Menu
    EventMenu=EventMenu()
    Select EventMenu
      Case 0
        End
    EndSelect
  Case #PB_Event_Gadget
    EventGadget=EventGadget()
    Select EventGadget
      Case 1 To 3
        MessageRequester("Information","Vous avez appuyé sur le bouton n°"+Str(EventGadget))
      Case 5 To 7
        MessageRequester("Information","Vous avez appuyé sur le bouton n°"+Str(EventGadget-1))
    EndSelect
EndSelect

ForEver
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Un éditeur!

Merci comtois, ton astuce fonctionne parfaitement bien! Je n'aurais jamais pensé faire un "Case 0" pour WindowEvent() ! :idea:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Octavius a écrit :Un éditeur!

Merci comtois, ton astuce fonctionne parfaitement bien! Je n'aurais jamais pensé faire un "Case 0" pour WindowEvent() ! :idea:
oui ! moi non plus :)
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Merci Comtois !
Avatar de l’utilisateur
Ouaf-Ouaf
Messages : 212
Inscription : dim. 11/juil./2004 9:07

Message par Ouaf-Ouaf »

Whaa.. J'savais pas qu'on pouvait utiliser les gadgets dans un windowedScreen *bave*
Parfait pour un editeur en effet :P
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Le seul petit bémol c'est qu'à cause de WindowEvent() le programme devient gourmand en temps CPU (chez moi environ 45% avec le dernier code donné par comtois).

Je cherche donc un moyen d'optimiser cela.

Pour l'instant je n'ai pas trouvé une meilleure solution que d'augmenter le temps de Delay(), par exemple : Delay(1000/60) pour avoir au maximum 60 boucles par seconde. Ce n'est pas très élégant mais ça a l'air de fonctionner.

EDIT: J'ai remarqué un autre truc, lorsque la souris est capturée par l'écran avec InitMouse() et ReleaseMouse(#False), l'événement Event=0 ne se produit plus : la commande Debug permet de montrer que le programme boucle sur l'événement Event=512 (je ne sais pas à quoi correspond cette constante). Il faut donc modifier "Case 0" en "Case 0,512" si le programme doit gérer une souris.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Je vais ptêt dire une mauvaise mais je préfère la dire quand même au cas où ça marche : WaitWindowEvent(1000/60), ça donne quoi ?

Si ça donne rien de bon, tu peux mettre un timer en CallBack aussi.

Et pour la souris, j'ai proscrit ReleaseMouse(). C'est une instruction à la c... qui m'a valu plusieurs heures de tests pour la faire tourner. Elle a quelque chose d'irréversible.
Résultat : je mixe les 2 systèmes de saisie de la souris GetCursorPos_() pour la partie windows, gadget, menu et compagnie et ExamineMouse() pour la partie graphique (pour choper les MouseDelta essentiellement).

Le programme est . Les 2 procédures qui peuvent t'intéresser WorldMenu() et ExploreWorld() (c'est l'une des procédures «graphiques» appelées par WorldMenu() ) pour voir comment je jongle même s'il n'y a de simultanéïté (je ne fais rien bouger en graphique pendant que tu accèdes au menu). Je ne sais si ça t'aidera plus...
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Le seul petit bémol c'est qu'à cause de WindowEvent() le programme devient gourmand en temps CPU (chez moi environ 45% avec le dernier code donné par comtois).
Essaye d'augmenter le Delay() , en mettant 10 par exemple.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Avec WaitWindowEvent(1000/60) les animations sont trop saccadées, Delay(1000/60) fonctionne mieux. Je vais garder cette solution je pense, ça me fait redescendre à 0-2% de temps CPU. :)

Je ne comprends pas ton problème Ollivier avec ReleaseMouse(), chez moi ça fonctionne parfaitement bien, j'arrive bien à m'en servir sans problème.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Octavius a écrit :Avec WaitWindowEvent(1000/60) les animations sont trop saccadées, Delay(1000/60) fonctionne mieux.
autant faire un Delay(16) alors :D
Répondre