wxDev.fr, le portail francophone consacré à wxWidgets ! ( The french portal for wxWidgets )  
Esp. membre
Recheche rapide



Recherche avancée
Statistiques
Membres inscrits :2359

Membres en ligne : 0
Invités en ligne : 1

Valid XHTML 1.0 Transitional

Valid CSS2

Menu Snippets (navigation):
Pages: 1    Accueil » Snippets » Chaînes de caractères
» wxTextCtrl + wxTextValidator : N'autoriser que certains caractères
Détails du snippet : wxTextCtrl + wxTextValidator : N'autoriser que certains caractères
Informations sur l'auteur de ce snippet :


Hors ligne
Xaviou (Administrateur)
Lieu: Annecy (74)
Inscrit le : 27-08-2007
Messages: 1375
Snippets: 25
Tutoriels: 6
Introduction / Description :
Bonjour tout le monde.
Le but de ce snippet est de montrer la méthode pour filtrer les caractères lors de leur saisie dans un wxTextCtrl.

Ce filtrage s'effectue à l'aide d'un wxTextValidator, à qui on spécifie les caractères autorisés.
Contenu du snippet :
Pour ce snippet, nous n'allons autoriser que la saisie de nombres entiers positifs. Il suffit de n'autoriser quel es caractères "0" à "9".
Il suffit de placer le code suivant lors de la construction du wxTextCtrl.

Code wxWidgets:

#include <wx/valtext.h>
 
// On crée d'abord le wxTextValidator
wxTextValidator validator(wxFILTER_INCLUDE_CHAR_LIST);
// Ensuite, on initialise un wxArrayString avec les caractères autorisés
wxArrayString allowed_chars;
for (int i=0;i<10;i++) allowed_chars.Add(wxString::Format(_T("%0d"),i));
// On affecte la liste des caractères autorisés au wxTextValidator
txtval.SetIncludes(allowed);
// On peut maintenant créer le wxTextCtrl en lui passant le wxTextValidator en paramètre
wxTextCtrl *txt=new wxTextCtrl(pnl,-1,_T(""),wxPoint(10,10),wxDefaultSize,0,validator);
Explications finales :
Voilà, c'est aussi simple que cela.
Il ne faut cependant pas perdre de vue que le wxTextValidator possède déjà quelques filtres prédéfinis :
- wxFILTER_ASCII : Seuls les caractères ASCII sont aurorisés
- wxFILTER_ALPHA : Seuls les caractères alphabétiques sont autorisés
- wxFILTER_ALPHANUMERIC : Les caractères non-alphanumériques sont interdits
- wxFILTER_NUMERIC : Les caractères non-numériques sont interdits

Il est à noter que les caractères ".", "+" et "-" sont considérés comme numériques, ce qui fait que le style wxFILTER_NUMERIC permet la saisie de nombres décimaux positifs ou négatifs.
Ainsi, pour qu'un wxTextCtrl autorise la saisie de tels nombres, il aurait suffit décrire :

Code wxWidgets:

wxTextCtrl *txt=new wxTextCtrl(pnl,-1,_T(""),wxPoint(10,10),wxDefaultSize,0,wxTextValidator(wxFILTER_NUMERIC));


@+, et bonne prog...
Xav'
Commentaires
cfdev (Membre)
Lieu: Alpes de Haut Provence
Inscrit le : 08-11-2007
Messages: 127
Snippets: 4
Tutoriels: 0
Site web
Hors ligne
Ne pas oublier

Code wxWidgets:

#include <wx/valtext.h>


et petite coquille il manque une parenthèse sur la dernière ligne de code.

++

GNU Linux Power !
Slacker
Xaviou (Administrateur)
Lieu: Annecy (74)
Inscrit le : 27-08-2007
Messages: 1375
Snippets: 25
Tutoriels: 6
Site web
Hors ligne
Salut.

Merci pour les remarques : j'ai fait la correction.

@+
Xav'

Le nouveau portail wxWidgets francophone : www.wxdev.fr
Ben en fait, vous y êtes déjà...
cfdev (Membre)
Lieu: Alpes de Haut Provence
Inscrit le : 08-11-2007
Messages: 127
Snippets: 4
Tutoriels: 0
Site web
Hors ligne
De rien ;)

Par contre il me semble qu'il y a un bug dans le wxFILTER_NUMERIC avec la touche "e". avérifier...

GNU Linux Power !
Slacker
Xaviou (Administrateur)
Lieu: Annecy (74)
Inscrit le : 27-08-2007
Messages: 1375
Snippets: 25
Tutoriels: 6
Site web
Hors ligne
C'est pas forcément un bug :
Avec la notation scientifique, le caractère "e" est bien présent dans la représentation des nombres.

@+
Xav'

Le nouveau portail wxWidgets francophone : www.wxdev.fr
Ben en fait, vous y êtes déjà...
cubbiste (Membre)
Inscrit le : 14-07-2010
Messages: 11
Snippets: 0
Tutoriels: 0
Hors ligne
Bonjour,
Je suis nouveau sur le forum, arrivé sur cette page en cherchant des infos sur la façon d'utiliser les validator.
Mon besoin était tout simple : je cherche à avoir un champ de saisie qui n'accepte que les chiffres. Le fait que le wxFILTER_NUMERIC accepte le 'e' me chagrine, et j'ai donc repris la méthode décrite ici.
Ce type de petit exemple est bien pratique, donc merci de les mettre à disposition ainsi, mais cela suscite de ma part une remarque et une question (j'espère que c'est le bon endroit pour les mettre, sinon dites le moi pour que je m'adapte aux usages du lieu) :

remarque : dans le snippet, il y a

Code Cpp:

txtval.SetIncludes(allowed);

alors que le reste du code utilise validator au lieu de txtval...

et maintenant la question :
J'obtiens bien un bip si je saisis directement un caractère qui n'est pas un chiffre : parfait.
Mais si je fais un copier-coller d'une chaîne non conforme (ie avec des lettres), il n'y a pas de blocage. Je suis le seul dans ce cas ? J'ai raté quelque chose ?
J'avais également lu que la validation avait également lieu lors de la fermeture de la fenêtre, mais ce n'est pas le cas chez moi. Là encore, c'est le comportement "normal", ou j'ai raté quelque chose ?

Précision : je travaille avec wxDev-C++. J'ai créé le dialogue dans l'éditeur graphique, et rajouté le validator en code spécifique après le code généré de création du wxTextCtrl (par un SetValidator). Les boutons OK / Cancel sont ajoutés par le biais d'un wxStdDialogButtonSizer, et pour le moment je n'ai pas ajouté de code sur l'utilisation des boutons.

Merci encore pour les infos disponibles sur le site, et pour une réponse à ces interrogations si quelqu'un passe encore sur un "vieux" topic qui date de plus d'un an...
Sem (Membre)
Inscrit le : 31-05-2008
Messages: 64
Snippets: 0
Tutoriels: 0
Hors ligne
bonjour,
je pense y a une petite coquille oui, ca doit être ca même

Code wxWidgets:

 
#include <wx/valtext.h>
 
// On crée d'abord le wxTextValidator
wxTextValidator validator(wxFILTER_INCLUDE_CHAR_LIST);
// Ensuite, on initialise un wxArrayString avec les caractères autorisés
wxArrayString allowed_chars;
for (int i=0;i<10;i++) allowed_chars.Add(wxString::Format(_T("%0d"),i));
// On affecte la liste des caractères autorisés au wxTextValidator
validator.SetIncludes(allowed_chars);
// On peut maintenant créer le wxTextCtrl en lui passant le wxTextValidator en paramètre
wxTextCtrl *txt=new wxTextCtrl(pnl,-1,_T(""),wxPoint(10,10),wxDefaultSize,0,validator);
 


Pour ce qui est du comportement que tu décris ( cad aucune validation sur un copier/coller et sur la fermeture du dialogue ), il me semble que c'est le comportement standard. Cependant, on peut toujours appeler la méthode Validate() qui valide ou non ton dialogue. Il suffit donc de gérer les évènements qui vont bien et de valider avec Validate().

Sem
cubbiste (Membre)
Inscrit le : 14-07-2010
Messages: 11
Snippets: 0
Tutoriels: 0
Hors ligne
Merci pour ta réponse Sem.

Malheureusement, ça ne marche toujours pas comme je voudrais ...

J'ai une classe qui hérite de wxDialog, dont voici quelques extraits du code :

Code wxWidgets:

 
alb_paramDlg::alb_paramDlg(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style | wxWS_EX_VALIDATE_RECURSIVELY)
{
    CreateGUIControls();
    ChargeValeurs();
}
 
void alb_paramDlg::CreateGUIControls()
{
    ////GUI Items Creation Start
...
    m_edtNbMotsCleRecents = new wxTextCtrl(WxNoteBookPage1, ID_WXEDIT1, wxT("m_edtNbMotsCleRecents"), wxPoint(222, 5), wxSize(50, 19), 0, wxDefaultValidator, wxT("m_edtNbMotsCleRecents"));
    WxFlexGridSizer2->Add(m_edtNbMotsCleRecents,0,wxALIGN_CENTER | wxALL,5);
 
    m_edtHauteurMiniature = new wxTextCtrl(WxNoteBookPage1, ID_WXEDIT2, wxT("m_edtHauteurMiniature"), wxPoint(222, 34), wxSize(50, 19), 0, wxDefaultValidator, wxT("m_edtHauteurMiniature"));
    WxFlexGridSizer2->Add(m_edtHauteurMiniature,0,wxALIGN_CENTER | wxALL,5);
 
...
    ////GUI Items Creation End
 
    // pour les validator
    wxArrayString listeChiffres;
    for (int ii=0;ii<10;ii++)
        listeChiffres.Add(wxString::Format(_T("%0d"),ii));
    wxTextValidator validator(wxFILTER_INCLUDE_CHAR_LIST);
    validator.SetIncludes(listeChiffres);
 
    m_edtHauteurMiniature->SetValidator(validator);
    m_edtNbMotsCleRecents->SetValidator(validator);
}
 
// gestionnaire du bouton OK
void alb_paramDlg::WxStdDialogButtonSizer1OkClick(wxCommandEvent& event)
{
    cubLogDebug("");
    cubLogDebug("Validate() global : %d", Validate());
    cubLogDebug("Validate() sur le wxTextCtrl : %d", m_edtNbMotsCleRecents->Validate());
    cubLogDebug("Validate() sur le validator : %d", m_edtNbMotsCleRecents->GetValidator()->Validate(m_edtNbMotsCleRecents));
 
    bool retValidate = m_edtNbMotsCleRecents->GetValidator()->Validate(m_edtNbMotsCleRecents);
    if (retValidate) {
        SauveValeurs();
        EndModal(wxID_OK);
    }
}
 


cubLogDebug() est juste une macro qui appelle wxLogMessage pour avoir des traces.

Si j'essaie de saisir directement des lettres dans m_edtNbMotsCleRecents : j'obtiens un bip et la lettre n'est pas saisie --> ok !

En revanche, si je colle une valeur textuelle et que je valide la fenêtre par ok, voici les traces que j'obtiens :

Code:

[2010-07-24 19:19:56] : DEBUG - alb_paramDlg.cpp:00320 - WxStdDialogButtonSizer1OkClick() -
[2010-07-24 19:19:56] : DEBUG - alb_paramDlg.cpp:00321 - WxStdDialogButtonSizer1OkClick() - Validate() global : 1
[2010-07-24 19:19:56] : DEBUG - alb_paramDlg.cpp:00322 - WxStdDialogButtonSizer1OkClick() - Validate() sur le wxTextCtrl : 1
[2010-07-24 19:19:57] : DEBUG - alb_paramDlg.cpp:00323 - WxStdDialogButtonSizer1OkClick() - Validate() sur le validator : 0

Autrement dit, on n'obtient pas d'erreur en appelant Validate() sur le dialogue, ni même en appelant Validate() sur le wxTextCtrl. Pour avoir un contrôle effectif, il faut appeler Validate() sur le validator de chaque champ, un par un.
Sachant que j'ai 9 champs avec ce même validator, et que je devrais en avoir plus encore par la suite, ce n'est pas très efficace, et surtout cela me semble en contradiction avec le comportement "officiel" des wxValidator sur un wxDialog.

Où est-ce que j'ai raté quelque chose ???

Précision : je crée un seul wxValidator que je passe à tous mes champs de saisie de nombres. Soupçonnant que cela pouvait peut-être être la cause de mes problèmes, j'ai changé provisoirement le code pour n'utiliser le wxValidator que sur le champ m_edtNbMotsCleRecents --> cela n'a rien changé au résultat constaté.
Sem (Membre)
Inscrit le : 31-05-2008
Messages: 64
Snippets: 0
Tutoriels: 0
Hors ligne
coucou,
as tu essayé de mettre le flag wxWS_EX_VALIDATE_RECURSIVELY à ton dialogue ?
Sem
cubbiste (Membre)
Inscrit le : 14-07-2010
Messages: 11
Snippets: 0
Tutoriels: 0
Hors ligne
Sem:
as tu essayé de mettre le flag wxWS_EX_VALIDATE_RECURSIVELY à ton dialogue ?
Oui, j'avais essayé, cf. l'extrait de code d'hier :

Code wxWidgets:

alb_paramDlg::alb_paramDlg(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style | wxWS_EX_VALIDATE_RECURSIVELY)
{
...
}

Et ça ne marchait pas, parce que wxWS_EX_VALIDATE_RECURSIVELY est un extra style !
Voici la nouvelle version :

Code wxWidgets:

alb_paramDlg::alb_paramDlg(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
    SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
    CreateGUIControls();
    ChargeValeurs();
}

Et là, ça marche.
Voici le résultat dans les traces si je colle une valeur textuelle dans le champ m_edtNbMotsCleRecents :

Code:

[2010-07-25 07:59:25] : DEBUG - alb_paramDlg.cpp:00321 - WxStdDialogButtonSizer1OkClick() -
[2010-07-25 07:59:26] : DEBUG - alb_paramDlg.cpp:00322 - WxStdDialogButtonSizer1OkClick() - Validate() global : 0
[2010-07-25 07:59:26] : DEBUG - alb_paramDlg.cpp:00323 - WxStdDialogButtonSizer1OkClick() - Validate() sur le wxTextCtrl : 1
[2010-07-25 07:59:28] : DEBUG - alb_paramDlg.cpp:00324 - WxStdDialogButtonSizer1OkClick() - Validate() sur le validator : 0


Il reste un truc bizarre : l'appel direct de Validate() sur le wxTextCtrl continue à retourner true. Peut-être vaudrait-il aussi lui donner le style wxWS_EX_VALIDATE_RECURSIVELY ?
Mais le Validate() du dialog retourne false, et c'est ce qu'il me faut.

Autre remarque : s'il y a plusieurs champs avec des valeurs incorrectes, seul l'un d'entre eux est signalé à l'utilisateur, en lui donnant la valeur mais sans lui dire quel est le champ concerné. Ce n'est pas idéal comme comportement, mais pour un comportement de défense sur des erreurs de saisie, cela ira bien ...

Merci pour ton retour Sem, qui m'a permis de creuser plus loin dans la bonne direction.

Dernière modification par cubbiste (25-07-2010 07:57:55)

Sem (Membre)
Inscrit le : 31-05-2008
Messages: 64
Snippets: 0
Tutoriels: 0
Hors ligne
bonjour,
pour ta remarque, il me semble que le Validate() s'il retourne false fera un focus sur le premier control du dialogue posant un problème.

Pour le Validate sur le wxTextCtrl retournant true, voici le code :

Code wxWidgets:

 
bool wxWindowBase::Validate()
{
#if wxUSE_VALIDATORS
    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
 
    wxWindowList::compatibility_iterator node;
    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
    {
        wxWindowBase *child = node->GetData();
        wxValidator *validator = child->GetValidator();
        if ( validator && !validator->Validate((wxWindow *)this) )
        {
            return false;
        }
 
        if ( recurse && !child->Validate() )
        {
            return false;
        }
    }
#endif // wxUSE_VALIDATORS
 
    return true;
}

donc c'est normal que cela renvoi 1,
Sem

Dernière modification par Sem (25-07-2010 12:24:04)

Menu Snippets (navigation):
Pages: 1    Accueil » Snippets » Chaînes de caractères
» wxTextCtrl + wxTextValidator : N'autoriser que certains caractères