Page 1 sur 1

Redimensionner mettre à jour un CanVasGadget

Publié : mar. 15/févr./2022 14:44
par falsam
Ce sujet a pour objectif de montrer une méthode (Il y a en surement d'autres) pour mettre à jour un CanvasGadget suite à un redimensionnement de celui-ci.

Cette question a été posée sur le serveur PureBasic Discord par Shadow.
Shadow sur Discord a écrit :salut, est ce que c'est normal que quand je redimensionne un canevas sont contenue disparait ?
Et bien oui Shadow comme te le montre cet exemple.

Code : Tout sélectionner

EnableExplicit

Enumeration window
  #mf
EndEnumeration

Enumeration gadget
  #mfCanvas
EndEnumeration

; Sommaire
Declare Start()
Declare RefreshCanvas()
Declare Resize()
Declare Exit()

Start()

Procedure Start()
  OpenWindow(#mf, 0, 0, 800, 600, "CanvasResize", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
  CanvasGadget(#mfCanvas, 0, 0, 800, 600)
  
  ; Dessin sur le canvas
  RefreshCanvas()  
  
  ; Déclencheurs
  BindEvent(#PB_Event_SizeWindow, @Resize())  ; Redimensionnement du canvas
  BindEvent(#PB_Event_CloseWindow, @Exit())   ; Sortie de l'application
  
  ; Loop
  Repeat : WaitWindowEvent(1) : ForEver   
EndProcedure

Procedure RefreshCanvas()
  Protected ww = GadgetWidth(#mfCanvas)
  Protected wh = GadgetHeight(#mfcanvas)
  
  StartDrawing(CanvasOutput(#mfCanvas))
  
  ; Clear canvas
  Box(0, 0, ww, wh, RGB(165, 224, 191))
  
  StopDrawing()
EndProcedure

Procedure Resize()
  Protected ww = WindowWidth(#mf)
  Protected wh = WindowHeight(#mf)
  
  ResizeGadget(#mfCanvas, #PB_Ignore, #PB_Ignore, ww, wh)
  ;RefreshCanvas()
EndProcedure

Procedure Exit()
  End
EndProcedure
Pour éviter ce désagrément, il faut dessiner à nouveau tous les éléments dans ton CanvasGadget. Décommente RefreshCanvas() dans la procédure Resize. Redimensionne la fenêtre, le souci que tu évoques a disparu.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : mar. 15/févr./2022 16:56
par falsam
Avec le code précédent j'ai ajouté l'ajout d'éléments (Des carrés identiques) dans des positions aléatoires en pressant la touche espace. Ces éléments défilent vers le bas de l'écran.

Code : Tout sélectionner

EnableExplicit

Enumeration window
  #mf
EndEnumeration

Enumeration gadget
  #mfCanvas
EndEnumeration

Enumeration misc
  #FontGlobal
  #mfSpace
  #mfRefresh
EndEnumeration

; Liste des Objets qui seront ajoutés au canvas
Structure NewObject
  x.i     
  y.i
  Color.i
EndStructure
Global NewList Object.NewObject()

; Sommaire
Declare Start()
Declare AddObject()
Declare RefreshCanvas()
Declare Resize()
Declare Exit()

Start()

Procedure Start()
  LoadFont(#FontGlobal, "Arial", 11)
  
  OpenWindow(#mf, 0, 0, 800, 600, "CanvasResize", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
  CanvasGadget(#mfCanvas, 0, 0, 800, 600)
    
  ; La touche Espace permet d'ajouter un Object (Evenement Menu)
  AddKeyboardShortcut(#mf, #PB_Shortcut_Space, #mfSpace) 
  
  ; Ajout d'un timer de raffraichissement du canvas 
  AddWindowTimer(#mf, #mfRefresh, 16)
  
  ; Déclencheurs
  BindEvent(#PB_Event_Menu, @AddObject())               ; Ajout d'un Object
  BindEvent(#PB_Event_SizeWindow, @Resize())            ; Redimensionnement du canvas
  BindEvent(#PB_Event_Timer, @RefreshCanvas(), #mf, #mfRefresh)  ; Mise à jour du canvas
  BindEvent(#PB_Event_CloseWindow, @Exit())             ; Sortie de l'application
  
  ; Loop
  Repeat : WaitWindowEvent() : ForEver   
EndProcedure

Procedure AddObject()
  Protected ww = GadgetWidth(#mfCanvas)
  Protected wh = GadgetHeight(#mfcanvas)
  Protected x = Random(ww)
  Protected y = Random(wh)
  Protected Color = RGB(Random(255), Random(255), Random(255)) 
  
  AddElement(Object())
  With Object()
    \x = x
    \y = y
    \Color = Color
  EndWith 
EndProcedure

Procedure RefreshCanvas()
  Protected ww = GadgetWidth(#mfCanvas)
  Protected wh = GadgetHeight(#mfcanvas)
  
  StartDrawing(CanvasOutput(#mfCanvas))
  
  ; Clear canvas
  Box(0, 0, ww, wh, RGB(169, 169, 169))
  
  ; Ajout de chaque Object
  ForEach Object()
    With Object()
      \y + 1
      
      Box(\x, \y, 40, 40, \Color)
    EndWith
  Next
  
  ; Barre info en bas du canvas
  DrawingFont(FontID(#FontGlobal))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawText(10, wh -30, "Touche [Espace] pour ajouter un objet - Nombre d'éléments ; " + Str(ListSize(Object())), RGB(255, 250, 250))
  
  StopDrawing()
EndProcedure

Procedure Resize()
  Protected ww = WindowWidth(#mf)
  Protected wh = WindowHeight(#mf)
  
  ResizeGadget(#mfCanvas, #PB_Ignore, #PB_Ignore, ww, wh)
  RefreshCanvas()
EndProcedure

Procedure Exit()
  End
EndProcedure

Re: Redimensionner mettre à jour un CanVasGadget

Publié : mar. 15/févr./2022 17:44
par Shadow
Merci beaucoup Falsam pour ces exemples :)

Re: Redimensionner mettre à jour un CanVasGadget

Publié : mar. 15/févr./2022 20:51
par Ollivier
En terme de performance, mais en excluant l'accélération graphique (openScreen, etc... ), est-ce qu'il n'est pas plus efficace d'utiliser
- une image, dans
- un scrollArea réadapté à la fenêtre,
et d'utiliser
- un "canvasPixel" qui se déplace continuellement sous le pointeur souris quand celui-ci pointe l'image

??

Merci pour le partage depuis discord.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : mer. 16/févr./2022 16:32
par Micoute
je viens de comprendre pourquoi Shadow réussi à animer des images dans un canvas.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : mer. 16/févr./2022 21:51
par Ollivier
Meilleurs voeux Micoute, heureux de te savoir bien portant.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : jeu. 17/févr./2022 11:19
par Micoute
Bonjour Ollivier et merci beaucoup, c'est vrai que depuis que je suis en bretagne, ma santé s'est améliorée, ici les routes sont très plates contrairement à Coutances où ce n'était que montées et descentes.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : ven. 18/févr./2022 9:35
par microdevweb
Bonjour à tous,
pour ma part, je dessine d'abord dans une image et dessine ensuite l'image dans le canvas.
Lorsque la fenêtre est redimensionnée, je redessine l'image et redessine cette dernière dans le canvas.
Par contre si je veux créer par exemple des boîtes de sélection d'éléments, j'utilise l'image comme masque de fond, ainsi je dessine l'image et ensuite la ou les boîtes de sélections.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : ven. 18/févr./2022 13:28
par falsam
microdevweb a écrit : ven. 18/févr./2022 9:35 pour ma part, je dessine d'abord dans une image et dessine ensuite l'image dans le canvas.
Lorsque la fenêtre est redimensionnée, je redessine l'image et redessine cette dernière dans le canvas.
je crois que c'est la solution que Shadow a finalement choisi.

Si j'ai bien compris, pour chaque modification, tu dessines dans une image puis tu crées l'image dans le canvas.
Si le canvas est redimensionné, tu crées de nouveau l'image, et tu redessines les objets.

N'est il pas plus rapide de faire tout ça dans le canvas ? A chacun sa solution ;)

Re: Redimensionner mettre à jour un CanVasGadget

Publié : ven. 18/févr./2022 14:23
par microdevweb
falsam a écrit : ven. 18/févr./2022 13:28 N'est il pas plus rapide de faire tout ça dans le canvas ? A chacun sa solution ;)
Bonjour Falsam,

J'ai essayé les deux solutions, mais les fonctions de dessin avec vector même si elles sont très rapides, prennent je pense plus de temps que le dessin d'une image préalablement créée.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : ven. 18/févr./2022 17:38
par falsam
microdevweb a écrit : ven. 18/févr./2022 14:23 .... mais les fonctions de dessin avec vector ...
Le code de mon premier message n'utilise pas la bibliothèque vecteur. Mais je suis d'accord avec toi, si j'avais utilisé cette bibliothèque, la mise à jour des objets sur le canvas serait plus longue à s'effectuer.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : sam. 19/févr./2022 4:28
par Ollivier
Ça dépend de l'utilisation :

(ici les modifs sont considérées en fonction du clavier et de la souris)
1- dessin sur image = pas de modif de la surface
2- dessin sur image sur canvas = modifs ponctuelles de la surface
3- dessin sur canvas = modifs fréquentes de la surface
4- pas de dessin car pas d'ordi que l'on a laissé se promener dans un lieu public = modifs imaginaires et imaginées par un blaireau comme moi

(Je vous déconseille la solution 4 bien qu'elle vous évite tout bug ou crash, ça reste alors un usage délicat de l'informatique)

Re: Redimensionner mettre à jour un CanVasGadget

Publié : sam. 19/févr./2022 16:09
par Shadow
Après toutes mes expérience, je peux répondre à tous ça.

Le plus simple et le plus propre c'est de créer un ScrollAreaGadget assez grand et ensuite de mettre un canevas
dedans de la taille voulue et celui-ci se sera jamais redimensionné (le canevas), c'est un excellent moyen ça.

Quand tu change la taille de la fenêtre, tu change juste la taille du ScrollAreaGadget et basta.
Sinon en 2, pour parler du sujet plus sérieusement, effectivement...

Il faut non pas dessiner sur le canevas directement mais sur une image, et ensuite tu met à jour
le canevas avec cette image, ainsi quand celui-ci sera redimensionné, oui tu perdra l'image afficher dessus
mais tu t'en fou en faite puisque toi tu as dessiner directement sur ton image et que ensuite tu as
donner cette image pour le canevas, donc t'as juste à mettre à jour l'image dans le canevas avec cette image-ci !

Autre solution, tu créer un grand canevas que tu ne redimensionnera jamais, sur la fenêtre, et quand
tu redimensionne la fenêtre, en faite, il ne se passera simplement rien donc
aucune perte car le canevas n'est pas redimensionné !

Après ça dépend aussi de ce que vous voulez faire !

Si tu veux que ton canevas est une bordure pour voir ça limitation, alors ici il faudra bien le redimensionné
si tu veux qu'il change de taille suivant la fenêtre, et là ya pas 50 000 solution !

La solution qui me semble le plus propre ici, et tous dépend encore de se que tu veux faire...
La solution du ScrollAreaGadget est très bien, sinon ça dépend.

Je vous remercie pour votre aide et participation.

Re: Redimensionner mettre à jour un CanVasGadget

Publié : lun. 21/févr./2022 11:02
par microdevweb
Bonjour Shadow,

Comme le dit Olivier cela dépend du cas d'utilisation. Donc il faut regarder les ressources utilisées par ton programme avec plusieurs solutions et les comparer pour choisir la meilleur.