Drag objet par objet

123457

Réponses

  • CeetixCeetix Membre
    03:23 modifié #182
    Qu'appelles-tu références ?
    Par exemple là  je l'ai modifier et j'ai fait ça :

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


    x1,x2,y1,y2,poids étant mes variables d'instance.
    C'est pas encore ça ?
    Là  ca trace bien mais si je bouge un sommet il n'y a pas d'actualisation.
  • schlumschlum Membre
    03:23 modifié #183
    Non, c'est pas ça du tout...
    -(id)initWithPoids:(float)w depart:(Sommet *)d arrive:(Sommet *)a{<br />	if((self = [super init]))<br />	{<br />		poids = w;<br />		<br />		dep = d;<br />		ar = a;<br />		<br />	}<br />	return self;<br />}
    
  • schlumschlum Membre
    avril 2009 modifié #184
    Ou alors, une référence " forte " ce qui est plus habituel avec Cocoa :


    -(id)initWithPoids:(float)w depart:(Sommet *)d arrive:(Sommet *)a{<br />&nbsp;&nbsp;&nbsp;if((self = [super init]))<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poids = w;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dep = [d retain];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ar = [a retain];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;return self;<br />}<br /><br /><br />- (void)dealloc<br />{<br />&nbsp;&nbsp;&nbsp;[dep&nbsp;release];<br />&nbsp;&nbsp;&nbsp;[ar&nbsp;release];<br />&nbsp;&nbsp;&nbsp;[super dealloc];<br />}
    
  • AliGatorAliGator Membre, Modérateur
    03:23 modifié #185
    Vois ça comme des "alias" si ça peut t'aider, comme dans le Finder.

    Quand schlum te parle de "il ne faut pas copier les variables d'instances, mais juste pointer dessus", tu peux comparer, si tu avais par exemple un document texte sur ton disque dur, à  "quand tu as besoin d'avoir aussi une référence à  ce fichier autre part, dans un autre dossier, il ne faut pas faire une copie de ce fichier, mais plutôt un alias".

    En effet, pour reprendre la comparaison, si tu fais une copie de ton fichier A à  un autre emplacement, ce seront des fichiers distincts : si tu modifies l'un, cela ne va pas modifier l'autre, qui a sa vie indépendante.
    Alors que si tu fais un alias, ça ne fait que "pointer" vers l'original. Si tu modifies l'original, bah quand tu vas double-cliquer sur l'alias qui est à  l'autre endroit ça va ouvrir l'unique document, celui-la même que tu as modifié.

    Si ça peut t'aider à  y voir plus clair...
  • CeetixCeetix Membre
    03:23 modifié #186
    Oui en effet j'y vois plus claire avec cette image d'alias. Et quelle est la différence entre la méthode "forte" de Schlum et celle qu'il propose avant?
  • schlumschlum Membre
    03:23 modifié #187
    dans 1238698394:

    Oui en effet j'y vois plus claire avec cette image d'alias. Et quelle est la différence entre la méthode "forte" de Schlum et celle qu'il propose avant?


    La référence " forte " est plus Cocoa, et garantit que les références seront toujours valables (c'est comme si on mettait une laisse aux instances tant qu'on en a besoin).
    La référence " faible ", c'est plus C++ et demande une gestion plus consciencieuse de la mémoire.
  • CeetixCeetix Membre
    03:23 modifié #188
    D'accord mais dans ton second code je vois pas comment dans le dealloc d et a sont reconnus vu qu'ils ne sont plus dans le init.
  • schlumschlum Membre
    03:23 modifié #189
    Ah ça... C'est rien, une p'tite erreur d'inattention maintenant corrigée  :P
    Effectivement, ça ne passerait pas la compilation.
  • CeetixCeetix Membre
    03:23 modifié #190
    Ok je comprends mieux ^^.
    J'espere qu'en pratiquant ça va rentrer...
  • CeetixCeetix Membre
    03:23 modifié #191
    J'ai envie de pouvoir sauvegarder le model d'un graphe construit et de pouvoir le recharger par la suite. Par quel moyen il faudrait passer pour pouvoir sauvegarder tout le graphe ?
    Un fichier .txt ? XML ? Autres moyens ?
  • schlumschlum Membre
    03:23 modifié #192
    NSKeyedArchiver
  • CeetixCeetix Membre
    03:23 modifié #193
    Bon j'avance dans mes algos et là  je bloque sur un truc tout bête je pense.
    J'ai besoin de la matrice de continuité du graphe.

    Exemple :

    J'ai trois noeuds "A", "B" et "C" .

    A -> B  poids 1.
    A -> C  poids 3.
    C -> B  poids 2.


    La matrice associée serait :

    013
    000
    020

    Pour moi c'est juste une histoire de tableau.
    Je parcours mon premier tableau qui contient mes sommets. En double boucle je parcours mon tableau d'arcs. Pour chaque sommet je parcours ce tableau d'arcs en regardant si le nom de mon sommet correspond au nom "départ" de mon arc. SI c'est le cas je marque le poids sinon je marque 0.

    J'ai fais comme ça .

    <br />-(void)matrice<br />{<br />	<br />	/* tableau à  double entrée */<br />	int **tab= NULL;<br />	tab = (int **)malloc([tableauSommets count]*sizeof(int*));<br /><br />	<br />	for( int i=0 ; i&lt;[tableauSommets count]; i ++)<br />	{<br />		tab[i] = (int*)malloc([tableauArcs count]*sizeof(int));<br />		Sommet *s = [tableauSommets objectAtIndex:i];<br />		<br />		for(int j = 0; j&lt;[tableauArcs count]; j ++)<br />		{<br />			Arc *a = [tableauArcs objectAtIndex:j];<br />			<br />			/* si je suis sur la diagonale c&#39;est un sommet pointant sur lui meme donc pas d&#39;arc possible */<br />			if(i == j)<br />			{<br />				tab[i][j] = 0;<br />			}<br />			<br />			/* sinon si mon nom de sommet est le même que le nom de départ d&#39;un arc*/<br />			else if([s.nom isEqualToString:a.de]) <br />			{<br />				tab[i][j] = a.poids;<br />			}<br />			<br />			/* si ce n&#39;est pas le cas je mets 0 */<br />			else<br />			{<br />				tab[i][j] = 0;<br /><br />			}<br />				<br />			<br />		}<br /><br />	}<br />}<br />
    


    Vous voyez un truc qui va pas?
  • AliGatorAliGator Membre, Modérateur
    03:23 modifié #194
    s.nom est le nom de ton sommet
    a.de est j'imagine une variable de type Sommet* qui pointe vers le sommet de départ... donc ce n'est pas une NSString.

    De plus tant qu'à  faire plutôt que de comparer les noms des sommets, autant comparer les sommets eux-mêmes : [tt]if (a.de == s)[/tt] ou [tt]if ([a.de isEqualTo:s])[/tt].
  • schlumschlum Membre
    03:23 modifié #195
    Je ne vois pas pourquoi tu parcours les sommets... Tu ne devrais avoir que les arcs à  parcourir !
  • CeetixCeetix Membre
    03:23 modifié #196
    Si a.de est de type sommet. C'est une variable de ma classe Arc qui récupère le nom de sommet de départ rentré comme paramètre d'initialisation de mon arc.

    <br />-(id)initWithPoids:(float)w depart:(Sommet *)dep arrive:(Sommet *)ar color:(NSColor *)c andOrient:(BOOL)o<br />{<br />	if((self = [super init]))<br />	{<br />		poids = w;<br />		<br />		d = [dep retain];<br />		a = [ar retain];<br />		<br />		de = [NSString stringWithString:dep.nom];<br />		vers = [NSString stringWithString:ar.nom];<br />		<br />		couleur = c;<br />		orient = o;<br />	}<br />	return self;<br />}<br /><br />
    


    Hum en effet pour ta remarque Shlum ... mais il me faudrait une sorte d'étiquette interne de type entiere pour chaque sommet pour connaitre sa position d'ajout et donc se place dans la matrice. Non?
  • schlumschlum Membre
    03:23 modifié #197
    dans 1238858647:

    Hum en effet pour ta remarque Shlum ... mais il me faudrait une sorte d'étiquette interne de type entiere pour chaque sommet pour connaitre sa position d'ajout et donc se place dans la matrice. Non?

    Oui, bien sûr... La seule chose qui m'étonne c'est qu'elle n'y soit pas déjà   :P
  • AliGatorAliGator Membre, Modérateur
    03:23 modifié #198
    Et pourquoi copier dans "de" et "vers" le nom de tes sommets ?
    Tu reproduis ici l'erreur que tu avais faite avec la position de tes sommets que tu stockais dans les arcs alors que tu peux les avoir dans tes sommets.

    Si tu veux le nom du sommet de départ d'un arc, il faut faire monarc.d.nom (et pas avoir une variable de et faire monarc.de) : en effet, si après coup tu changes le nom de ton sommet dans ton instance d'un Sommet*, tous les arcs qui ont se sommet en tant que point de départ (ou d'arrivée) garderont pourtant dans ta variable "de" (ou "vers") l'ancien nom du sommet !

    A la limite si tu veux vraiment garder "de" et "vers", fais-en propriétés readonly dont tu implémentes l'accesseur pour qu'il retourne le nom du sommet... mais calculé en temps réel, et non stocké en dur, pour que s'il change dans le Sommet*, ça soit bien le nouveau que l'on retourne.
    @interface Arc : ...<br />{<br />&nbsp;  ...<br />&nbsp;  // pas besoin de variable &quot;NSString* de;&quot;<br />&nbsp;  // ni de &quot;NSString* vers;&quot; ici !!<br />}<br />// ici on déclare qu&#39;on peut utiliser &quot;monarc.de&quot; comme si c&#39;était une property<br />// mais on ne va pas l&#39;associer à  une variable d&#39;instance comme tu le fais toi<br />@property(nonatomic, readonly) NSString* de;<br />@property(nonatomic, readonly) NSString* vers;<br />@end<br /><br />@implementation Arc<br />// ici du coup on va pas laisser &quot;@synthesize de, vers;&quot; qui générerait l&#39;accesseur de ces variables<br />// en utilisant la variable d&#39;instance, puisqu&#39;on ne fait plus avec ça<br />// à  la place, on définit nous-même l&#39;accesseur associé à  la @property :<br />-(NSString*)de { return d.nom; } // on retourne le nom du sommet de départ, calculé en temps réel<br />-(NSString*)vers { return a.nom; } // pareil pour le sommet d&#39;arrivée<br />@end
    
  • CeetixCeetix Membre
    03:23 modifié #199
    dans 1238859755:

    dans 1238858647:

    Hum en effet pour ta remarque Shlum ... mais il me faudrait une sorte d'étiquette interne de type entiere pour chaque sommet pour connaitre sa position d'ajout et donc se place dans la matrice. Non?

    Oui, bien sûr... La seule chose qui m'étonne c'est qu'elle n'y soit pas déjà   :P


    Oui bon rooo ^^.
    Merci Ali je crois que je vais faire monArc.d.nom pour pas avoir 36000 variables.
  • CeetixCeetix Membre
    avril 2009 modifié #200
    Bon je comprends le principe.

    J'ai fais ça et ça a l'air de marcher ^^

    <br />-(void)matrice<br />{<br />	int i,j,k;<br />	int **tab= NULL;<br />	<br />	<br />	/* initialisation à  0 */<br />	tab = (int **)malloc([tableauSommets count]*sizeof(int*));<br />	<br />	for(i=0 ; i&lt;[tableauSommets count]; i ++)<br />	{<br />		tab[i] = (int*)malloc([tableauSommets count]*sizeof(int));<br />		<br />		for(j = 0; j&lt;[tableauSommets count]; j ++)<br />		{<br />			tab[i][j] = 0;<br />		}<br />	}<br />	<br />	<br />	/* Remplissage */<br />	for(i=0;i&lt;[tableauArcs count];i++)<br />	{<br />		Arc *a = [tableauArcs objectAtIndex:i];<br />		j = a.d.e; // etiquette du premier sommet<br />		k = a.a.e; // etiquette du second<br />		tab[j][k] = a.poids;<br /><br />	}<br />	<br />	/* Affichage */<br />	for(i=0; i&lt;[tableauSommets count];i++)<br />	{<br />		for(j=0;j&lt;[tableauSommets count];j++)<br />		{<br />			printf(&quot;%d&quot;,tab[i][j]);<br />		}<br />		printf(&quot;&#092;n&quot;);<br />	}<br />	<br />	free(&amp;tab);<br />	<br />}<br />
    
  • CeetixCeetix Membre
    03:23 modifié #201
    J'ai commencé à  essayer NSKeyedArchiver.
    Je tatonne un peu.
    SI j'ai bien compris il faut que je transforme mes objets (Sommets et Arcs) en code binaire.
    J'ai modifier un code et au départ j'ai ça :

    <br />- (void) encodeWithCoder: (NSCoder *)coder { <br /><br />[coder encodeObject:tableauSommets forKey:@&quot;sommets&quot;]; <br />[coder encodeObject:tableauArcs forKey:@&quot;arcs&quot;]; <br /><br />} <br />
    

    C'est un début correct?
  • schlumschlum Membre
    03:23 modifié #202
    Oui, ça c'est pour rendre ta classe Data conforme au protocole <NSCoding> (il manque la partie decoding...)

    Mais tu peux faire plus simple sans...

    Encoding
    - Créer une instance NSMutableData
    - Créer un NSKeyedArchiver
    - (id)initForWritingWithMutableData:(NSMutableData *)data
    

    - Lui envoyer ce qu'on veut encoder
    - (void)encodeObject:(id)objv forKey:(NSString *)key
    

    - Terminer l'encoding
    - (void)finishEncoding
    

    - à‰crire son objet NSData dans un fichier
    - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
    


    Decoding
    - Initialiser un NSData avec le fichier
    + (id)dataWithContentsOfFile:(NSString *)path
    

    - Initialiser un NSKeyedUnarchiver avec
    - (id)initForReadingWithData:(NSData *)data
    

    - Récupérer ses objets
    - (id)decodeObjectForKey:(NSString *)key
    



    Sinon, en rendant son objet Data conforme <NSCoding> :
    + (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path
    

    + (id)unarchiveObjectWithFile:(NSString *)path
    
  • CeetixCeetix Membre
    03:23 modifié #203
    Pour ta méthode
    - (void)encodeObject:(id)objv forKey:(NSString *)key
    

    L'id a envoyer est un sommet de mon tableau de sommet?
    Par contre pour :

    - (id)initForWritingWithMutableData:(NSMutableData *)data
    

    data correspond à  quoi?

    Et ces méthodes je dois les implétanter dans ma NSView, c'est bien ça?
  • schlumschlum Membre
    03:23 modifié #204
    Non, dans les fonctions qui vont enregistrer / ouvrir un fichier...
    Le "initForWritingWithMutableData", c'est juste un "init" avec un NSMutableData vide, un constructeur quoi  ???
  • CeetixCeetix Membre
    03:23 modifié #205
    Ok donc je dois créer une nouvelle classe de type NSObject?
    Sinon dans quel format de fichier ca va enregistrer? C'est à  moi de choisir?
  • schlumschlum Membre
    03:23 modifié #206
    dans 1238930286:

    Ok donc je dois créer une nouvelle classe de type NSObject?
    Sinon dans quel format de fichier ca va enregistrer? C'est à  moi de choisir?


    C'est du XML binaire (compressé)...
    Si tu veux un autre format, alors il va falloir écrire toi même ta classe de sérialisation / désérialisation.
  • CeetixCeetix Membre
    03:23 modifié #207
    Ca ira lol... C'est juste pour pas me faire *** à  chaque run à  ajouter mes sommets. Perte de temps ...
  • CeetixCeetix Membre
    03:23 modifié #208
    Bon ca marche super et mon dijkstra aussi ^^.
    J'ai pensé pouvoir supprimé les sommet un à  un en appuyant sur un bouton d'édition qui affiche sur chaque sommet une petite croix (un peu comme sur l'iphone). Pour ca je dois rajouter un parametre dans ma fonction d'init de sommet ou bien créer un tableau de NSView ? J'aurai penché pour la premiere solution et ainsi en fonction d'un état BOOL dessiner ou non l'image dans mon drawRect .

    Qu'en pensez-vous?
  • schlumschlum Membre
    03:23 modifié #209
    Ni l'un ni l'autre...
    Soit c'est une propriété qui s'applique à  un seul élément, soit à  tous, mais il serait illogique de l'avoir sur seulement un sous-ensemble de taille > 1.

    À partir de là , c'est une propriété globale.
  • CeetixCeetix Membre
    03:23 modifié #210
    Et donc a chaques fois que je dessine un sommet selon un etat je dessine aussi mon image a coté du sommet?
  • AliGatorAliGator Membre, Modérateur
    03:23 modifié #211
    La solution du flag me semble mieux... mais en effet à  ne mettre que sur ta UIView (appellons-là  GraphView) qui te sert à  dessiner ton graphe (celle pour qui le drawRect consiste essentuellement à  appeller [self drawSommet:...] sur chaque sommet et [self drawArc:...] sur chaque arc).

    Du coup au moment de dessiner tes sommets, si le "editable" de ta GraphView est à  YES tu dessines la petite croix à  côté du sommet quand tu le dessines, sinon non. Et de même quand tu détectes les clics dans ta GraphView, si editable est à  YES tu fais le traitement adéquat (détecter si le clic est sur une zone où il y a une petite croix, si oui supprimer le sommet correspondant du graphe (et ses arcs associés) et redessiner le graphe...
    Sinon bah pourquoi pas permettre d'autres types d'édition, par exemple un clic sur le nom du sommet pour modifier son nom, ou un drag du sommet pour le déplacer dans le dessin... et puis si le clic est dans le vide bah l'ignorer.
Connectez-vous ou Inscrivez-vous pour répondre.