[Résolu] Zoom, ScrollView et gestion des évènements

MickMick Membre
février 2011 modifié dans API AppKit #1
Bonjour à  tous,

Voici le problème : j'ai une vue "support" de 2 layers : la vue en elle-même n'affiche rien, ce sont les layers qui produisent le contenu. Le masque pour le redimensionnement est bien défini en hauteur et largeur. Un layer est un QTMovieLayer, l'autre est un CALayer classique dont le délégué dessine le contenu (des lignes, rien de compliqué). La vue reçoit les évènements de souris, et un array stocke la position des points
Ma vue est "embedded" dans une scrollView. Un petit slider me permet de "zoomer" en changeant la frame. La scroll affiche bien automatiquement les scrollers, et c'est opérationnel.
Mon soucis vient de la gestion des évènements de souris : comment récupérer la position de l'évènement en tenant compte à  la fois du zoom et du scrolling (translation) ? Je me perds dans tout ça, et je ne sais pas mettre en oe“uvre les AffineTransform.... De même, comment la méthode drawLayer: peut-elle être implémentée pour tenir compte de ce zoom et du scroll ??.


Réponses

  • MickMick Membre
    14:40 modifié #2
    Bon, je relance en expliquant mieux :

    ma question est : comment changer le système de coordonnées d'une vue de manière à  ce que si j'agrandit ou réduit la vue (qui est donc la documentview d'une scrollview) un point AVANT changement ait les mêmes coordonnées APRES changement ? l'objectif est que lorsque j'intercepte un évènement mouseDown, la méthode convertPoint me donne les coordonnées du point tel qu'elles auraient été si la vue n'était pas "zoomée". de même lorsque je dessine, un point dessiné après zoom doit se trouver au bon endroit...

    Voyez-vous ce que je veux dire ?...

    J'ai essayé avec un setBounds, mais cela ne "dilate pas" le système de coordonnées.

    Please.. help...
  • AliGatorAliGator Membre, Modérateur
    14:40 modifié #3
    [EDIT] (Oups oublie ce message qui était une réponse dans le cas où tu étais sur iOS, alors que je viens de voir que tu as posté dans la section Mac et pas iPhone, désolé)
  • AliGatorAliGator Membre, Modérateur
    14:40 modifié #4
    Et pourquoi tu n'appelles pas "convertPoint:fromView:" non pas sur la NSView mais sur la scrollview ?
    NSPoint pt = [theEvent locationInWindow];<br />NSPoint localPt = [scrollView convertPoint:pt fromView:nil]; // appel de convertPoint sur scrollView, et non sur self
    
    Comme ça tu demandes à  la scrollView de convertir les coords, donc elle devrait prendre en compte le scroll et zoom, non ? C'est fait pour ça normalement cette méthode
  • MickMick Membre
    14:40 modifié #5
    Bonjour Ali,

    En appelant la méthode convertPoint de la scroll view, ça merdouille complet !
    Pour l'instant, en bidouillant (mais c'est moche), je convertit d'abord les coordonnées de l'évènement dans le système de la clipView, puis je divise x et y par le facteur de zoom, puis je reconvertis de la clipView vers la documentView... => Je stocke ces coordonnées. Dans la méthode de dessin je prends un point de l'array, je multiplie par le facteur de zoom avant de dessiner
    Va savoir pourquoi, ça marche jusqu'à  un facteur de zoom de 2. Après on commence à  observer un décalage (vertical) entre le clic et ce qui est dessiné...

    Je ne crois pas que ce soit très propre....

    Que pensez-vous de la méthode de zoom, à  savoir changer la frame via NSMakeRect (origineActuellex, origineActuelley, initWidth*zoom, initHeight*zoom) ? Est-ce la technique "propre" à  utiliser ?
  • MickMick Membre
    14:40 modifié #6
    Bon, je viens de découvrir par hasard une magnifique méthode NSView appelée setFrameSize:, qui permet de changer la frame sans modifier le système de coordonnées !! Ceci me permet de virer tous mes "*zoom". C'est déjà  plus propre.

    N'empêche, lorsque j'utilise la métode NSView [self convertPoint:[event locationInWindow] fromView:nil], il y a un léger décalage (vertical et pas horizontal, ce qui est très louche...) entre mon clic de souris et le dessin.

    Peut-être cela vient du fait que j'utilise des layers ? Je redimensionne les layers avec un setFrame:, peut-être y a-t-il un décalage ? Comment redimensionner et placer mes layers PILE POIL supperposés à  la vue ?...
  • MickMick Membre
    14:40 modifié #7
    Bon, pour celles et ceux qui sont intéressé par mon soucis, j'ai (enfin !) ma réponse !

    Lorsqu'on utilise des layers (pour par exemple superposer différentes couches de dessin), et qu'on veut que ces layers aient quoi qui se passe la même position que la vue d'origine, (pour que les évènements clic ou autre soient bien "en phase" avec les layers affichés), il faut utiliser un CAConstraintLayoutManager instancié et ajouté au layer principal, et ajouter des contraintes "midX, width, midY, height" ET SURTOUT PAS BIDOUILLER A LA MAIN LES FRAME !! Du coup, si on change la frame de la vue qui accueille les layers, ceux-ci vont automatiquement prendre la même taille et par l'occasion, le même système de coordonnées que la vue.
    <br />[laVueQuickTime setWantsLayer:YES];<br />	leConteneur=[laVueQuickTime layer];<br />	leConteneur.layoutManager=[CAConstraintLayoutManager layoutManager];<br />	decos=[[CALayer layer] retain];<br />	[decos addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidX<br />													relativeTo:@&quot;superlayer&quot;<br />													 attribute:kCAConstraintMidX]];<br />	[decos addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintWidth<br />													relativeTo:@&quot;superlayer&quot;<br />													 attribute:kCAConstraintWidth]];<br />	[decos addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY<br />													relativeTo:@&quot;superlayer&quot;<br />													 attribute:kCAConstraintMidY]];<br />	[decos addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintHeight<br />													relativeTo:@&quot;superlayer&quot;<br />													 attribute:kCAConstraintHeight]];<br />	<br />	[decos setDelegate:self];//pour dessin<br />	[leConteneur addSublayer:decos];<br />
    

    Ainsi, lors du clic, les coordonnées récupérées par le [maVue convertPoint:[event locationInWindow] fromView:nil] correspondent bien aux coordonnées du layer. On divise x et y par le facteur de zoom (variable d'instance) et on stocke. Pour le dessin, on prend les coordonnées d'un point, on multiplie par le zoom et ça fonctionne. Du coup, on peut zoomer autant qu'on veut, l'ensemble reste bien cohérent et précis.

    En espérant que cela puisse aider !

    PS : les zooms, c'est quand même pas simple !
Connectez-vous ou Inscrivez-vous pour répondre.