Contrôler la validation d'un bouton

muqaddarmuqaddar Administrateur
05:49 modifié dans API AppKit #1
Yop,

Comment s'y prendre pour contrôler l'activation (setEnable) d'un bouton valider d'une sheet, sachant que celui-ci doit être actif que si tous les champs on été remplis ou sélectionnés (popup, fields...etc). Je pense au delegate, et à  une méthode associée, mais sur chaque champ ? Y a t-il une autre solution ?
Merci. :why?:

Réponses

  • Eddy58Eddy58 Membre
    05:49 modifié #2
    Pour ce genre de chose, j'utilise une notification a chaque changement dans les textfields, puis je change l'état du bouton en fonction : :)

    <br /><br />-(void)awakeFromNib<br />{<br />	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldModif:) name:NSControlTextDidChangeNotification object:nil];<br />}<br /><br />-(void)textFieldModif:(NSNotification *)notification<br />{<br />	if ([[textField1 stringValue] isEqualToString:@&quot;&quot;] || [[textField2 stringValue] isEqualToString:@&quot;&quot;])<br />	{<br />		[validerButton setEnabled:NO];<br />	}<br />	else<br />	{<br />		[validerButton setEnabled:YES];<br />	}<br />}<br />
    
  • muqaddarmuqaddar Administrateur
    05:49 modifié #3
    Merci Eddy  :adios!:
    Super réponse.

    A ce propos, les observers sont à  déclarer ds le awakeFromNib obligatoirement ?
    C'est le mieux ?
  • Eddy58Eddy58 Membre
    05:49 modifié #4
    dans 1102522902:

    Merci Eddy :adios!:
    Super réponse.

    A ce propos, les observers sont à  déclarer ds le awakeFromNib obligatoirement ?
    C'est le mieux ?

    Et bien je déclare toujours mes notifications dans awakeFromNib:, ou init: si j'ai besoin de la notification avant l'initialisation des objets nib, je pense que c'est le mieux, mais je ne connais pas tout des notifications, il ne m'étonnerait pas qu'il existe des cas particuliers... :) ;) 8)
  • muqaddarmuqaddar Administrateur
    05:49 modifié #5
    J'ai un soucis pour mon popup :

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(validateAdd:) name:NSControlTextDidChangeNotification object:nil];<br />[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(validateAdd:) name:NSPopUpButtonWillPopUpNotification object:nil];
    


    Et :

    -(void)validateAdd:(NSNotification *)notification<br />{<br />	if (([[newDomaineField stringValue] isEqualToString: @&quot;&quot;]) || ([newPaysPopup indexOfSelectedItem] == 0)) {<br />		[validateButton setEnabled:NO];<br />	}<br />	else {<br />		[validateButton setEnabled:YES];<br />	}<br />}
    


    ça marche à  moitié, en fait, quand je change ma sélection, la nouvelle notification n'est pas envoyée, mais si je reclique sur le popup, elle passe... :o

    ça doit venir de : NSPopUpButtonWillPopUpNotification qui n'est pas être pas la plus appropriée... mais j'en ai pas vu d'autre pour les popup ! So what ?
  • 05:49 modifié #6
    dans 1102532078:

    Et bien je déclare toujours mes notifications dans awakeFromNib:, ou init: si j'ai besoin de la notification avant l'initialisation des objets nib, je pense que c'est le mieux, mais je ne connais pas tout des notifications, il ne m'étonnerait pas qu'il existe des cas particuliers... :) ;) 8)


    Comme tu ne spécifies pas d'objet à  la notification (si tu veux surveiller les changements d'un objet précis), ça ne change rien de le faire avant ou après. Par contre si tu spécifies un objet, il faut que l'objet soit créé, et donc il faut le faire après initialisation de l'objet (le awakeFromNib est le bon endroit). Si tu le fais avant, nil sera renvoyé pour l'objet et donc ça revient à  observer toutes les notifications.

    Voili voulou.
  • cbrandtcbrandt Membre
    05:49 modifié #7
    dans 1102514750:

    Yop,

    Comment s'y prendre pour contrôler l'activation (setEnable) d'un bouton valider d'une sheet, sachant que celui-ci doit être actif que si tous les champs on été remplis ou sélectionnés (popup, fields...etc). Je pense au delegate, et à  une méthode associée, mais sur chaque champ ? Y a t-il une autre solution ?
    Merci. :why?:


    personnellement, j'ai dans le controller de mes sheet (et autres dialogues) une méthode
    <br />- (IBAction) itemChanged: (id) sender<br />
    

    qui est appelée par chaque object de la sheet/fenêtre en question, de façon à  vérifier l'état des différents éléments d'interface et ensuite valider un bouton "OK" ou non.
    Pour les NSTextFields, si je veux être au courant dès le premier caractère tapé (et non quand on quitte le champ) mon controller est son delegate et j'implémente
    <br />- (void) controlTextDidChange: (NSNotification*) notification<br />
    

    qui se contente d'appeler [self itemChanged: nil].
    Pour les items qui ont une IBAction dédiée, juste avant la fin de celle-ci j'appelle aussi [self itemChanged: nil].

  • Eddy58Eddy58 Membre
    05:49 modifié #8
    dans 1102533246:

    ça marche à  moitié, en fait, quand je change ma sélection, la nouvelle notification n'est pas envoyée, mais si je reclique sur le popup, elle passe... :o

    ça doit venir de : NSPopUpButtonWillPopUpNotification qui n'est pas être pas la plus appropriée... mais j'en ai pas vu d'autre pour les popup ! So what ?

    J'ai toujours utilisé cette méthode avec des textfields, donc là  je peux qu'essayer de t'aiguiller.... :o
    En faites, ce qui se passe actuellement, c'est que quand tu changes une premiere fois la sélection du pop-up, la notification n'est pas envoyée, mais quand tu recliques dessus une deuxieme fois ca marche ? ???
    Pourtant NSPopUpButtonWillPopUpNotification est sensée marcher lors d'un mouse-down event, donc je comprend pas...
    Essaie en spécifiant le nom de ton pop-up dans le paramètre object, pour voir si ca améliore les choses, ou alors en faisant une action classique sur ton pop-up dans IB, et récupérer le résultat dans une méthode à  part. Sinon là  pour l'instant je vois pas, NSPopUpButtonCell propose aussi une notification mais elle est du même genre que celle de NSPopUpButton... >:)
  • muqaddarmuqaddar Administrateur
    05:49 modifié #9
    Malheureusement je confirme.
    Si je change de selection, ça ne fait rien, mais si je reclique juste sur le popup, même sans changer de selected item, ça marche, là  ça prend en compte la sélection précédente, la notification passe. J'ai ajouté l'objet sans succès.

    ça vient pas de ma double notification dans la même méthode ?
  • 05:49 modifié #10
    C'est normal. Cette notification est envoyée pour indiquer que le PopUp va s'ouvrir(NSPopUpButtonWillPopUpNotification), pas pour indiquer un changement de valeur, donc quand la notification est envoyée, le changement de valeur n'a pas eu lieu. Une solution est de créer une action générique, que tu relies à  tous tes popups.
  • décembre 2004 modifié #11
    Bein, moi, je ne suis pas fan de cette méthode ! A tel point que je répond :p Utiliser des notifications pour si peu... ??

    Je préfère de loin une globale (ail ! pas taper !) et un bon vieux

    updateUI
    {
    [bouton activer:globale]
    }

    Evidemment la globale est modifiée dans l'action des éléments style globale=[text length]>0;....
  • 05:49 modifié #12
    Rrr... ça marche pas Cocoa quand on a rien dant le bide ;)

    Pas de globale et un updateUI genre  :

    {
    BOOL b=[text Length]>0 && [popUp selection]==2 && serbraxuaepmirperemdnargam

    [bouton actvier:b];
    }
  • muqaddarmuqaddar Administrateur
    05:49 modifié #13
    Bon...
    Merci pour toutes vos combines. Je vais essayer de "magouiller" une action générique. Pas glop quand même que d'autres notifications n'existent pas pour NSPopupButton.
  • ClicCoolClicCool Membre
    05:49 modifié #14
    hem hem !

    ça a l'air bien compliqué ce pb:
    - Utiliser une globale n'est jamais une bonne solution même si ça marche.
    - Les Notifications existantes ne semblent pas utilisables pour un Pop up.

    Quel dommage qu'Apple ne nous fournisse pas un moyen facile et fiable de lier les statuts d'un bouton à  une série de condition...  :'(

    Ah ben oui! ce serait génial ça ! un système qui relie le model objet avec les éléments d'interfaces et les éléments d'interface entre eux. Des sorte de liens dynamiques automatiquement mis à  jour et tout et tout. :o

    On pourait appeler ça des "liens"?
    Non faut penser aux anglophones ... des "Bindings" alors ?
    Ah oui se serait super chouette ça, on va tous écrire à  Apple pour réclamer des Bindings.  :boss):
    En plus ça irait pil poil avec les ambitions de Tiger pour gérer aussi le stockage du model sur disque (en XML, SQLLite etc ...).
    Bon sang ! j'espère qu'il est pas trop tard et qu'Apple va avoir le temps d'inventer les Bindings avant la sortie de Tiger histoire qu'on s'habitue à  ce que l'avenir nous réserve comme bonnes choses.

    Voili voilou (comme dirait un certain canard)  ;)
  • muqaddarmuqaddar Administrateur
    05:49 modifié #15
    C'est de la provocation ça, Mr ClicCool.
    Tu sais ce que j'en pense des bindings à  l'heure actuelle. hihi
    :-*

  • ClicCoolClicCool Membre
    05:49 modifié #16
    dans 1102584740:

    Tu sais ce que j'en pense des bindings à  l'heure actuelle. hihi
    :-*


    Ben oui je sais ;)

    T'en penses que c'est tellement pratique, efficace et facile que tu t'imposes de t'en passer pour t'aguérir dans ton apprentissage de Cocoa.
    Et tu a bien raison de faire ainsi  :-*














    N'empèche que c'est tellement pratique, efficace et facile ...  :kicking:
  • 05:49 modifié #17
    Il y a une autre solution (que j'ai commencé à  mettre en pratique, mais pas le temps d'avancer...).

    En fait tous les objets se voient attribuer un identifier(NSString) à  partir de IB (ça demande donc de créer de nouvelles palettes, et de sous-classer les principaux types de contrôles). Lorsque les contrôles changent d'état, ils envoient un message au file's owner, avec eux comme argument. Quand une variable change d'état dans le file's owner, elle envoient une notification reçues par les contrôles qui se trouvent dans des fenêtres dépendant de lui.
  • Eddy58Eddy58 Membre
    décembre 2004 modifié #18
    dans 1102576470:

    Bein, moi, je ne suis pas fan de cette méthode ! A tel point que je répond :p Utiliser des notifications pour si peu... ??

    Les notifications sont justement conçues pour renseigner...les notifications sont là  pour permettre d'intercepter des évènements de manière élégante....et de plus elle a toute son utilité ici car a chaque changement dans tes textfields, tu peux en déduire tout de suite l'état de ton bouton. ;) :)
    Les trucs globaux, c'est du bricolage en Objective-Cocoa, tandis que les notifications font parties des cocoas design patterns... ;D

    Oxitan, tu peux faire une action générique dans IB sur tes pop-ups, puis avec cette action tu appel la méthode appelée par la notification : :)

    <br />-(IBAction)popUpAction:(id)sender<br />{<br />[self validateAdd:nil];<br />}<br />
    
  • muqaddarmuqaddar Administrateur
    05:49 modifié #19
    Oui, Eddy je vais m'y prendre comme ça...
    Merci pour tout.
  • ClicCoolClicCool Membre
    décembre 2004 modifié #20
    dans 1102589260:

    Oxitan, tu peux faire une action générique dans IB sur tes pop-ups, puis avec cette action tu appel la méthode appelée par la notification : :)

    <br />-(IBAction)popUpAction:(id)sender<br />{<br />[self validateAdd:nil];<br />}<br />
    



    de mon côté, si je devais m'emputer des bindings, je ne ferais pas ça, et surtout je garderais les bonnes habitudes de tout codeur (bindeur) à  savoir l'usage des ACCESSEURS.

    Ce n'est pas ton action d'un élément graphique qui doit être responsable d'appeler ta méthode de mise à  jour de ceci ou cela.
    Et si ton interface évolue et permet de modifier la valeur depuis plusieurs objets d'interface ?
    Et si tu modifies tes données par ton code ?

    Ton action popUp doit simplement appeler un accesseur: setValue.
    Et bien sur dans ton setValue tu peux poster une notification après avoir vérifié si la valeur est effectivement différente ou mieux si le setValue écrit une valeur là  ou il y en avait pas ou inversement enlève une valeur préexistante ...
    (Tu teste la valeur à  placer et la valeur préexistante, si elles sont toutes deux vides ou toutes deux non vides tu postes rien, si une seule des deux est vide tu postes ta notification perso)
  • Eddy58Eddy58 Membre
    05:49 modifié #21
    dans 1102596161:

    de mon côté, si je devais m'emputer des bindings,

    Quelle horreur les amputations, surtout de bindings ! ;)

    dans 1102596161:

    je ne ferais pas ça, et surtout je garderais les bonnes habitudes de tout codeur (bindeur) à  savoir l'usage des ACCESSEURS.

    Ce n'est pas ton action d'un élément graphique qui doit être responsable d'appeler ta méthode de mise à  jour de ceci ou cela.
    Et si ton interface évolue et permet de modifier la valeur depuis plusieurs objets d'interface ?
    Et si tu modifies tes données par ton code ?

    Oui ClicCool, tout est envisageable... effectivement si la gestion de l'interface se complique par exemple en se partageant dans plusieurs controleurs, des accesseurs dédiés sont une bonne solution pour une bonne structure du code, mais si l'élément d'interface n'est géré que par un seul contrôleur, je pense qu'il est inutile de surcharger le code avec d'autres méthodes...
    :) :o
  • muqaddarmuqaddar Administrateur
    05:49 modifié #22
    Bein je m'en suis sorti simplement, avec 2 notifs et une méthode adéquate...
Connectez-vous ou Inscrivez-vous pour répondre.