Drag objet par objet
Ceetix
Membre
Bonsoir !
Voilà , j'ai un soucis de réflexion.
J'ai dessiner 3 rectangles dans un NSView. Ils sont tous les 2 reliés à un point d'encrage dans ma vue avec une droite.
Je peux dragger mes rectangle tous ensemble et quand je lâche ma souris, ils rejoignent le point d'encrage. Le truc c'est que j'aimerai pouvoir dragger les rectangle un par un ... Je vois pas trop comment m'y prendre.
Voici mon code et je vous mets mon projet si vous voulez voir.
.h
.m
J'ai essayé de tout bien commenter 8--)
Voilà , j'ai un soucis de réflexion.
J'ai dessiner 3 rectangles dans un NSView. Ils sont tous les 2 reliés à un point d'encrage dans ma vue avec une droite.
Je peux dragger mes rectangle tous ensemble et quand je lâche ma souris, ils rejoignent le point d'encrage. Le truc c'est que j'aimerai pouvoir dragger les rectangle un par un ... Je vois pas trop comment m'y prendre.
Voici mon code et je vous mets mon projet si vous voulez voir.
.h
<br />#import <Cocoa/Cocoa.h><br /><br />@interface Ball : NSView {<br /> Ball *maBalle;<br /> CGFloat x;<br /> CGFloat y;<br /> NSPoint posSouris;<br /> NSTimer *timer;<br /> BOOL etat;<br /> <br /> NSRect tableauDeDepart;<br /> NSRect tableauDeRect[3];<br /> NSColor *couleur[3];<br /> NSRect rectangle;<br /><br />}<br /><br />@end<br /><br />
.m
#import "Ball.h"<br /><br />@implementation Ball<br /><br />- (id)initWithFrame:(NSRect)frame {<br /> self = [super initWithFrame:frame];<br /> if (self) {<br /> /* Coordonnée du premier rectangle au lancement de l'app */<br /> x = 10;<br /> y = 100;<br /> }<br /> return self;<br />}<br /><br />- (void)drawRect:(NSRect)rect {<br /> <br /> /* Je colore ma vue */<br /> [[NSColor grayColor] set];<br /> NSRectFill ( [self bounds] );<br /> <br /> /* compteur */<br /> int i;<br /> <br /> /* Je dessine mon rectangle témoin et le met dans ma premiere case de tableau */<br /> tableauDeDepart = NSMakeRect(x, y, 30, 30);<br /> tableauDeRect[0] = tableauDeDepart;<br /> <br /> /* définition d'une couleur */<br /> couleur[0] = [NSColor redColor];<br /> <br /> /* le rectangle que je vais imprimer recoit le rectangle de la 1ere case du tableauRect */<br /> rectangle = tableauDeRect[0];<br /> <br /> for( i = 0; i<3 ; i ++)<br /> {<br /> <br /> tableauDeRect[i] = rectangle;<br /> couleur[i] = [NSColor redColor];<br /> <br /> /* Initialisation des deux points de ma droite */<br /> NSPoint p1 = NSMakePoint(rectangle.origin.x, rectangle.origin.y);<br /> NSPoint p2 = NSMakePoint(200, 300);<br /> <br /> /* Je commence à tracer ma droite */<br /> NSBezierPath *tracer = [NSBezierPath bezierPath];<br /> [tracer moveToPoint:p1];<br /> [tracer lineToPoint:p2];<br /> <br /> /* Ma droite sera bleue */<br /> [[NSColor blueColor] set];<br /> [tracer stroke];<br /> <br /> /* Je décale mon prochain rectangle de +40px sur x */<br /> rectangle.origin.x +=40; <br /> }<br /> <br /> /* Je rempli mes rectangles */<br /> NSRectFillListWithColors ( tableauDeRect, couleur, 3);<br />}<br /><br />-(void)mouseDown:(NSEvent *)theEvent {<br /> <br /> /* J'arrête le timer qui appelle elast() */<br /> [timer fire];<br /> <br /> /* Par sécurité une variable qui permet de savoir si je dois rentrer dans if de elast() */<br /> etat = YES; <br /> <br />}<br /><br />- (void)mouseDragged:(NSEvent *)theEvent {<br /> <br /> /* Position de souris */<br /> posSouris = [theEvent locationInWindow];<br /> <br /> /* mes coordonnées de rectangle deviennent les coordonnées de ma souris */ <br /> x = posSouris.x;<br /> y = posSouris.y;<br /> <br /> /* Je redessine */<br /> [self setNeedsDisplay:YES];<br />}<br /><br />- (void)mouseUp:(NSEvent *)theEvent {<br /> /* Mon etat devient NO pour que je puisse entrer dans le if de elast()*/<br /> etat = NO;<br /> <br /> /* Appel à la fonction elast() */<br /> [self elast]; <br />}<br /><br />-(void)elast<br />{<br /> if(etat == NO)<br /> {<br /> <br /> /* En fonction de la position du rectangle je le replace à mon point d'encrage de ligne */<br /> <br /> if(x <= 200 && y <= 300)<br /> {<br /> x = x + fabs(((200 - x)/100));<br /> y = y + fabs(((300 - y)/50));<br /> }<br /> <br /> if(x >= 200 && y <= 300)<br /> {<br /> x = x - fabs(((200 - x)/100));<br /> y = y + fabs(((300 - y)/50));<br /> }<br /> <br /> if(x <= 200 && y >= 300)<br /> {<br /> x = x + fabs(((200 - x)/100));<br /> y = y - fabs(((300 - y)/50));<br /> }<br /> <br /> if(x >= 200 && y >= 300)<br /> {<br /> x = x - fabs(((200 - x)/100));<br /> y = y - fabs(((300 - y)/50));<br /> }<br /> <br /> /* Je redessine */<br /> [self setNeedsDisplay:YES];<br /> <br /> /* On actualise elast() toutes le 1ms pour avoir cet effet d'animation */<br /> timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(elast) userInfo:nil repeats:NO]; <br /> }<br />}<br /><br />@end<br />
J'ai essayé de tout bien commenter 8--)
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Au lieu de 8 ?
Puis il me paraà®t bizarre ce code... pourquoi <=200 au lieu de <=0 ??
Pour 200 c'est juste que dans mon exemple mon point d'encrage de droite est en (200,300) .
Déjà attention schlum, tes conditions ne sont pas exclusives... dans le cas où x est précisément égal à 200, tu vas passer dans les 2 premières conditions au lieu d'une seule.
Mais de toute façon, si x<=200 alors (200-x)>0 et si (x>=200) alors (200-x)<0... donc d'une part pas besoin d'utiliser fabs alors qu'on connaà®t le signe de la différence... et en plus si on enlève fabs et applique le signe nous-même, ça donne la même affectation. Donc on peut se contenter de :
Quand même plus compact que les 23 lignes... et évite des if et des fabs consommateurs pour rien !!
Mais t'es au courant qu'avec cette technique il va s'en approcher de plus en plus lentement ?
Si au début il est à une distance de 100, il sera au pas suivant à 99 ; ensuite à 98.01... à chaque fois le pas d'approche sera plus petit et la convergence est très très lente !
Parce que je pensais que condition <= était erronnée donc j'ai séparé les cas.
Ce qui n'est pas dramatique en soi puisque ça ajoute 2 fois 0 :P
Mais j'avais pas compris ce qu'il voulait faire...
Ni l'intérêt des fabs en fait... Si x<=200, fabs(((200-x)/100)) = (200-x)/100
En effet passer de 23 à 2 lignes.... :-\\
Et oui c'est pour se rapprocher de plus en plus lentement, histoire de donner un petit effet .
J'ai du mal à voir comment ils auraient pu s'éloigner en se rapprochant d'1/100e de la distance... mais bon, passons :P
C'est quoi le problème en fait ?
Oui le problème c'est que c'est super chouette pour un rectangle mais j'aimerai le faire pour plus, et ne pouvoir en bouger qu'un seul (celui que je selectionne) . Et là je suis un peu perdu (voir beaucoup ...)
Si x>200, x-200>0
Si x<200, x-200<0
Sinon, pour en gérer plusieurs, il suffit d'en instancier plusieurs et dans le drawrect de sauter les tests si ce n'est pas celui sélectionné.
Enfin ça dépend de son archi et de son use case mais bon moi c'est comme ça que je gère mon "objet actuellement sélectionné" quand j'ai ce genre de trucs à faire
Oui mais imaginons qu'il y ai 100 rectangles .... Ca commence à faire un peu beaucoup non ?
Ben... Et tu redessines comment les autres (même s'ils ne bougent pas !) ?
:P
Quoi dessiner 100 rectangles, tu penses que ça va fatiguer la carte graphique ? Tu rigoles j'espère
Mais comment tu fais savoir lequel est sélectionné? Car là j'ai bien mon tableau de rectangle mais après ...
Car ok, après l'avoir selectionné je lui fou un indice qui dira que c'est lui qu'il faut bouger. Mais aavnt ?
Si ce sont des NSView, et que userInteractionEnabled=YES, ce sont elles qui vont recevoir le Touch, sinon bah tu boucles sur tes formes et tu utilises CGRectContainsPoint pour tester l'appartenance du point du Touch au rectangle, ou CGPathContainsPoint si c'est un CGPath plus complexe qu'un CGRect...
Merci
D'ailleur, je sais comment coloriser un context mais un CGRect je vois pas ...
Je créer un NSObject Rectangle avec une method d'initialisation d'un rectangle.
Puis dans ma NSView et dans drawRect je fais :
Sans ajouter a mon tableau tout marche, mes deux rectangles s'affiches.
Si je fais mon addObjet à mon tableau alors l'app crash sans même dessiner et aucun message d'erreur spécifique n'apparait à part : " EXC_BAD_ACCESS ".
Je comprends pas où est mon erreur
Ensuite, il y a sans doute aussi une erreur de mémoire... il faudrait voir commetn est initialisé "tableauRect", mais je parie qu'il est déjà libéré au niveau de ce code !
Sinon j'ai initialiser ainsi :tableauRect = [[NSMutableArray alloc] init];
Il faudrait faire un initWithObjects plutôt?
Dur dur pour la mémoire aussi :P
"addObject:" fait un "retain" sur les objets.
"[[NSMutableArray alloc] init]" c'est OK... À voir si la variable n'est pas écrasée après...
Merci à vous trois particulièrement (schlum,Ali et Philippe), c'est bien sympa de prendre du temps pour nous aider!
Tu trouveras sans doute ton bonheur dans cette page de la doc (que j'ai toujours de mal à retrouver à chaque fois d'ailleurs, je la trouve bien cachée), n particulier cette fonction autour de NSRect.
Et je suis en total accord avec Greensource . Merci beaucoup
Voici comment je m'en sers.
La compilation se fait bien mais quand je run ma fenetre n'apparait même pas
Nan, mais t'es conscient qu'à chaque appel de "drawRect", tu vas ajouter deux nouveaux objets à la liste ?
À chaque "setNeedsDisplay:", hop deux nouveaux objets...