NSTextField et Delegate
skimpy
Membre
Bonjour,
J'avais laissé Cocoa pendant une période et je viens de m'y remettre. J'ai donc repris mon livre "Cocoa par la pratique - 2ème édition" et je refais les exercices proposés.
Dans le chapitre 4, l'auteur propose de faire un programme composé :
- de 2 NSTextField
- d'un bouton "Compter les lettres"
Le but du programme et de saisir du texte, d'appuyer sur le bouton et d'afficher : "la chaine xxxx contient x caractères".
Jusque là , pas trop de difficulté (j'ai créé mon interface avec mes outlets/actions et j'ai créé un contrôleur AppController). Et puis je me suis dit qu'il serait intéressant de désactiver le bouton quand le champ de saisi est vide.
Dans un 1er temps, j'avais fait en sorte que AppController soit le delegate pour le champ de saisi. J'ai donc tiré dans IB la connexion delegate et dans le code d'AppController, rajouté dans le awakeFromNib la ligne [texteSaisi setDelegate:self] et puis implémenté les 2 méthodes suivantes (avec juste un NSLog) :
- (void)textDidBeginEditing:(NSNotification *)aNotification;
- (void)textDidChange:(NSNotification *)aNotification;
mais rien n'apparaissait dans la console.
En regardant la documentation de NSTextField, j'ai vu qu'il fallait en fait surcharger NSTextField. J'ai créé une classe SKTextField dans laquelle j'ai implémenté les méthodes.
Les messages apparaissent bien dans la console quand je saisis du texte.
Le problème où je bute est le suivant : comment activer le bouton dans le delegate (celui-ci n'est pas connu à ce niveau là [ibBtnCount setEnabled:YES]) ?
Merci.
J'avais laissé Cocoa pendant une période et je viens de m'y remettre. J'ai donc repris mon livre "Cocoa par la pratique - 2ème édition" et je refais les exercices proposés.
Dans le chapitre 4, l'auteur propose de faire un programme composé :
- de 2 NSTextField
- d'un bouton "Compter les lettres"
Le but du programme et de saisir du texte, d'appuyer sur le bouton et d'afficher : "la chaine xxxx contient x caractères".
Jusque là , pas trop de difficulté (j'ai créé mon interface avec mes outlets/actions et j'ai créé un contrôleur AppController). Et puis je me suis dit qu'il serait intéressant de désactiver le bouton quand le champ de saisi est vide.
Dans un 1er temps, j'avais fait en sorte que AppController soit le delegate pour le champ de saisi. J'ai donc tiré dans IB la connexion delegate et dans le code d'AppController, rajouté dans le awakeFromNib la ligne [texteSaisi setDelegate:self] et puis implémenté les 2 méthodes suivantes (avec juste un NSLog) :
- (void)textDidBeginEditing:(NSNotification *)aNotification;
- (void)textDidChange:(NSNotification *)aNotification;
mais rien n'apparaissait dans la console.
En regardant la documentation de NSTextField, j'ai vu qu'il fallait en fait surcharger NSTextField. J'ai créé une classe SKTextField dans laquelle j'ai implémenté les méthodes.
<br />@interface SKTextField : NSTextField<br />{<br />}<br />- (void)textDidBeginEditing:(NSNotification *)aNotification;<br />- (void)textDidChange:(NSNotification *)aNotification;<br />@end<br /><br />#import "SKTextField.h"<br /><br />@implementation SKTextField<br /><br />- (void)textDidBeginEditing:(NSNotification *)aNotification<br />{<br /> NSLog(@"textDidBeginEditing");<br />}<br /><br />- (void)textDidChange:(NSNotification *)aNotification<br />{<br /> NSLog(@"textDidChange");<br />}<br />@end<br />
Les messages apparaissent bien dans la console quand je saisis du texte.
Le problème où je bute est le suivant : comment activer le bouton dans le delegate (celui-ci n'est pas connu à ce niveau là [ibBtnCount setEnabled:YES]) ?
Merci.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Abonne ton contôleur à la notification NSControlTextDidChangeNotification.
Cette notification est émise lorsque le fieldElditor du contrôle (ici le textFieldCell) est modifié.
Dans la méthode de réception de la notif, il ne te reste plus qu'à tester si le champ est vide ou non, puis de positionner l'état de ton bouton.
.
Enfin bon dans tous les cas se faire la main sur les notifications ça ne fait pas de mal
Par contre juste par curiosité, si j'avais voulu conserver la surcharge de mon textField, quel aurait été le moyen à utiliser ?
Plusieurs méthodes :
1. exposer ton outlet afin que ton textfield puisse l'utiliser. Cette méthode n'est pas à recommander, car elle lie le code du textfield à celui de ton appli (ce qui rend plus difficile la réutilisation de ton textfield dans une autre appli).
2. utiliser le notificationCenter : là , ton textField émet une notification. Il ne te reste plus qu'à abonner ton contrôleur pour surveiller cette notif.
3. implanter un mécanisme de delegate : idem, ton textField appelle le delegate afin de lui faire exécuter une méthode précise.
(Ceci ne marche pas dans le cas d'un textField en mode édition)
.
Bru, j'aimerais bien essayer ta méthode 3. Est-ce que tu pourrais me guider davantage ? Ce que j'avais fait avant, c'était dire que AppController était le delegate pour mon textField et j'avais implémenté les 2 méthodes que j'avais citées et tiré la connexion dans IB. Le problème c'est que rien ne se passait. En surchargeant NSTextField et en mettant les méthodes du delegate dans ma nouvelle classe, ça fonctionnait (enfin le NSLog) mais à partir de ma classe SKTextField, impossible d'accéder au bouton.
Quelle est la bonne méthode à suivre pour ta 3ème proposition ?
Merci.
Dans ce cas, ton textField va tenter d'exécuter la méthode enableCount appartenant à l'objet qui est target de ton bouton : comme cet objet est normalement ton contrôleur, il aura accès à ton outlet de bouton.
Note : le target, c'est l'objet que tu connectes à ton contrôle quand tu tires une ligne dans IB.
.
Merci.
[Fichier joint supprimé par l'administrateur]
Mais...
J'aurai dû le voir dans la doc : la méthode surchargée textDidChange: est appelée par une notification envoyée par le field editor.
Un textField qui est en mode édition se "transforme" en field editor, c'est donc un autre objet qui n'a plus rien à voir avec ton texField d'origine. Ceci explique que le target soit nil.
Donc, oublie la solution delegate.
Désolé.
.