Déclencher des méthodes à partir de controles

Sken

Membre confirmé
8 Juin 2003
24
0
Nouvelle question : comment fait-on pour déclancher une méthode après une action autre que taper sur Return ? Je m'explique : j'ai un textField, je voudrais que son contenu s'efface quand je clique dessus. Je n'ai réussi à lancer une méthode qu'avec l'appui sur Return, pourtant les autres événements doivent bien être prévus non ? J'ai vu qu'on pouvait mettre un script applescript, mais je ne connais pas la syntaxe de applescript, y a t il une autre solution ?
Merci de votre patience...
Sabine
 
<blockquote><font class="small">Post&eacute; &agrave; l'origine par Sken:</font><hr /> Nouvelle question : comment fait-on pour déclancher une méthode après une action autre que taper sur Return ? Je m'explique : j'ai un textField, je voudrais que son contenu s'efface quand je clique dessus. Je n'ai réussi à lancer une méthode qu'avec l'appui sur Return, pourtant les autres événements doivent bien être prévus non ? J'ai vu qu'on pouvait mettre un script applescript, mais je ne connais pas la syntaxe de applescript, y a t il une autre solution ?
Merci de votre patience...
Sabine


[/QUOTE]

Pour gerer les éléments d'edition, de modification ou de validation de texte ce n'est pas très compliquer. il suffit que ton NSTextField soit delegate de ton objet puis dans l'objet tu implémente les methodes :

public void controlTextDidBeginEditing(NSNotification aNotification)
{
// Début de l'edition du texte

}

public void controlTextDidChange(NSNotification aNotification)
{
// le texte a été modifié.

}

public void controlTextDidEndEditing(NSNotification aNotification)
{
//fin d'edition du texte

}

Mais si tu veux faire une action quand ton controle devient le firstResponder (qu'il est selectionné) ca devient legerement plus compliquer parce que la méthode n'est pas implémenter comme delegate.

Pour ma part je créerais une sous classe de NSTextField comme suit.

/* MonTextField */

import com.apple.cocoa.foundation.*;
import com.apple.cocoa.application.*;

public class MonTextField extends NSTextField {

// initialisation (comme pour une NSView)
public MonTextField() {
super();
}

public MonTextField(NSRect aRect) {
super(aRect);
}

public void drawRect(NSRect aRect)
{
super.drawRect(aRect);
}

// implémentation de la mathode du firstResponder
public boolean becomeFirstResponder()
{
// on efface le NSTextField :
this.setStringValue("");
return super.becomeFirstResponder();
}
}

Bien sur si vous avez d'autres solutions je suis preneur......

 
Aucune des deux solutions que tu proposes ne marche, mais je dois dire que je ne m'y suis peut-être pas prise comme il faudrait; il faut dire que j'ai du mal à comprendre cette notion de délégation etc... Pourtant il me semble que j'avais bien assimilé la notion de programmation objet en apprenant java, mais là, avec cocoa, j'ai vraiment du mal...j'ai essayé de comprendre les topics sur le MVC dans project omega, mais bof...
Donc pour le moment, je suis dans l'impasse... et pour mon problème spécifique, il n'y avait pas moyen de redéfinir la méthode mouseDown() quelque part ?
A +
Sabine
 
Je me permets de répondre en essayant de ne pas dire de bêtises.

Certaines classes possèdent des méthodes qui peuvent être déléguées. Cela veut dire que si un délégué est défini pour un objet d'un certain type (i.e. d'une certaine classe). Ce délégué recevra certains appels de méthode que l'objet aurait du normalement recevoir et traiter lui-même.

Pour reprendre l'exemple cité plus haut, la classe NSTextField définit des méthodes qui peuvent être déléguées à un autre objet, dans ces méthodes, il y a : void controlTextDidChange(NSNotification aNotification). Cette méthode est automatiquement appelée lorsque le texte d'un NSTextField a changé. Si tu veux exécuter du code lorsque ce NSTextField est changé, tu as deux solutions :
1) Tu pourrais créer une sous-classe de NSTextField qui implémenterait uniquement cette méthode et tu n'utiliserais pas la notion de délégation. Ce n'est pas très pratique, si tu as de nombreux NSTextField.
2) Tu assignes un délégué à ton objet NSTextField, et lorsque l'utilisateur modifiera ce NSTextField, la méthode controlTextDidChange sera appelée sur le délégué et non sur l'objet lui-même.
 
Pour illustrer ce que je disais plus haut, j'ai fais un petit exemple qui utilise une sous class de NSTextView qui est en plus delegate d'un autre objet NSTextView.

Mon explication peu paraitre compliquer mais l'exemple est très simple et comporte très peu de ligne.

vous pouvez le trouvé ici

 
Les explications de Mitch sont les bonnes.

Mais pour que cela marche, il ne faut surtout pas oublier d'indiquer que le textfield donne sa "délégation" à l'objet controleur dans IB (et c'est dans le .m de cet objet qu'il faut mettre les 2 méthodes de délégations).

Pour faire ca, il suffit de control-draguer une ligne entre le textfield et l'instance de l'objet controleur, puis de clicker sur "delegate" et "connect".

.
 
Une solution.
Ton interface a forcément un controller.
Dans la méthode awakeFromNib de ton controller ajoute l'instruction :
[montextField setdelegate:self]

ou montextField.setDelegate(this)

Ensuite implémente la méthode controltextShouldBeginEditing en y ajoutant l'instruction :
[montextField setStringValue:mad:" "]

ou montextField.setStringValue(" ")
pour mettre ta zone à blanc.
 
<blockquote><font class="small">Post&eacute; &agrave; l'origine par Manu:</font><hr /> Une solution.
Ton interface a forcément un controller.
Dans la méthode awakeFromNib de ton controller ajoute l'instruction :
[montextField setdelegate:self]

Ensuite implémente la méthode ...textDidBeginEditing en y ajoutant l'instruction :
[montextField setStringValue:mad:" "]
pour mettre ta zone à blanc.


[/QUOTE]

Je ne suis pas tout a fais d'accord avec toi.

En Effet la methode textDidBeginEditing ne se produit qu'au moment ou tu tape le premier caractère. donc pas lors de la selection du NSTextField.

De plus (si je ne me trompe pas) textDidBeginEditing nest pas une methode delegue, donc pour que cela fonctionne il faut subclasser NSTextField pour l'implémenter.

Les delegate du NSTextField se trouve dans l'objet NSControl.
 
D'abord merci à tous, chacun d'entre vous a contribué à ce que je commence à comprendre... J'ai mis un peu de temps à réagir, à cause 1) d'une migraine
wink.gif
)), 2) des grèves sur Paris, ça complique quand même pas mal la vie (Vive les suisses !!!), 3) de la cannicule à Paris...
Voilà, donc, j'émerge... d'autant que le week-end n'est plus très loin;)))
molgow ton explication m'a bien aidée, quant à l'exemple que tu donnes Mitch, je n'ai pas encore fini de tout regarder mais je crois que je suis sur la voie... Et Manu, j'ai pu constater que la méthode awakeFromNib marche effectivement en Java. Donc merci à tous.
Voilà, cela dit, j'ai encore des questions, mais je vais continuer à tatonner... En fait le delegate il est l'équivalent du addActionListener en java standard, non ?
Je pensais déja connaître pas mal de classes en java, mais celles de cocoa.java sont encore différentes... On peut quand même utiliser les classes de java standard, non ? exemple, j'avais pris le coup de main avec les classes GregorianCalendar de java, et je ne trouve pas les méthodes équivalentes dans NSGregorianCalendar..En fait j'ai vu que c'est possible, mais est-ce au détriment de la performance ? Mitch tu disais que si on utilises Swing ou Awt cela ralentit l'application, est-ce la même chose avec toutes les classes qui ne sont pas issues du package com.apple.cocoa ?
Cordialement
Sabine
 
Toutes les méthodes d'affichage en java sont plus lente sous OSX par contre il faut savoir que les classes java pour les tableaux (Vector Hashtables...) sont plus rapide et moins gourmandes en mémoires. donc je te conseille de les utiliser.

Cocoa c'est excellant pour tout ce qui touche a l'affichages, aux nibs mais pour le reste je te conseille d'utiliser des classes pure java.

Cette analyse vient après maintenant 3 années de développement en java cocoa et de mon expérience acquise dans le monde Next.

mais mes propos n'impliquent que moi..... d'autres ne seront certainement pas d'accord... a voir
wink.gif
 
Bonjour,
Je progresse lentement... encore du mal à saisir la notion de délégation, et beaucoup de mal avec la doc... Mitch, ta technique de créer une sous classe de TextField marche effectivement, mais de ce fait il n'est plus possible de formatter la zone de texte en deux coups de clics comme on peut le faire avec un TextField. Je voudrais que mon TextField formatte les nombres avec deux chiffres après la virgule, j'ai pour cela importé java.text, pour avoir la classe DecimalFormat, mais je n'arrive pas à l'appliquer sur le contenu du TextField.
Autre point, quand même, je trouve que les classes de java sont plus faciles à utiliser, par exemple j'ai essayé la méthode componentsSeparatedByString, préconisée par Manu dans un exercice qu'il avait proposé il y a un an sur ce forum, et je n'arrive pas à la faire marcher, alors que ça marche quand j'utilise StringTokenizer, qui fournit les mêmes fonctionnalités...
 
Merci Mitch
Mais voilà encore du nouveau : j'essaie de faire un convertisseur euros. J'ai deux textFields de la sous classe MonTextField. Un controlleur avec la méthode convert. Dans le code de la classe MonTextField j'ai fait comme tu m'as dit : le constructeur et la méthode becomeFirstResponder. quand je compile, pas de problème puis au run j'ai ce message :
2003-06-15 20:41:38.932 EurosConvertisseur[7821] AppKitJava: uncaught exception NSArchiverArchiveInconsistency (*** file inconsistency: read '@', expecting 'C')
2003-06-15 20:41:38.934 EurosConvertisseur[7821] AppKitJava: exception = *** file inconsistency: read '@', expecting 'C'
2003-06-15 20:41:38.936 EurosConvertisseur[7821] AppKitJava: terminating.

«PROJECTNAME» has exited with status 1.

J'ai réécris le projet deux fois, ça ne change rien...
Avez vous une idée ?
 
J'ai eu exactement le même problème hier en voulant faire un petit programme de test à propos de ces delegates.

Je pense savoir d'où vient le problème. Dans mon cas, j'avais défini une sous-classe de NSTextField, et dans cette sous-classe, j'avais un outlet à un autre élément d'interface (un NSTextField non éditable en l'occurence). Cette erreur se produit au moment de l'exécution. Je pense que le problème vient du fait que lorsque l'application est lancée, il charge la fenêtre avec le NSTextField, mais le problème c'est que le outlet ne peut pas être défini puisqu'il n'a peut-être pas encore chargé. Pour expliquer autrement, au moment où l'application se lance, il voit qu'il y a un outlet dans la sous-classe NSTextField qui pointe vers un autre NSTextField, alors il essaie de faire pointer cet outlet vers cet autre NSTextField, mais ce n'est pas possible, car il n'a pas encore été créé en mémoire.

Il faudrait pouvoir commander l'ordre de chargement des éléments graphiques au lancement, mais comme je suppose que ce n'est pas possible, il vaudrait mieux programmer ça d'une manière différente.

 
Je me rends compte que c'est étrange, car apparemment ton exemple TextViewDelegate fait exactement la même chose que ce que je décris (sauf que l'outlet pointe sur un NSTextView et non un NSTextField).

Je comprends plus là...

J'espère que tu pourras encore une fois nous éclairer tous Mitch
zen.gif


 
Sken a dit:
Merci Mitch
Mais voilà encore du nouveau : j'essaie de faire un convertisseur euros. J'ai deux textFields de la sous classe MonTextField. Un controlleur avec la méthode convert. Dans le code de la classe MonTextField j'ai fait comme tu m'as dit : le constructeur et la méthode becomeFirstResponder. quand je compile, pas de problème puis au run j'ai ce message :
2003-06-15 20:41:38.932 EurosConvertisseur[7821] AppKitJava: uncaught exception NSArchiverArchiveInconsistency (*** file inconsistency: read '@', expecting 'C')
2003-06-15 20:41:38.934 EurosConvertisseur[7821] AppKitJava: exception = *** file inconsistency: read '@', expecting 'C'
2003-06-15 20:41:38.936 EurosConvertisseur[7821] AppKitJava: terminating.

«PROJECTNAME» has exited with status 1.

J'ai réécris le projet deux fois, ça ne change rien...
Avez vous une idée ?

pourais tu m'envoyer le projet que tu as fais pour que je puisse regarder d'ou viens t'on erreur d'execution.... moi je n'ai jamais eu ce problème..... donc je ne sais pas comment te répondre.
confused.gif


Mais je suis pres a t'aider......
 
molgow a dit:
Je me rends compte que c'est étrange, car apparemment ton exemple TextViewDelegate fait exactement la même chose que ce que je décris (sauf que l'outlet pointe sur un NSTextView et non un NSTextField).

Je comprends plus là...

J'espère que tu pourras encore une fois nous éclairer tous Mitch
zen.gif



En fait je pense que quand j'ai écris ce petit exemple j'ai fais des confusion de nom.
la classe MonTextView est une sous classe de NSTextField donc je pense que la fatigue m'avais déja gagner lors de l'écriture de cet exemple.
Par contre mon outlet est bien un NSTextView qui correspond au champs 'action'. qui me permet d'afficher sur plusieurs lignes les evenements en cours.

Je suis désolé pour ses confusions de nom qui pourrais porter a confusion.... je tiens a m'en excuser, il va falloir que je ré-écrive cet exemple avec les bon noms de classe.
frown.gif


j'essaierais de faire mieu la prochaine fois ..... mais si vous voulez mz banir... je comprendrais....
frown.gif
frown.gif
 
Héhé.. c'est pas grave. Personnellement, j'avais bien vu que ta classe MonTextView était une sous-classe de NSTextField. Mais ça ne change rien au problème.

Comme je le disais avant, j'ai également fait une sous-classe de NSTextField avec un outlet qui pointe lui sur un NSTextField et non un NSTextView comme chez toi. Et à part cette différence majeure, je ne vois pas en quoi ce que j'ai fait ne fonctionne pas alors que ce que tu as fait fonctionne.
 
Molgow, juste pour te signaler que la méthode awakeFromNib du Controller de ton interface te permet justement d'initialiser des éléments d'interface.