Créer une 2e fenetre : problème de liens
Fred20
Membre
Bonjour
Décidément, je ne suis toujours pas familié avec les liens.
Mon projet vise à créer et afficher une 2e fenêtre ( trucs) à partir de ma première venant de MyDocument. Une fois cette 2e fenêtre affichée, je voudrais utiliser son bouton afin que la console m'affiche que j'ai bien appuyé sur ce bouton (je sais, ce n'est pas très original mais c'est pour continuer d'apprendre !).
Cependant, je pense que mes liens sont erronés puisque ça ne marche pas.
Est ce que quelqu'un pourrait se plonger dans mon petit code afin d'expliquer au débutant que je suis ce que j'aurais dû faire /huh.gif' class='bbc_emoticon' alt='???' />
Merci d'avance
Décidément, je ne suis toujours pas familié avec les liens.
Mon projet vise à créer et afficher une 2e fenêtre ( trucs) à partir de ma première venant de MyDocument. Une fois cette 2e fenêtre affichée, je voudrais utiliser son bouton afin que la console m'affiche que j'ai bien appuyé sur ce bouton (je sais, ce n'est pas très original mais c'est pour continuer d'apprendre !).
Cependant, je pense que mes liens sont erronés puisque ça ne marche pas.
Est ce que quelqu'un pourrait se plonger dans mon petit code afin d'expliquer au débutant que je suis ce que j'aurais dû faire /huh.gif' class='bbc_emoticon' alt='???' />
Merci d'avance
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Dans ton projet, tu n'as connecté le "selector" du bouton à rien du tout. Aucun message ne peut donc être envoyé.
Tu as créé une classe FenetreSup (qui soit en passant est plutot de la couche controller que de la couche View : je l'aurais appelée autrement cette classe, du genre FenetreSupController). Mais nul part tu ne crées d''instance de cette classe !
Donc, deux solutions. La plus simple est de créer une instance dans interface builder, puis de connecter le "selector" du bouton à l'action clickBouton;.
L'autre est de créer une instance de la classe dans la méthode windowControllerDidLoadNib, puis d'indiquer la cible et le selector (en considérant que tu as un outlet vers le bouton dans MyDoc
J'ai testé ta 2e solution qui fonctionne (je n'y aurais jamais pensé!). Mais pour ta 1ere, elle me pose problème : comment tu crées une instance dans IB ?
En fait, l'objectif de cet exercice est de me rapprocher de Qt dans ce sens où MyDocument va s'occuper de ma fenêtre principale et que FenetreSup va s'occuper de la fenêtre "trucs". Donc toutes les méthodes qui concerneront "trucs" seront dans ma classe FenetreSup et toutes les méthodes qui concerneront ma fenêtre de démarrage seront dans MyDocument, sachant que c'est Mydocument qui dispatchera vers les autres fenetres via menus ou boutons.
De ce fait, ta 2e solution ne rentre pas dans ma démarche puisque finalement, c'est MyDocument qui va "gérer" (au moins au début) le bouton de ma fenêtre "trucs".
En fait, j'avais fait un outlet du bouton de cette 2e fenêtre et tiré un lien vers file's owner et ça marchait mais la méthode correspondant devait bien sur être dans MyDocument, ce qui ne m'allait pas.
Peut être que ton explication sur ma 1ere question répondra à ma 2e ?
Merci et à bientôt
Une méthode pour l'exemple :
et pour la fenêtre :
N'hésite pas à jouer avec les NSNotification si relier les classes AppDelegate et tonNSWindowController semble difficile.
Pour créer une instance dans IB, tu glisses un cube bleu (NSObject) , et tu précises la classe FenetreSup dans l'inspecteur. Lors du désarchivage du XIB, l'instance sera créée. Ainsi, tu crées l'outlet du bouton dans la classe fenetreSup, MyDocument n'a pas à gérer ça et à maintenir des outlets vers les vues ou autre de cette fenêtre.
Dans IB, tu indiques au FilesOwner qu'il est une instance de monNSWindowController. (sa classe dans sa fiche identité est ...) Alors les IBOutlet et IBActions apparaissent et tu "câbles" (pour parler comme un mec du son...)
Merci à toi aussi Mick. Je vais essayé ton principe sachant que je suis encore réfractaire à l'utilisation de ce cube bleu qui n'a pas encore beaucoup de signification pour moi (bien que je viens d'essayer ta solution et ça me paraà®t pas si compliqué que ça).
Ceci étant, j'ai réfléchi à ta 2e solution afin de créer un lien. Ainsi, tu me disais que mon bouton était nul part et pour cause, je ne voyais pas où le lier. Mais dans ton exemple tu fixes par programmation une cible du bouton vers fsc (qui est en fait ma fenêtre). Du coup j'ai essayé de lier ce bouton à ma fenêtre "trucs" (et non pas à window(trucs)) et ça marche.
Cependant, est ce que c'est probant ou pas ??
Merci d'avance
je ne crois pas qu'il ait subclassé nswindowcontroller, mais juste créé une sublass nsobject. le owner est donc MyDocument. Il veut un objet qui gère son autre fenetre, mais qui est dans le mm xib. donc il faut bien créer une instance de son controleur dans le xib, spécifier sa classe et connecter l'outlet non ?
La solution propre serait de créer une subclass de nswindowcontroller (et pas NSObject), en créer une instance lors du click, et séparer les deux fenetre dans des XIB différents.
Voici le projet modifié en pj.
EDIT : oublié un release sur leController après ajout dans le dictionnaire. (le dictionaire le retient)
J'ai fais comme tu as dis :
J'ai d'abord créé un nouveau projet, donc un MyDocument que j'ai installé comme avant.
J'ai créé une nouvelle fenetre (j'avais le choix entre Application XIB, empty XIB, main menu XIB, view XIB et Window XIB, j'ai supposé que la dernière option était la bonne et je l'ai appelé FenetreSup.)
J'ai créé une nouvelle classe FenetreSup (.h et m)
J'ai ouvert le FenetreSup.xib et créé un bouton avec un label pour afficher "coucou" (tant qu'à faire !).
Cependant, j'ai un pbl à ce stade puisque je ne peux rien connecter.
En fait, qu'appelles tu
"// J'ai indiqué la classe de File's Owner pour que IB prenne connaissance des actions/outlets de la classe FenetreSup
//J'ai connecté l'action du bouton a clickBouton, et SURTOUT, j'ai connecte l'outlet de File's owner "window" à la fenetre."
merci d'avance
Maintenant ça marche
Par contre, si je veux accéder à des méthodes ou objet de MyDocument depuis FenetreSup, comme je fais puisque c'est 2 xib différents?
Le plus simple est de créer une variable d'instance MyDocument *leDoc dans ton controleur de fenetre (avec ses accesseurs (retain) : tu peux utiliser property (retain) / synthetize : le retain permet d'etre sûr que l'instance de MyDocument sera toujours là tant que le controleur FenetreSup sera là ... Il ne faut pas oublier le release dans le dealloc)
Lorsque tu crées l'instance de ce controleur (au moment du click), tu lui passes le message suivant juste après son initialisation :
[leControleur setLeDoc:self];
ou si tu as utilisé les property : leControleur.leDoc=self;
Ainsi, si ton controleur a besoin d'acceder aux méthodes de MyDoc ou a ses variables d'instance, il le poura puisque la variable leDoc pointera sur cette instance de MyDoc.
Par contre, dans le XIB, tu n'as pas normalement à avoir besoin des actions de MyDocument. Le but du controleur est justement de gérer la fenetre supérieure, pas le reste... A toi d'organiser tes objets pour que chacun ait son rôle.
Si j'arrive à le reproduire, ça sera exactement ce qu'il me faut
A+ et merci
Je te tiens au courant
Bon, j'ai essayé ta solution.
J'ai fais un doc = [[MyDocument alloc]init]; dans un -(void) awakeFromNib car dans init de FenetreSup (je suppose que tu entendais par controleur de la fenetre cela), ça ne passait pas.
Cependant, je n'ai pas eu besoin des property/synthesize pour accéder aux méthodes de MyDocument. Ce qui me laisse à penser que je n'ai pas réalisé ta proposition !!.
De plus, je voulais récupérer la taille de ma fenêtre principale via une méthode dans MyDocument :
NSRect rect = [[self windowForSheet] frame];
mais qui ne me donne pas le bon résultat (méthode qui du reste, fonctionne puisque lorsque je la place au début , lorsque je clique pour afficher ma 2e fenetre, ça marche. Donc je suppose que j'ai encore un problème de pointeur)
Que c'est il passé ?
NNOOONN. L'instance de MyDocument est créée lors du désarchivage de MyDocument ! tu n'as absolument pas à en créer une autre !
Tu as juste à déclarer une variable d'instance. Bon je te fais un projet vite fait en PJ
Je regarde ça et je te tiens au courant
A+
Je n'ai pas compris ton exemple. Comment je peux, de FenetreSupController, accéder à MyDocument (connaitre la taille de la fenetre par exemple- accéder à ses méthode ...)?? Je ne vois pas de variable d'instance MyDocument *monDoc comme tu me le suggérais avant. ?
Topo sur le delegate : en fait, l'idée du delegate en gros est de pouvoir faire une classe d'objets destinés à gérer un truc, mais qui est susceptible d'envoyer des messages à un autre objet qui est son "délégué". A priori, n'importe quel objet peut être le délégué d'un autre, d'où "id". En général, on définit alors un "protocole" : un ensemble de méthodes auxquelles est sensé pouvoir répondre le délégué de ton controleur. Certaines peuvent être obligatoires, d'autres facultatives.
Par exemple, tu peux définir n'importe quel contrôleur de ton cru comme delegué d'une NSTableView : ce délégué doit être conforme au NSTableViewDelegate protocol, c'est à dire qu'il doit implémenter les méthodes du genre tableView:heightForRow: ou selectionShouldChangeInTableVIew: ... (cf doc) Ces méthodes ne sont ici pas obligatoires : certaines peuvent être implémentées et pas d'autres. Les objets de la classe NSTableView envoient des messages à leur délégué (si celui-ci n'est pas nil) pour lui demander des choses : la tableView teste si le délégué réponds à la méthode, et si c'est le cas, appelle cette méthode en lui passant un certain nombre de paramètres (en général, la tableView elle-même, et d'autres choses nécessaires au delegate pour pouvoir "répondre à la question")
Pour revenir à ton problème :
Juste après la création dans la méthode ouvreFenetre:, j'ai passé le message : leControleur.delegate=self. C'est ici que j'assigne le pointeur "delegate" du controleur de ta fenetreSup à l'adresse de l'instance de MyDoc.
Du coup, si tu a besoin d'accéder, depuis le controleur FenetreSupController, à des infos genre la taille de la fenetre principale (mais pourquoi en aurais-tu besoin ? ) Voici une méthode (de la classe FenetreSupController) permettant de retourner la taille de la fenetre principale. Pour test, dans la méthode click:, j'ai mis un log pour voir. cf code ci-dessous.
En fait, cette taille de fenetre me permet d'avoir ma 2e fenetre à la taille de la 1ere afin simplement de la superposer.
Sinon pour obtenir ces données, j'ai fais NSRect rect = [[delegate windowForSheet] frame]; dans la méthode de FenetreSupControler (deClick).
En effet, puisque delegate est le pointeur de MyDocument (enfin je crois) n'est-ce pas plus simple ?(d'autant que ça marche)
Sinon, au lieu de créer une variable d'instance delegate etc, pourquoi ne pas envoyer le message de redimensionnement de la fenêtreSup au moment de la création du contrôleur FenetreSupController ?
(pour le "design" de l'appli, ce serait mieux). Est-ce que ton contrôleur de fenêtre a réellement besoin d'un délégué (doit-il envoyer des messages à ce délégué après sa création pour obtenir des informations auprès de , ou informer, ce délégué ? Si oui, Ok pour le délégué, sinon, inutile)
Pas besoin de delegate pour ça.
En tout cas, tu me sors une énorme épine du pied. Merci encore
J'aurais sans doute un dernier service à te demander. connais tu un tuto qui traite (en français) de l'écriture et lecture sur disque. Je cherche à lire (et écrire) des fichiers et surtout, importer un dossier d'images du disque ds un tableau, puis transférer ce dossier dans un autre endroit sur mon disque.
A+
A+
Je commence à créer mon application en essayant de mettre en oeuvre tous ces conseils et pour l'instant ça marche !
J'ai cependant besoin d'utiliser une classe Data dont les variables devront être lues de 2 xib différents (MyDocument et M_Echelle). Or la solution de faire un outlet pour instancier Data ne peux pas fonctionner sous ce système.
D'où ma question: comment récupérer le pointeur de Data sous MyDocument ET sous M_Echelle ??
Merci d'avance
Et bien, comme à l'habitude, tu crées une variable d'instance avec ses accesseurs dans M_Echelle, et à la création du controleur M_Echelle (je suppose dans une méthode de MyDocument) tu envoies le message : monM_Echelle.data=data
Après, je ne sais pas comment tu as organisé tes objets.
J'essaye
Au sein de ton projet, tu ajoutes un fichier Cocoa (h+m) dérivant de NSWindowController. (New > New file > Objectiv-C class ...), puis par le même chemin > User Interface > Window effectivement.
Dans ce fichier xib nouvellement créé, tu cliques sur l'icône Files owner à gauche et tu lui attribues dans l'onglet "class" de sa fiche d'identité la classe dérivant de NSWindowController. A partir de là , tu crées ce que tu veux sur ta fenêtre, et tu relies aux IBActions et IBOutlets que tu veux dans ta classe.
Tu n'oublies pas dans ta classe principale #import "taClasse.h", tu crées au démarrage une instance de cette classe, et tu utilises le code donné plus haut pour que la fenêtre s'ouvre.
Je parlais aussi des NSNotifications pour connecter les actions au besoin à où tu veux dans ton programme.
Ca marche aussi.
Me voici de retour de vacances !
Je continue à avancer ds mon projet et je veux ouvrir une autre fenêtre à partir de ma fenêtre principale. Mais j'ai quelques petites questions concernant ton dernier exemple.
J'ai tout d'abord "épuré" ton code pour mieux le comprendre et j'obtiens pour ouvrir ma fenêtre M_Echelle :
sachant que lesControleursDeFenetre est un NSMutableDictionary
Cependant, je n'ai pas compris le rôle de lesControleursDeFenetre justement. Je ne le réutilise nul part ailleurs. Je pense que c'est en cas de nombreuses fenêtres afin de les retrouver rapidement ? Cependant, si je l'enlève, ma fenêtre M_Echelle s'affiche mais se referme immédiatement ? Peux tu me donner des info à ce sujet ?
D'autre part, j'ai procédé de la même manière pour ouvrir une autre fenêtre (M_PtDigit) avec ce code suivant :
Ma fenêtre apparaà®t bien quand je clique sur le bouton adéquat mais est grisée (il faut que je clique dessus pour avoir la main) et la modif de taille n'est pas prise en compte.
Aurais je oublié quelque chose ?
Merci d'avance
Je viens de trouver le pbl : j'ai oublié de relier le files owner à la fenetre .Maintenant c'est OK
Merci pour tout
Ce dictionnaire permet de maintenir la liste de tous les contrôleurs de fenêtre et de les retenir aussi du point de vue de la gestion mémoire. Ainsi, l'instance de MyDocument a accès à tous ces contrôleurs. C'est une structure assez classique en fait : un contrôleur "principal" qui a pour rôle de créer les contrôleurs de fenêtre/de vue lorsque l'utilisateur en fait la demande. Cela évite d'avoir un immense contrôleur qui gère tout, et de charger l'intégralit' de l'interface graphique au lancement de l'appli.
bon courage pour la reprise !