Problème avec TextField

Eddy58Eddy58 Membre
08:49 modifié dans API AppKit #1
Il y a quelque chose que je ne comprend pas : J'ai un textfield, formaté pour nombres à virgules. Une notification NSContolTextDidChange surveille le textfield et notifie correctement tout changement dans celui-ci. Quand la méthode liée à la notification est appelée, je récupère la valeur du textfield. Jusqu'ici pas de problème tout fonctionne. Le problème réside dans le comportement du textfield : Celui-ci est initialisé à "0,00". Quand on rentre un chiffre entre la virgule et le premier zéro, le curseur passe soudainement de l'autre coté de la virgule ! C'est très gênant.... En cherchant, et en supprimant la ligne : val=[textField floatValue]; qui récupère la valeur, et bien le textfield se comporte normalement. Je ne comprend pas en quoi le faites de récupérer la valeur pendant l'édition perturbe le comportement du textfield ?
Quelqu'un a-t-il déjà eu ce problème, et/ou aurait-il une idée pour le résoudre ?

Le projet est récupérable ici

Réponses

  • TiffTiff Membre
    08:49 modifié #2
    Une remarque : si tu supprimes la ligne val = [textField floatValue] , tu t'apercevras que ton formatter n'est pas actif : tu peux taper autant de chiffres après la virgule que tu veux, textField te les affichera tous. Tu peux même entrer du texte si ça te chante, personne ne te dira rien. Par contre, dès que tu valides ton champ par Tab ou Enter, le formatter réagit : si c'est du texte, il r‚le ; si c'est un nombre, il le met au bon format.

    L'instruction val = [textField floatValue] va implicitement faire appel au formatter : avant de pouvoir récupérer la valeur, il faut être s?r que celle-ci soit dans les clous. Du coup, l'affichage va changer, le nombre va se mettre au bon format, et le curseur va se balader au bon gré du formatter.

    Conclusion : NSFormatter et NSControlTextDidChangeNotification ne font pas bon ménage, il va falloir changer de tactique. Tout dépend de ce que tu veux faire exactement.
  • Eddy58Eddy58 Membre
    08:49 modifié #3
    Merci pour cette explication. Le but est de détecter le moindre changement dans les textfields, afin de procéder à de petits calculs temps réel et sauvegardes. Cette technique fonctionne très bien avec les Textfields Textes et nombres entiers, mais les virgules ça ne passe pas. Je ne vois pas d'autre solution. Tant pis, je vais me baser sur la notification TextDidEndEditing, et procéder aux diverses opérations ensuite.
  • Eddy58Eddy58 Membre
    08:49 modifié #4
    J'ai finalement trouvé une solution..... Je crée un NSNumberFormatter indépendant, puis je joue avec les deux notifications TextDidChange et TextDidEndEditing. Au début, le textfield est sans formatter. Quand le textfield est édité, rien ne dérange le comportement du curseur, et chaque notification TextDidChange permet de procéder aux diverses opérations. Quand une notification TextDidEndEditing est envoyée, j'attache le formatter au textfield, puis je fais une récupération des données, ce qui "met la valeur du textfield dans les clous" :). Ensuite je n'ai plus qu'a redétacher le formatter du textfield, et le tour est joué.  8)
  • TiffTiff Membre
    08:49 modifié #5
    As-tu remarqué comment iCal gère les heures dans le tiroir ?
    "du 24/05/04 à 17:22" est composé de 5 TextField : "24"  "05" "04" "17" "22".
    Un peu lourd sans doute, mais dès que l'on passe d'un champ à l'autre, TextDidEndEditing doit être envoyé pour une Màj des autres champs.
  • Eddy58Eddy58 Membre
    08:49 modifié #6
    Je trouve ce type de tiroir (iApp) très intéressant techniquement. Ca doit être assez lourd à mettre en oeuvre, même avec toutes les "facilités" proposées par Cocoa, car l'interface est très dynamique. Ceci dit vive les notifications et autres delegates ! :)
  • TiffTiff Membre
    08:49 modifié #7
    Très simple les tiroirs !
    Il suffit de mettre un bouton dans la fenêtre (ou mieux dans la barre d'outils) et de le relier au tiroir par l'action toggle:
    Et c'est tout !
    Une fois que j'ai compris les bindings, j'ai voulu voir comment ils fonctionnaient avec les tiroirs : tableau dans la fenêtre et champs de texte dans le tiroir. Le pied total, rien à écrire, et tout fonctionne du premier coup !
  • Eddy58Eddy58 Membre
    08:49 modifié #8
    Oui je sais, j'ai déjà fait des tiroirs, c'est du plus simple en effet. En faites je parlais des interfaces dynamiques à l'intérieur des tiroirs des iApps, qui elles demandent bcp de boulot je pense. Par contre je ne me suis pas encore mis aux bindings.... Tout le monde en parle, c'est si fabuleux que ça ?  :D
  • 08:49 modifié #9
    dans 1085492354:

    Par contre je ne me suis pas encore mis aux bindings.... Tout le monde en parle, c'est si fabuleux que ça ?  :D


    A part l'interrogation concernant le tri (voir le thread dans la section données ;) ), les bindings sont une pure merveille pour le programmeur car ils le dégagent de tous ce qui est code de synchro entre les différents éléments graphiques et les  informations représentées. Et c'est franchement une excellente initiative car faire du "glue code" n'a rien d'interessant intellectuellement :)
    Par contre, faut pas tomber dans l'excés et essayer de tout faire avec les bindings (si tu n'as qu'une TableView alors le datasource est largement suffisant).
  • Eddy58Eddy58 Membre
    08:49 modifié #10
    Donc en faites les bindings prennent en charge une partie du code, c'est intéressant, est-ce long à en apprendre le fonctionnement ?
  • TiffTiff Membre
    08:49 modifié #11
    Le plus long est de tomber sur le bon tutoriel.
    Une fois que l'on a compris, ça parait tout bête. (Du moins les principes de base).
    Voir, en toute modestie, mon projet Videotheque 02 dans le forum Projet.
    En gros, pour une appli sans document :
    tu as une classe Modele qui déclare plusieurs variables d'instances var1, var2, var3.
    tu as une classe Controleur qui déclare une liste NSMutableArray *mesModeles
    dans IB, tu as besoin d'une instance de NSObjectController et une de NSArrayController
    tu connectes l'objectController à ton Controleur par l'outlet content et tu déclares dans la fenêtre attributes la clé mesModeles
    dans les attributes de l'arrayController, tu déclares le nom de la classe Modele et toutes ses variables (var1, var2, var3) comme clefs
    dans les bindings de l'arrayController, tu choisis dans contentArray : ObjectController selection mesModeles
    Terminé ! "a peut paraà“tre long à paramétrer, mais quand on l'a fait deux ou trois fois, ça parait évident (déclarer les clefs dans les attributes, puis faire les liens dans les bindings).

    Tu n'as plus qu'à choisir dans l'interface ce qui va afficher les variables en question : normalement un tableau mais tu peux aussi connecter des textField en plus.
    Tu cliques sur l'en-tête de la première colonne de ton tableau, tu vas dans la fenêtre bindings, tu choisis value puis
    Bind to: ArrayController
    ControllerKey:arrangedObjects
    Model Key Path:var1 (ou var2, var3,etc)
    et tu fais ça pour toutes les colonnes du tableau, puis pour des textField si tu veux, qui se mettront à jour dès que tu sélectionneras une ligne du tableau.

    On peut aussi choisir le Placeholder, c'est-à-dire le texte qui va s'afficher en grisé quand rien n'est sélectionné ou quand plusieurs lignes sont sélectionnés, etc ; comme "Google" qui est inscrit par défaut dans le SearchField en haut à droite de la fenêtre de Safari.

    Plein d'autres outils disponibles avec les bindings, mais je ne les ai pas encore étudiés.

    L'inconvénient des bindings est que notre Controleur ne contrôle plus grand chose justement. Je suis en train de chercher comment on peut créer une sous-classe de NSArrayController pour réécrire des méthodes (tri et recherche en particulier).
  • ClicCoolClicCool Membre
    08:49 modifié #12
    T'as un Tuto en ligne qui vient de démarrer sur Macfr: http://macfr.com/forums/index.php?showtopic=12488
    :D
    ClicCool
Connectez-vous ou Inscrivez-vous pour répondre.