Prb fluidité d'une animation dans une picturebox

daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007 - 17 mars 2007 à 07:35
daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007 - 18 mars 2007 à 09:37
Bonjour,
J'ai dans une picturebox des objets (circle, line et text) que l'utilisateur peut déplacer lorsqu'il clic dessus.
Le code est un peu bourrin : il efface la picturebox et la redessine à chaque déplacement d'un pixel de la souris.

Si on execute le prog tout seul, ça va.
Mais je m'en sert comme control ActiveX dans une autre appli et là, ça rame à mort lors du déplacement des objets (plus la fenêtre est grande et plus ça rame)!! 

Aujourd'hui on arrive à faire des supers effets 3d et moi je ne peux même pas déplacer des cercles sur un fond blanc ..?........... ;-)

J'ai pensé utiliser DirectDraw mais je suis noob en la matière et ça me parait un peut excessif pour ce que je veut faire.

Si vous avez des idées, merci....

28 réponses

jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 07:59
Bonjour,

Quel code (on le le voit pas et il est peut-être perfectible) utilises-tu pour effectuer ces déplacements ?
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 08:09
Par ailleurs : comment fais-tu pour cliquer sur des "objets" (puisque tu dis  "l'utilisateur peut déplacer lorsqu'il clic dessus") circle, et line (qui ne réponsent pas aux événements souris ?
Tu les as mis dans un container lui-même contenu dans ta pictureBox, je suppose donc... et c'est ce container que tu déplaces ?
En résumé : il nous faut plus de précisions et le code utilisé, pour y voir clair.
0
cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
17 mars 2007 à 09:29
Par "ca rame à mort", tu veux dire quoi ?

Tes objets se déplacent lentement ou ca clignote dans tout les sens ?

Pour le clignotements, c'est un problème bien connu : il faut utiliser un système de double-buffer : tu dessine dans un buffer non visible, puis tu copie l'image finale du buffer dans le buffer principal (celui qui affiche l'animation), ainsi, tu n'a plus de clignotement puisque le clignotement apparaît lorsque tu efface l'image puis tu la retrace.
0
daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007
17 mars 2007 à 10:28
Merci de vos réponses,

je met mon code en téléchargement à cette adresse pour que vous y voyez plus clair.
http://isi-challenge.cybergraphik.net/rgp.zip 
(Faite un clic droit dans la fenetre exe du prog pour faire bouger les objets)

En fait je n'ai pas de problème de scintillement. Le problème est que lorsque l'on déplace un objet circle avec la souris, le mouvement est saccadé. Plus le mouvement de la souris est rapide et plus la fenêtre est grande, plus ce problème est visible.

Je n'utilise pas de container. Tous les objets dessinés dans ma pictureBox sont stockés sous formes de tableaux contenant leurs coordonnées.
Lorsque l'événement click() se fait je compare les coordonnées du click avec mes tableaux. Si ces coordonnées sont (quasi) équivalentes alors j'autorise le déplacement de l'objet.

Lorsque le déplacement est autorisé, la pictureBox se rédessine en tant réél (a chaque mouvement d'un pixel de la souris [evenement mouseMove])  avec les nouvelles coordonnées des objets.

Ce n'est clairement pas optimisé puisqu' on redessine toute la pictureBox mais c'est plus simple .

Ps : C'est d'autant pire lorsque je m'en sert de controle ActiveX dans mon appli principale.   
 
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 11:07
Oui,
Je viens d'y jeter un coup d'oeil.


 


Comme tu t'y prends là, je vois en effet mal comment tu peux attendre des performances !


Tu dessines toute ta fenêtre, pixel par pixel .... et quand elle est grande, ma foi... celà fait beaucoup de pixels...


C'est toute la philosphie, qui est complètement à revoir.


Au lieu de redessiner tes "objets", tu ferait beaucoup mieux de "promener" des contrôles images... voire d'utiliser carrément une superposition avec transparence, d'objets à placer ...

Si tu gardes le mécanisme que tu as défini là : je ne vois rien qui pourrait vraiment apporter une amélioration sensible !
0
daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007
17 mars 2007 à 11:14
Ok, je me doutais effectivement du problème. Je vais revoir ça....

Merci !
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 12:01
Ouille !

Je viens seulement de m'apercevois que tu as donné (ce qui n'arrange pas du tout les choses) la valeur true à la propriété autoredraw de ta pictureBox !!

Il est clair que tu gagnerais :

à mettre cette propriété à false
à ajouter un cls ici :

Public Sub ReDraw(ByRef Sommet() As Variant, ByRef Liens() As Variant, pic As PictureBox)
    'on redessine tout le tableau
    Dim i As Integer, j As Integer
    pic.Cls
    'on creer les liens
    For i = 1 To UBound(Liens, 2)
etc...

Et, bien sur, à faire en sorte qu'il y ait un 1er affichage au début (tu peux pour l'instant le provoquer par un simple clic sur la form toute blanche au départ)

De cette façon, ti gagneras beaucoup en vitesse de suivi de ta souris, mais perdras en clignotements divers, que tu devrais pouvoir atténuer en jouant de la fonction ValidateRect de l'Api de Windows.

Voilà de quoi bûcher, mais je reviens vers toi cet après-midi pour t'exposer une philosophie totalement différente et plus orthodoxe (plus légère égalemen) que celle que tu as mise en oeuvre.

Bon appétit.
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 12:43
Un petit ajout à ce qui précède si tu ne veux pas qu'il soit nécessaire de cliquer une 1èere fois pour y "voir" clair :

Private Sub Form_Activate()
  ReDraw Sommet(), Liens(), Me.Picture1
End Sub

Pour le reste (exposé d'une autre philosophie)... tu dis...
0
daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007
17 mars 2007 à 13:12
Super !
Effectivement en passant la proprieté AutoRedraw à False, ça accélère bien l'animation (surtout avec l'activeX). Par contre il y a un petit problème de scientillement

En ce qui concerne l'autre philsophie, je suis partant bien sûr !!!
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 13:20
C'est sur : le problème de scintillement est difficilement évitable (je te l'avais dit) dès lors que l'on efface et recommence...
Sauf peut-être en utilisant la fonction Validaterect de l'Api de Windows...

Mais ne te casse pas trop la tête avec çà ...

Je fais une petite sieste (je suis vieux) et reviens t'exposer une autre philosophie.
A +
0
daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007
17 mars 2007 à 13:32
Ok, ben moi c'est mon fiston qui va faire une sieste ;)


a toute...
0
cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
17 mars 2007 à 13:36
C'est toujours sympa de voir qu'on parle dans le vide...
0
daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007
17 mars 2007 à 13:58
Meuuuuuuuu non !
C'est vrai que tu as évoqué le problème de scintillement...
Par contre je ne sais pas ce que tu entends par "double buffer"...
Est-ce que ce sont deux picturebox (une visible et une invisible)?
Dans ce cas cela ne va pas-t-il faire encore plus ralentir l'animation ?

Ps : Merci à tous ceux qui prenne le temps de répondre
0
cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
17 mars 2007 à 14:07
Tout à fait, le truc c'est de tracer dans un picturebox (par exemple) temporaire, avant de faire un PaintPicture sur ton usercontrol, ca ralentira bien moins qu'un autoredraw qui fait retracer l'affichage à chaque pixel modifié (tu m'étonne que ca ramait !), et ca évitera ton problème de scintillement.
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 14:09
Bonjour Nicolas,

Son problème était ici ailleurs, hélàs, et l'utilisation d'un double buffer, utile lorsque l'on déplace des contrôles, ne pouvait aller : il ne déplace rien : il repeint !
Il n'est pas possible, lorsque l'on repeint, d'utiliser cette méthode puisque :
Si l'on utilise autoredraw = True : il faudra attendre que tout se repeigne
Si on met autoredraw  à False, il faudra faire un CLS et alors : ce CLS s'appliquerait également au double Buffer, avec le même effet de scientillement, bien sur...
Ne pas mettre le CLS conduirait, par ailleurs, à une "trainée" plus moche encore jusqu'à stabilisation.
Le double buffering est certes par contre utile lorsque l'in déplace une image (un contrôle image)


Ouille ! je n'ai pas commencé ma sieste...
0
cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
17 mars 2007 à 14:31
T'as rien compris jacques : le double-buffer permet de tracer l'image AVANT de la redessiner à l'écran, y'a pas de notion de déplacement d'image ou de contrôle ! C'est une technique générale, utilisée dans n'importe quel composant graphique digne de ce nom.

Donc si dans la méthode repaint de son usercontrol, il trace l'image dans un buffer temporaire, puis qu'il l'applique dans son usercontrol, plus de scintillement (et plus de rapidité aussi car à chaque tracé (lignes, pixels ou autre), il n'est pas nécessaire de raffraichir le usercontrol (ce que fait l'autoredraw), mais uniquement enregistrer les nouveaux pixels dans le buffer.

Le repaint est automatiquement appelé à chaque fois qu'un contrôle doit être raffraichit (une fenêtre qui passe par dessus, lors du déplacement d'un contrôle, etc.), donc il est tout à fait possible de simuler un auto-redraw de façon bien plus rapide et optimisé grâce à l'événement repaint.

Tout les problèmes de scintillement qui peut y avoir, c'est à cause qu'il efface puis retrace son graphique à chaque raffraichissement, avec le double-buffer, plus besoin d'effacer : il trace par dessus l'ancienne image le contenu du buffer.

Crois-moi, j'utilise le doublebuffering depuis belle lurette, que ce soit pour des controles activeX ou pour des applications graphiques, et niveau scintillements, y'a plus rien, et niveau rapidité, j'obtiens d'excellentes performances (bien entendu, il faut savoir tracer optimisé : API voir manipulation directe de la mémoire au lieu d'accèder à chaque pixels, avec ma classe de gestion d'image par exemple, et qu'on ne vienne pas me dire encore que vb est lent !).

:-p
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
17 mars 2007 à 14:35
Je sais bien tout celà, Nicolas...
Mais va voir son Zip... et tu comprendras...
0
cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
17 mars 2007 à 14:35
Tiens d'ailleurs, une excellente source montrant les bénéfices du double-buffering, tu remarquera qu'il n'y a aucune notion de déplacement de contrôle au autre, et ca montre également les limites (très fines d'ailleurs !) de l'autoredraw :

http://www.vbaccelerator.com/home/VB/Code/Libraries/Graphics_and_GDI/Flicker_Free_API_Drawing/article.asp
0
daddycool76 Messages postés 56 Date d'inscription mardi 19 décembre 2006 Statut Membre Dernière intervention 2 juillet 2007
17 mars 2007 à 15:30
J'ai essayé le double buffer avec ce code :

Form2.Picture1.PaintPicture Form1.Picture1.Image, 0, 0

Cela ne donne rien, c'est comme si l'image de Form1.picture1.Image était vide.  Pourtant à l'écran on voit bien que ce n'est pas le cas.
J'ai l'impression  que les éléments dessinés avec les méthodes Form1.picture1.line (circle etc..) ne sont pas pris en compte...
0
cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
17 mars 2007 à 15:36
Il faut par contre que l'auto-redraw de ton Picture1 de ta Form1 soit à true, sinon c'est normal : un picturebox, s'il n'est pas visible, et que l'auto-redraw n'est pas activé, ne garde pas son graphique !
0
Rejoignez-nous