[Débutant] Comprendre les systèmes de coordonnées dans les subviews
colas_
Membre
Bonjour !
J'ai créé une application où la fenêtre contient une NSScrollView mainScrollView.
J'ai aussi créé une vue customisée qui s'appelle MyCustomView et dont la hauteur est fixe, disons 300 pixels.
Si je demande à l'application de mettre une instance de MyCustomView dans mainScrollView
La vue MyCustomView apparaà®t bien dans ma fenêtre (d'ailleurs sans que j'aie à passer par une documentView pour mainScrollView ni à considérer les coordonnées).
Mon problème est le suivant : quand j'ajoute une seconde occurrence de MyCustomView, celle-ci vient se superposer à la première. J'aimerais quelle apparaisse en-dessous.
Vu que je n'ai pas utilisé les systèmes de coordonnées pour la première MyCustomView, je ne sais pas où les utiliser pour la seconde.
Pourriez-vous m'aider ?
Merci
PS : Je ne peux malheureusement pas utiliser les View-Based Table Views car je suis sous Max OS X 10.6
J'ai créé une application où la fenêtre contient une NSScrollView mainScrollView.
J'ai aussi créé une vue customisée qui s'appelle MyCustomView et dont la hauteur est fixe, disons 300 pixels.
Si je demande à l'application de mettre une instance de MyCustomView dans mainScrollView
<br />
[mainScrollView addSubview:myView];<br />
La vue MyCustomView apparaà®t bien dans ma fenêtre (d'ailleurs sans que j'aie à passer par une documentView pour mainScrollView ni à considérer les coordonnées).
Mon problème est le suivant : quand j'ajoute une seconde occurrence de MyCustomView, celle-ci vient se superposer à la première. J'aimerais quelle apparaisse en-dessous.
Vu que je n'ai pas utilisé les systèmes de coordonnées pour la première MyCustomView, je ne sais pas où les utiliser pour la seconde.
Pourriez-vous m'aider ?
Merci
PS : Je ne peux malheureusement pas utiliser les View-Based Table Views car je suis sous Max OS X 10.6
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Sinon, tu peux aussi faire sous IB, ce que je suppose que tu as fait avant ton addSubview, d'où le fait qu'elle sache déjà où se placer.
Après, sous iOS, mais ça doit être pareil plus ou moins sous Mac OSX, tu as diverses méthodes, comme bringSubviewToFront, etc.
Non ! J'ai juste dessiné ma vue dans IB, mais je ne lui pas donné plus d'indications (en tous cas je crois).
Mais ensuite, je veux faire apparaà®tre deux fois la même vue (ou plutôt deux instances de la classe MyCustomView) dans [font=helvetica, arial, sans-serif]mainScrollView. Mon problème c'est qu'elle se superposent.[/font]
[font=helvetica, arial, sans-serif]Si j'essaie de passer par une documentView, c'est pire rien n'apparaà®t !![/font]
[font=helvetica, arial, sans-serif]Mon code est alors : [/font][font=helvetica, arial, sans-serif] [/font]
Je ne sais pas comment utiliser les sytèmes de coordonnées.
Dans l'état actuel :
Sous iOS :
X = 0, c'est à gauche. Plus X grandit, plus tu vas vers la droite...
Y = 0, c'est en haut. Plus Y grandit, plus tu vas vers le bas.
Pour mieux comprendre, je te dirais de faire ses tests là :
Tu créées un projet avec un simple ViewController.
Dans viewcontroller.view, tu insères une view1 et tu settes sa frame.
Tu joues avec les paramètres du CGRect du setFrame pour comprendre un peu mieux...
Une fois compris, tu fais de même, mais tu mets maintenant un view2 dans la view1 (que tu mets par exemple à [view1 setFrame:CGRect(50,100,200,300)] et tu joues avec les même propriétés sur la view2.
Note que pour bien répérer avec quoi tu joues, je te conseilles de mettre une backgroundColor différente pour le viewcontroller.view, view1 et view2. Voire même de mettre l'alpha de view1 et view2 à 0.5.
Après, tu peux jouer avec les bounds aussi (setBounds).
Tu lui fais démarrer le "origin.y" de sa frame non pas à 0 (tout en haut) mais à 300.
Ou pour être plus dynamique et flexible, tu dis que l'origine Y de ta 2e myView2 doit avoir comme valeur... la valeur max du Y de ta 1ère vue myView1 (forcément si ta vue myView1 a son origine en y=0 et qu'elle fait 300 de haut ça va donner une origine y=300 pour myView2, mais au moins si un jour tu changes les tailles ou positions de myView1, la position de myView2 sera calculée (et pas en dur) et donc se calera correctement en dessous puisqu'elle calculera son origin.y en fonction du CGRectGetMaxY(myView1.frame)
Il fallait que j'utilise la méthode setFrameOrigin: de NSView.
Après il s'agit de compter !
Remarque : c'est galère (pour l'instant ça bugue encore chez moi) car il faut redimensionner la documentView de NSScrollView à mesure qu'on y ajoute des objets...
Malheureument ce n'est pas simple à faire, ci-joint une démo avec les classes perso qui me permettent de gérer des listes de views dans une tableView.
Je ne voudrais te décourager, mais comme tu es un débutant, à mon avis tu vas avoir du mal ...
J'ajoute mes vues de bas en haut, donc j'ai vraiment besoin d'une vue flipped pour mon documentView.
Mais, j'ai l'impression que quand j'augmente la hauteur, il ajoute la hauteur en plus "en haut".
Je ne sais pas si c'est très clair, c'est difficle à expliquer...
Voilà mon code :
J'ajoute 520 pixels en hauteur à chaque ajout.
La position initiale du premier objet myCustomView est (0,0) dans une vue flipped.
Mais, quand j'augmente la hauteur, il semble que ses coordonnées d'origine deviennent (0,520).
C'est pourquoi je dis "j'ai l'impression que quand j'augmente la hauteur, il ajoute la hauteur en plus "en haut"."
Merci de votre aide.
J'ai réussi mais les [font=helvetica, arial, sans-serif]objets [/font]myCustomView apparaissent dans le mauvais ordre... le premier est en bas, etc.
J'ai l'impression que la vue flipped ne réagit pas comme je l'attends.
C'est expliqué ici: http://www.poweredbytim.co.uk/programming/nsscrollview-top-left-pinning-and-isflipped/
La solution est donc de remplacer le documentView pas une vue perso flipped.
C'est exactement ce que je fais dans le fichier demo proposé plus haut.
C'est ce que j'ai fait pourtant...
Je vais regarder ça.
Ce n'est pas pratique cette gestion de flipped...
On aimerait bien une méthode pour NSView setFlipped...
D'un autre côté, c'est mathématiquement plus naturel que l'axe y pointe vers le haut.
Voilà quelques explications pour les curieux.
Pour comprendre, il faut savoir que les vues que j'ajoute à ma ScrollView sont créées via IB.
Plus précisément, j'ai une classe MyCustomView, qui hérite de NSViewController et qui s'initialise avec initWithNibName.
Par conséquent, lorsqu'un telle vue est créée, on ne lui donne pas vraiment de point d'origine.
De fait, son origine est fixée à (0,0).
Puis, quand j'augmente la hauteur du documentView qui contient cette vue :
Donc il semble que quand on ajoute une View dans préciser le point d'origine, la vue est semble "flottante".
Quand on augmente la taille, ses coordonnées changent !
Pour régler ce problème, j'ai essayé de faire de préciser l'origine de ma vue avec
où n est le nombre de vues que j'ai déjà ajouté.
Mais pour l'instant, ça ne marche pas...
Il semble que je doive indiquer que la vue n'est pas flottante... Des idées ?
J'ai réussi, en modifiant (un peu au hasard) les propriétés d'autosizing de ma CustomView qui contient tous les objets de MyCustomView. Au lieu de rester à distance fixe en haut à gauche, j'ai réglé sur en bas à gauche, et ça marche.
Commentaire bienvenu /smile.png' class='bbc_emoticon' alt=':)' />
Rien à faire et pourtant je ne me serais jamais cru un puriste, mais une MyCustomView devrait pour moi hériter d'une NSView. Un contrôleur est une autre bestiole. Par contre rien n'empêche une MyCustomView d'avoir une propriété myCustomViewController qui lui descendrait de NSViewController, à partir du moment où il est indispensable à ma MyCustomView ..
Pas tout à fait. La vue a la frame fixée dans le xib. Par contre, dans le cas d'une vue à la racine d'un XIB (ton cas), l'origine de la frame est forcément (0;0).
C'est faux. Comme on te l'a indiqué, l'origine du repère est dans le coin inférieur gauche de la vue, et l'axe des y pointe vers le haut. Ainsi, si tu agrandis la vue parente, la vue garde la même origine, relativement au coin inférieur gauche de la vue parente.
Non, la vue n'est pas flottante, elle conserve une position fixe par rapport à son origine.
Mais une des solutions au problème est de faire en sorte que la vue soit flipped, ainsi son système de coordonnées est inversé sur l'axe y, et pointe alors vers le bas, et l'origine du repère devient le coin supérieur gauche.
Cette solution t'a déjà été donnée plus haut: il faut créer une sous-classe de la vue parente qui renvoie YES dans la méthode -isFlipped.
Je suis d'accord avec toi, même si je viens juste de me lancer dans cocoa.
Il me semble que c'est impossible de créer une vue avec IB. On ne peut que créer une NSViewController.
Oui je sais ! C'est ce que je fais ! J'ai bien créé une nouvelle classe qui hérite de NSView et qui est flipped. Mais le problème n'est pas ceci. J'ai trouvé la solution du problème, c'est lié aux paramètres d'autoresizing dans IB.
M'enfin ?
Tu fais glisser une NSView générique et dans l'onglet où l'on définit sa classe tu lui met ta sous classe, il n'y a rien là de compliqué.
Pour définir ta vue dans IB tu peux même créer directement un xib pour qu'il soit une sous classe NSView (comme le dit Lame), tu pars de là pour lui ajouter un à un tous les controls que tu veux mettre et tu lui ajoutes un descendant de NSViewController pour les contrôler.
Comme ça chaque fois que IB reprend ton xib pour créer une vue elle aura son contrôleur et ses controls.
J'espère avoir été clair.
Et dans le code de ma nouvelle classe, est-ce que je dois faire référence au xib ?
Il sera appelé automatiquement au chargement de la vue. Quand la vue se dessine elle interroge sa classe pour savoir comment, d'où les méthodes isFlipped et autres willDraw: qui sont là pour être redéfinies..
Quand à définir une vue avec IB il me semble pour finir que la méthode de choix prévue par Cocoa est peut être:
1) Créer une nouvelle classe, sous classe de NSViewController, cocher la case "Créer le xib" et on a alors un xib avec une vue qu'on peut parsemer d'outlets qu'on reliera tous à la sous classe NSViewController (fileOwner) parce que c'est plus propre.
1 bis) On peut créer une sous classe de NSView si on veut avoir une vue qui ait les coordonnées inversées en retournant YES dans - (BOOL)isFlipped{ return YES;} ou tout autre modification qui concerne la vue (mais pas ses contrôles). Et en la définissant comme classe de la vue du ViewController
2) Créer une instance de viewController via initWithNibName:bundle: qui aura alors une vue principale qui sera celle composée dans IB avec les contrôles déclenchant des actions dans le contrôleur.
3) Ajouter cette vue à la vue courante.
Pour me mettre les idées au clair et te montrer j'ai monté un petit projet et je t'en ai fait un .zip mais je ne sais plus trop comment on les affiche dans un post alors je l'ai mis en lien sur le download de free [url="http://dl.free.fr/thT3bm1HF"]http://dl.free.fr/thT3bm1HF[/url]
hth
Disons qu'ils sont revenus à leurs premières amours... QuickDraw fonctionnait comme iOS. Merci NextStep.