Drag objet par objet

123468

Réponses

  • schlumschlum Membre
    mars 2009 modifié #152
    dans 1238535855:
    J'ai passé des heures sur ce problème sans pouvoir le résoudre... Ne me dis pas que c'est un truc con ... :'(

    Bah... désolé, mais très certainement si !  :P
    Comme un appel à  la fonction dessin avant que tout ne soit correctement initialisé par exemple...
  • CeetixCeetix Membre
    05:09 modifié #153
    Arrggggg . Je vois pas bor**** .
    C'est un soucis au niveau graphique pur ou niveau coordonnées de l'arc ?
  • CeetixCeetix Membre
    05:09 modifié #154
    Ok j'ai compris, il en dessine deux surperposé. Donc il faut changer les 2 coordonnées
  • schlumschlum Membre
    05:09 modifié #155
    En même temps, avec ta technique bizarre, pas étonnant qu'il en dessine 2 superposés...
    à‰trange cette idée de tableau de tableaux ; moi j'aurais fait un tableau unique qui contient pour chaque arc la référence des 2 sommets.
  • CeetixCeetix Membre
    05:09 modifié #156
    Comment ça ? Je comprends pas trop je sature  :p
  • schlumschlum Membre
    05:09 modifié #157
    Pourquoi se prendre la tête à  lier les arcs aux sommets (en double du coup) au lieu de les gérer séparément, c'est tout...
  • CeetixCeetix Membre
    05:09 modifié #158
    Bah j'essaie de les gérer séparément justement non? Et il faut bien que je les lie aux différents sommets. Il y a un truc que je dois pas saisir dans ce que tu me dis ^^
  • schlumschlum Membre
    05:09 modifié #159
    Pourquoi y a-t-il un tableau de tableaux alors, et non pas seulement un tableau d'instances d'arc ?
  • AliGatorAliGator Membre, Modérateur
    mars 2009 modifié #160
    Moi je ferais, comme modèle de données, en gros :
    @interface Sommet : ...<br />{<br />  NSString* nom;<br />  ...<br />}<br />...<br />-(id)initWithName:(NSString*)name; // appelle init + set le nom<br />@end<br /><br />@interface Arc : ...<br />{<br />  Sommet* sommet1;<br />  Sommet* sommet2;<br />  float distance;<br />}<br />-(id)initWithDistance:(float)dist fromSommet:(Sommet*)s1 toSommet:(Sommet*)s2; // constructeur de commodité<br />@end
    
    Et du coup tu peux avoir un NS(Mutable)Array d'objets Sommets, et un NS(Mutable)Array d'arcs, un bout de code vitre fait vaut mieux qu'un long discours :
    // on crée 3 sommets par exemple<br />Sommet* s1 = [[Sommet alloc] initWithName:@&quot;A&quot;];<br />Sommet* s2 = [[Sommet alloc] initWithName:@&quot;B&quot;];<br />Sommet* s3 = [[Sommet alloc] initWithName:@&quot;C&quot;];<br />// on initialise notre tableau (variable d&#39;instance) de sommets<br />tableauSommets = [[NSMutableArray alloc] initWithObjects:s1,s2,s3,nil];<br /><br />// Ajout de deux arcs, l&#39;un entre les sommets A et B l&#39;autre entre A et C.<br />Arc* s1s2 = [[Arc alloc] initWithDistance:3 fromSommet:s1 toSommet:s2];<br />Arc* s1s3 = [[Arc alloc] initWithDistance:5 fromSommet:s1 toSommet:s3];<br />// on initialise notre tableau (variable d&#39;instance) d&#39;arcs<br />tableauArcs = [[NSMutableArray alloc] initWithObjects:s1s2,s1s3,nil];<br /><br />// maintenant qu&#39;ils sont rajoutés aux tableaux et qu&#39;on en a fini avec eux, on peut releaser :<br />[s1 release]; [s2 release]; [s3 release]; // nos sommets<br />[s1s2 release]; [s1s3 release]; // nos arcs<br />// NB: faudra pas oublier de releaser tableauSommets et tableauArcs dans le -(void)dealloc bien sûr<br /><br />...<br />...<br />...<br /><br />// pour l&#39;exemple, si tu veux rajouter un sommet en cours de route :<br />Sommet* s4 = [[Sommet alloc] initWithName:@&quot;D&quot;];<br />[tableauSommets addObject:s4];<br />[s4 release];<br /><br />// et pour rajouter un arc entre le sommet B et D de distance 7 :<br />Sommet* sB = [tableauSommets objectAtIndex:1]; // tels qu&#39;on les as ajoutés, le sommet A est en zero, le B en 1<br />Sommet* sD = [tableauSommets objectAtIndex:3]; // et le D en 3 (on aurait pu utiliser la variable s4 aussi on l&#39;a pas encore releasée)<br />[tableauArcs addObject:[[[Arc alloc] initWithDistance:7 fromSommet:sB toSommet:sD] autorelease]];<br />// et voilà , on a récupéré nos deux sommets et on a créé un arc entre eux
    
  • CeetixCeetix Membre
    05:09 modifié #161
    ton (float)dist c'est juste le poids de l'arc hein?
    Et apres dans le initWithDistance je trace une ligne des coordonnée (s1.x;s1.y) -> (s2.x,s2.y) .

    Dans mon initWithName de sommet je dois aussi rajouter tout ce qui est coordonnée du sommet, couleur etc..
    Et je mois j'ai tout mis en void, je voulais savoir ce que ça allait changer de mettre les méthodes en id.
    Merci en tout cas j'avais pas pensé a faire comme ca ... ::)
  • AliGatorAliGator Membre, Modérateur
    avril 2009 modifié #162
    dans 1238563314:

    ton (float)dist c'est juste le poids de l'arc hein?
    Et apres dans le initWithDistance je trace une ligne des coordonnée (s1.x;s1.y) -> (s2.x,s2.y) .
    Oui, c'était l'idée
    dans 1238563314:
    Dans mon initWithName de sommet je dois aussi rajouter tout ce qui est coordonnée du sommet, couleur etc..
    Oui tout à  fait, j'ai oublié les coordonnées des sommets, qu'il faut bien sûr rajouter en variable d'instance de ta classe Sommet, et rajouter un constructeur de commodité (ou pas) qui te permet de passer ces coordonnées (tu peux aussi rajouter une [tt]@property NSPoint position[/tt] et affecter la valeur à  cette position dans la ligne d'après le init quand tu crées ton sommet, si tu veux pas avoir un constructeur de commodité qui a un nom de 3km)

    Mais bon c'était pour l'exemple, j'allais pas tout te faire non plus, c'était juste pour te donner une idée de la vision du modèle... que tu sembles avoir compris si tu me fais cette remarque donc :P

    dans 1238563314:
    Et je mois j'ai tout mis en void, je voulais savoir ce que ça allait changer de mettre les méthodes en id.
    Alors par contre si tu crées réellement un constructeur de commodité (initXXX), il y a des règles à  respecter : comme tu vas l'appeler sous la forme [tt]s = [[Sommet alloc] initXXX][/tt] il faut que la méthode init retourne un (id), et il faut aussi avoir appelé [super init] au début de ta méthode. Je t'invite à  relire la doc à  ce sujet ici, en bref il faut toujours coder ses designed initializers ainsi :
    -(id)initXxx:(Type)var Yyy:(Type2)var2<br />{<br />  if ((self = [super init])) {<br />    // code spécifique ici qui va initialiser les variables d&#39;instance d&#39;après var et var2<br />  }<br />  return self;<br />}
    

    Merci en tout cas j'avais pas pensé a faire comme ca ... ::)
    Bah heu c'est la base de la POO, tu crées des classes représentant les objets que tu vas manipuler, et tu crées des instances de ces classes pour créer les objets. Il faut mieux voir tout ce que tu veux manipuler comme des objets. Il va falloir t'habituer à  avoir cette vision, ça viendra avec la pratique, et au final on réalise que c'est plus clair, on peut manipuler des sommets individuellement, des arcs aussi, ça finit par faire un code clair et propre à  lire.

    Après en plus tu peux rajouter des méthodes que tu appellerais genre "-(void)drawSommet:(Sommet*)s" et "-(void)drawArc:(Arc*)arc" à  ta partie vue qui vont se charger du dessin d'un sommet individuel et d'un arc individuel, et il te suffira pour ton dessin final das drawRect de boucler sur tous tes sommets de ton tableau pour appeler drawSommet dessus, et tous tes arcs pour appeler drawArc.

    NB : On pourrait imaginer aussi plutôt une méthode [tt]-(void)draw[/tt] à  mettre dans la class Sommet, qui dessine se dernier, et pareil pour Arc. Mais ça ne respecterai pas le MVC, car là  où tes Sommet et Arc décrivent ton Modèle, le draw fait partie de la partie Vue, donc faut mieux séparer les 2 composantes.
  • CeetixCeetix Membre
    05:09 modifié #163
    Ok merci je vais me pencher dessus sérieusement.
    Pour les methodes de dessin j'avais bien fait comme ca mais je mettait en paramettre un context. Ce n'est pas a faire là ? Le context se trouvera dans ma méthode alors..
  • CeetixCeetix Membre
    05:09 modifié #164
    J'ai tester déjà  avec juste la classe Sommet. Ca marche, j'initialise à  un sommet, ca l'affiche bien. Par contre si je veux en faire plusieurs, j'ai mis une boucle for  pour afficher ensuite tous mes sommets
    for(int i=0; i&lt;[tableauSommet count]; i++)<br />{<br />&nbsp;  Sommet *temp = [[Sommet alloc] initWith...];<br />&nbsp;  [self drawSommet:temp];<br />}<br />
    


    Je voulais savoir s'il fallait release temp à  chaque itération ...
    En tout cas c'est cool, j'avais pas pensé à  faire tout ça de cette manière et c'est bien plus pratique.
  • schlumschlum Membre
    05:09 modifié #165
    T'as beaucoup de mal avec la gestion mémoire quand même  :P
    Pourquoi constamment faire des allocations / releases à  chaque dessin ?
    Il faut allouer les sommets et arcs une fois pour toute à  la lecture du fichier, point barre.
  • CeetixCeetix Membre
    05:09 modifié #166
    Bah moi j'ai compris ça avec l'allocation :

    Le mac va me faire une case mémoire pouvant contenir mon temp et donc commet je reitere l'oépération je n'ai pas besoin de release car a chaque fois la mémoire demandée par mon temp ne changera pas. C'est ça ?
  • schlumschlum Membre
    05:09 modifié #167
    À chaque fois que tu vas réitérer, ce seront de nouvelles cases mémoires, et de plus en plus jusqu'à  saturation.
  • CeetixCeetix Membre
    05:09 modifié #168
    D'accord . Merci Schlum  ;)
  • AliGatorAliGator Membre, Modérateur
    05:09 modifié #169
    dans 1238603346:

    Bah moi j'ai compris ça avec l'allocation :

    Le mac va me faire une case mémoire pouvant contenir mon temp et donc commet je reitere l'oépération je n'ai pas besoin de release car a chaque fois la mémoire demandée par mon temp ne changera pas. C'est ça ?
    Non le alloc crée un nouvel espace en mémoire pour contenir ton objet, certes, mais une fois que l'objet existe quelque part, tant qu'il est retenu par au moins un objet, il existe encore en mémoire. Par contre si tous ceux qui l'ont "retain" ont fini par le "releaser", et que du coup la balance retain-release (qu'on appelle retainCount) est retombée à  zéro, là  plus personne ne dit vouloir utiliser ton objet, donc il est détruit.

    On compare souvent ça à  un chien en laisse. Le alloc/init crée ton chien, et lui ajoute une laisse (c'est l'objet qui a fait le alloc/init qui tient ton chien en laisse). Ensuite quand des objets font un retain (explicite, genre toi qui appelle un retain, ou implicite, genre tu mets ton "chien" dans une collection comme NSArray ou NSDictionary qui comme dit dans la doc retain les objets qu'ils contiennent), ce retain correspond à  l'ajout d'une laisse à  ton chien. Et quand on fait un release, explicite (appel à  release) ou implicite (suppression de l'objet du tableau dans lequel il était par ex), ça enlève la laisse au chien.
    Quand plus personne ne tient le chien en laisse, il est libre de s'enfuir, plus personne n'en a plus rien à  fouttre de lui (ouais c'est cruel). Du coup il est détruit de la mémoire (et le runtime appelle alors sa méthode "dealloc" tout seul sur cet objet)


    Là  c'est pareil, tu crées un Sommet au début de ton programme (quand tu lis ton fichier), donc il a un retainCount de 1 (une seule "laisse"). Puis tu le mets dans un tableau, qui le retient implicitement (le retainCount = nombre de "laisses" passe à  2). Du coup tu peux relâcher la variable qui t'a servi à  créer ton Sommet avant de l'ajouter à  ton tableau, puisqu'il est encore retenu dans ton tableau. Et tant que tu ne le supprimes pas de ton tableau (ou que tu n'envoyes pas un release à  ton tableau, ce qui envoie un release à  tous ses éléments aussi), ton Sommet existe encore, puisqu'il est dans le tableau.

    // initialisation, lecture du fichier<br />// ajout d&#39;un sommet au tableau : on le crée, le temps de l&#39;ajouter, et on le release<br />Sommet* s = [[Sommet alloc] initWith...]; // retainCount = 1<br />[tableauSommets addObject:s]; // retainCount à  2 car retenu par le tableau<br />[s release]; // retainCount retombe à  1<br />// ton sommet existe encore, dans le tableau<br /><br />...<br /><br />// Récupération du sommet stocké dans le tableau<br />Sommet* temp = (Sommet*)[tableauSommets objectAtIndex:0];<br />// pas besoin de faire un alloc/init/release ici, on récupère un Sommet déjà  existant dans le tableau<br /><br />// boucle pour dessiner tous les Sommets de ton tableauSommet<br />for(Sommet* s in tableauSommets)<br />{<br /> &nbsp; [self drawSommet:s];<br />}
    
  • schlumschlum Membre
    05:09 modifié #170
    dans 1238605115:
    Du coup il est détruit de la mémoire (et le runtime appelle alors sa méthode "dealloc" tout seul sur cet objet)


    T'es sûr que c'est le runtime qui gère ça ?
    Il me semblerait plus logique que ça soit l'appel à  "release" de NSObject qui teste s'il est à  0 et appelle "dealloc" le cas échéant  ???
  • AliGatorAliGator Membre, Modérateur
    05:09 modifié #171
    dans 1238605273:

    dans 1238605115:
    Du coup il est détruit de la mémoire (et le runtime appelle alors sa méthode "dealloc" tout seul sur cet objet)


    T'es sûr que c'est le runtime qui gère ça ?
    Il me semblerait plus logique que ça soit l'appel à  "release" de NSObject qui teste s'il est à  0 et appelle "dealloc" le cas échéant  ???
    Ouais ho tu vas pas commencer à  pinailler :) lol Une petite faute sur un post de 3km, ça va hein :P Bon ok allez, hop je t'offre un  :p pour me faire pardonner  :o

    Ouais en effet c'est très certainement NSObject qui se charge d'appeler dealloc, d'autant plus que la gestion du retainCount avec les méthodes retain/release & co sont propres à  NSObject... mais ce que je voulais dire c'est que c'est pas à  nous d'appeler "dealloc" quoi ;)
  • CeetixCeetix Membre
    05:09 modifié #172
    Merci pour les explications AliGator. En C je vois tout à  fait mais là  avec les retain, release auto release j'ai un peu plus de mal.
  • AliGatorAliGator Membre, Modérateur
    05:09 modifié #173
    La doc Apple est très bien foutue, et plein de très bons articles pour expliquer ces concepts. Faut les lire !!
    http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
  • CeetixCeetix Membre
    05:09 modifié #174
    Oui c'est vrai, je lis plus la doc sur les différentes méthodes mais pas assez celles qui parles des principes fondamentaux. Je vais les lire ;)
  • CeetixCeetix Membre
    05:09 modifié #175
    Par contre c'est bizar, j'ai réimplémenter mes méthodes de mouvement de sommet. Ca marche bien mais mes arcs ne bougent plus.
    J'ai eu l'idée de faire une boucle qui regarde quel arc est connecté au sommet sélectionné et alors de lui attribuer les coordonnée de mon sommet bougeant mais si j'ai plusieurs arc je suis out .
  • schlumschlum Membre
    05:09 modifié #176
    Mais pourquoi les objets arcs n'ont pas des références aux objets sommets qui leurs donneraient immédiatement les coordonnées ?  ???
  • CeetixCeetix Membre
    05:09 modifié #177
    Bah si enfin je pense, vu que dans les parametre init d'un arc je mets le sommet d'arrivé et de départ. Pourtant rien ne bouge. J'ai encore du mal faire un truc...
  • CeetixCeetix Membre
    05:09 modifié #178
    Bon j'ai repris tout ça et j'ai modifié ma méthode d'initialisation d'Arc.

    <br />-(id)initWithPoids:(float)w depart:(Sommet *)d arrive:(Sommet *)a<br />{<br />	if((self = [super init]))<br />	{<br />		poids = w;<br />		<br />		dep.abs = d.abs;<br />		dep.ord = d.ord;<br />		<br />		<br />		ar.abs = a.abs;<br />		ar.ord = a.ord;<br />		<br />	}<br />	return self;<br />}<br />
    


    Pour le moment ca me parait correct . Mes ar et dep sont des variables d'instance.

    Mais ensuite dans ma méthode drawArc dans la classe NSView je fait :

    <br />-(void)drawArc:(Arc *)a<br />{<br />	NSBezierPath *tracer = [NSBezierPath bezierPath];<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; /* c&#39;est ici que ça à  l&#39;air de ne pas marcher */<br />	[tracer moveToPoint:(NSMakePoint(a.dep.abs,a.dep.ord))];<br /><br />.<br />.<br />.<br />
    


    En gros là  ca ne trace plus rien.
  • schlumschlum Membre
    05:09 modifié #179
    Mais, mais... Pourquoi dupliquer ces variables d'instances ?
    C'est pas ça qu'il faut faire, il faut avoir deux pointeurs vers Sommet et les conserver, c'est tout !

    Tu as déjà  fait du développement objet ?  :P
  • CeetixCeetix Membre
    05:09 modifié #180
    Bah non je débute en objet car en cours on voit le C. La POO c'est en 3eme année  :-\\ .
    Et comme j'e nai marre de dev en C en cours pour regarder a la console comment est mon graphe j'ai décider de me plonger sur ca en Objective-C et par la même occasion prendre un peu d'avance sur l'année prochaine.
    Pas de la tarte ...
  • schlumschlum Membre
    05:09 modifié #181
    Si tu gardes des références sur les sommets, tu n'as rien d'autre à  faire, les coordonnées que tu récupéreras via ces références seront toujours OK.
    Tandis que si tu copies les coordonnées, il faudra que tu les mettes à  jour à  chaque déplacement, et non seulement c'est dramatiquement complexe, mais en plus c'est pas optimisé du tout !
Connectez-vous ou Inscrivez-vous pour répondre.