IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

QTableItem et validator


Sujet :

Qt

  1. #1
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut QTableItem et validator
    Bonjour à tous,

    Je souhaiterais créer un tableau dont les cellules seraient associées à un Validator.

    Dans un premier temps, j'ai fait en sorte de "transfomer" les cellules de mon tableau en QLineEdit via la méthode setCellWidget, le problème est que le QTable qui contient ce genre de cellule/widget ne semble pas envoyer de signal si l'on modifie l'une de ces cellules/widget.

    Je pense donc qu'il faut plutôt convertir les cellules du tableaux en QTableItem, mais le problème est que je ne sais pas du tout comment définir un Validator pour ce genre de cellule. J'ai bien vu qu'on pouvait récupérer un QLineEdit via la méthode createEditor, mais je ne sais pas quoi en faire. Par exemple j'ai défini un Validator pour le QLineEdit renvoyé par createEditor, mais cela n'a aucun effet.

    Merci d'avance pour vois suggestions

  2. #2
    Membre chevronné

    Inscrit en
    Octobre 2007
    Messages
    234
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 234
    Par défaut
    Si tu crées un QValidator que tu affectes à ton QLineEdit que tu place dans ta cellule avec setCellWidget(), ça ne marche pas ?

    J'ai fait un rapide essai et chez moi les valeurs de la cellule étaient bien restreintes dans les bornes de mon QValidator.

  3. #3
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut
    Bonjour Kinji,

    Si tu crées un QValidator que tu affectes à ton QLineEdit que tu place dans ta cellule avec setCellWidget(), ça ne marche pas ?
    Si, ça marche pour moi aussi, mais le problème est que j'ai besoin de savoir quand une cellule du tableau perd le focus, tout en connaissant la ligne et la colonne du tableau auxquelles elle appartient.

    Pour ce faire je pensais utiliser le signal currentChanged de mon QTable, mais le problème est que pour les cellules du tableau converties en widget, le signal ne se lance pas.

  4. #4
    Membre chevronné

    Inscrit en
    Octobre 2007
    Messages
    234
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 234
    Par défaut
    Donc vu que le signal est pas déclenché avec avec les QLineEdit dans les cells, essaie de dériver QTableItem et réimplémente createEditor un peu comme dans la doc. Dans ton cas il faut créer un QLineEdit auquel tu ajoutes un QValidator.

    Ensuite il doit falloir faire des setItem dans la QTable pour mettre les éléments de ta classe dérivée.

    Bon je dis tout ça à peu près, Qt 3 c'est un peu loin, pour moi.

  5. #5
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut
    Malheureusement pour moi, QT3 est une contrainte imposée.
    Pour répondre à ta suggestion ,j'ai déjà pensé à dériver QTableItem, cependant 2 choses me retiennent de le faire jusqu'à maintenant :

    • La doc nous dit que l'implémentation par défaut de createEditor renvoie un QLineEdit (createEditor) . Donc je me demande si on ne peut pas directement placer le Validator sur le QLineEdit renvoyé par défaut


    • Je ne saisi toujours pas le fonctionnement des QTableItem. A quel moment par exemple doit-on appeler createEditor et setContentFromEditor ?


    The returned widget should preferably be invisible, ideally with QTable::viewport() as parent.
    Ça non plus je ne comprends pas, ça se trouve également dans la doc de la méthode createEditor

  6. #6
    Membre chevronné

    Inscrit en
    Octobre 2007
    Messages
    234
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 234
    Par défaut
    Pour le premier point c'est sur que si c'est possible de récupérer les QLineEdit tu peux y mettre le validator mais je crois pas que ça soit faisable sans faire tes propres QTableItem.

    Pour le second, je pense que c'est Qt qui appelle createEditor() quand il en a besoin, ce qui dépend de l'EditType de la table. (http://qt.developpez.com/doc/3.3/qta...#EditType-enum)

    Donc quand tu dérives QTableItem il faut redéfinir createEditor(), setContentFromEditor() etc. qui sont appelées par Qt pour éditer et mettre à jour la cellule de la table via ton widget d'édition personnalisé.

    Pour la citation de la doc, ça dit que le widget créé pour l'édition devrait être créé invisble et avec pour parent le viewport de la table. A mon avis c'est juste pour avoir un affichage correct, genre le widget ne s'affiche pas trop tôt.

  7. #7
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut
    Ok, merci pour les explications.
    Donc si je comprends bien, même si createEditor renvoie un QLineEdit par défaut, je ne peux pas placer mon Validator sur ce QLineEdit.

    Je suis donc obligé de dériver QTableItem, de redéfinir mon createEditor et setContentFromEditor et d'appliquer mon Validator dans l'une de ces fonctions ?

  8. #8
    Membre chevronné

    Inscrit en
    Octobre 2007
    Messages
    234
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 234
    Par défaut
    Oui je pense qu'il n'y a pas le choix.

  9. #9
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut
    Bon et bien j'ai essayé de dériver QTableItem...mais sans grand succès. Je ne pense pas avoir saisi le mécanisme. Je me suis pourtant basé sur l'exemple de la doc disponible ici

    Voici mon code :
    La déclaration de la classe ValidatedItem qui dérive QTableItem :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #ifndef VALIDATED_IT_H
    #define VALIDATED_IT_H
     
    #include "allheader.h"
     
    class ValidatedItem : public QTableItem
    {
    	private:
    		QLineEdit *le ;
     
    	public:
    		ValidatedItem(QTable *table, EditType et = QTableItem::WhenCurrent) ;
    		virtual QWidget* createEditor() const ;
    		virtual void setContentFromEditor(QWidget *)  ;
    		bool hasAcceptableInput() { return le->hasAcceptableInput() ; } ;
    } ;
     
    #endif
    et son implémentation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include "ValidatedItem.h"
     
    ValidatedItem::ValidatedItem(QTable *t, EditType et)
    	: QTableItem(t, et), le(0)
    {}
     
    QWidget* ValidatedItem::createEditor() const
    {
    	((ValidatedItem*)this)->le = new QLineEdit(table()->viewport()) ;
    	QObject::connect(le, SIGNAL(activated(int)),table(),SLOT(doValueChanged())) ;
    	le->setValidator(new QRegExpValidator(QRegExp("pattern"),le)) ;
    	return le ;
    }
     
    void ValidatedItem::setContentFromEditor(QWidget *w)
    {
    	if(w->inherits("QLineEdit"))
    		setText(((QLineEdit*)w)->text()) ;
    	else
    		QTableItem::setContentFromEditor(w) ;
    }
    Dans le code où j'initialise ma QTable, voici comment j'insère mes ValidatedItem pour la colonne 0 dans l'exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tabData->setItem(rowNumber,0, new ValidatedItem(tabData)) ;
    tabData->setText(rowNumber,0, monTexte) ;
    Je pense que je m'y prend mal dans la dérivation de QTable Item, car dans le slot suivant, l'appel à hasAcceptableInput() provoque un accès illégal à la mémoire.

    A coup de debugger je me rends compte que le QLineEdit de mon ValidatedItem n'est pas instancié, ce qui prouve bien que createEditor n'est jamais appelé.
    Voici le slot ou ce produit l'accès illegal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void WinEdit::checkInput(int row, int col)
    {
    	if(col == 0) 
    	{
    		ValidatedItem *cell = (ValidatedItem *) tabData->item(row,col) ;
    		if(!cell->hasAcceptableInput()) //acces illegal a cet endroit
    		{
    			//traitement de l'erreur
    		}
    	}
    }

  10. #10
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    tabData->setItem(rowNumber,0, new ValidatedItem(tabData)) ;
    tabData->setText(rowNumber,0, monTexte) ;
    tu n'as donc pas que des ValidatedItems.
    Donc cell peut être n'importe quoi.
    Puis un cast à la C c'est pas propre du tout.
    Là j'aurais plutôt utilisé un dynamic_cast et verifié que le résultat n'est pas 0.
    En Qt4, il existe un http://qt.developpez.com/doc/latest/...l#qobject_cast. Je n'ai pas vue si il y as un equivalent avec Qt3. si tu utilise la macro Q_OBJECT tu peut vérifier le nom de la class avec
    http://qt.developpez.com/doc/3.3/qobject.html#className

    Si tu as la possibilité, utilise Qt4 et n'utilise pas visual 6

  11. #11
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut
    J'ai passé un peu de temps pour me me mettre au parfum sur le downcasting en C++ et plus généralement le polymorphisme (une petite révision qui était la bienvenue).

    Donc pour le code contenant le cast pas propre (d'ailleurs je serais curieux de savoir la différence d'un cast à la C et l'utilisation de l'opérateur dynamic_cast), j'ai effectué les modifications qui s'imposaient. Ce qui donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void WinEdit::checkInput(int row, int col)
    {
    	if(col == 0)
    	{
    		ValidatedItem *cell = dynamic_cast<ValidatedItem*>( editWin->tabData->item(row,col)) ;
    		if(cell != 0)
    		{
    			if(!cell->hasAcceptableInput())
    			{
    				//traitement de l'erreur ici
    			}
    		}
    	}
    }
    Cependant cela ne résoud pas mon problème. Le pointeur cell retourné par le dynamic_cast est différent de 0, puis l'appelle à la méthode hasAcceptableInput() provoque l'accès illégal. Comme je l'ai dit précédement, le QLineEdit de ma classe ValidatedItem n'est pas instancié. Donc je dois toujours mal m'y prendre pour la dérivation de QTableItem.

    Puis un cast à la C c'est pas propre du tout
    En fait ce cast m'a été inspiré par le code d'exemple de la doc, donc voici l'extrait concerné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void ComboItem::setContentFromEditor( QWidget *w )
    {
        // the user changed the value of the combobox, so synchronize the
        // value of the item (its text), with the value of the combobox
        if ( w->inherits( "QComboBox" ) )
            setText( ( (QComboBox*)w )->currentText() );
        else
            QTableItem::setContentFromEditor( w );
    }
    Si tu as la possibilité, utilise Qt4 et n'utilise pas visual 6
    , personnellement je souhaiterais utiliser QT4 et développer sous code::blocks, mais QT3 et VisualC++ 6 me sont imposés, à moi de m'adapter...

  12. #12
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par M@t67 Voir le message
    Donc pour le code contenant le cast pas propre (d'ailleurs je serais curieux de savoir la différence d'un cast à la C et l'utilisation de l'opérateur dynamic_cast), j'ai effectué les modifications qui s'imposaient.
    un cast a la C fait un cast brut sans aucune vérification. Tu peut caster un pointeur vers int en un pointeur vers ValidatedItem...


    Cependant cela ne résoud pas mon problème. Le pointeur cell retourné par le dynamic_cast est différent de 0, puis l'appelle à la méthode hasAcceptableInput() provoque l'accès illégal.
    tu as bien le rtti d'activé dans les option de compilation de visual 6

    En fait ce cast m'a été inspiré par le code d'exemple de la doc, donc voici l'extrait concerné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void ComboItem::setContentFromEditor( QWidget *w )
    {
        // the user changed the value of the combobox, so synchronize the
        // value of the item (its text), with the value of the combobox
        if ( w->inherits( "QComboBox" ) )
            setText( ( (QComboBox*)w )->currentText() );
        else
            QTableItem::setContentFromEditor( w );
    }
    Il verifie avant de caster par w->inherits( "QComboBox" ).
    En ajoutant la macro Q_OBJECT à ta class tu pourra faire pareil.

    Comme je l'ai dit précédement, le QLineEdit de ma classe ValidatedItem n'est pas instancié
    comment cela?

  13. #13
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut
    tu as bien le rtti d'activé dans les option de compilation de visual 6
    oui

    comment cela?
    Dans ma classe ValidatedItem, j'ai un attribut QLineEdit que j'ai appelé le (cf code). C'est à cet attribut que je souhaiterais affecter mon Validator. Il se trouve que ce QLineEdit n'est jamais instancié, d'où l'erreur de violation d'accès mémoire.

    D'après les messages précédents de Kinji, la méthode createEditor serait automatiquement appelée par QT au moment de l'appelle de setItem sur ma QTable, hors ça n'est pas le cas.

    Petit rappel pour éviter qu'on s'égare de trop, ma question est simple :
    comment affecté un QValidator à une cellule d'un QTable ?

  14. #14
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par M@t67 Voir le message
    Dans ma classe ValidatedItem, j'ai un attribut QLineEdit que j'ai appelé le (cf code). C'est à cet attribut que je souhaiterais affecter mon Validator. Il se trouve que ce QLineEdit n'est jamais instancié, d'où l'erreur de violation d'accès mémoire.
    Le dynamic_cast ne semble pas fonctionner . Je sais qu'il y as des problème avec VC6. Essaye d'ajouter la macro Q_OBJECT et utilise inherits("ValidatedItem") avant de faire le cast.

    Tu devrais blinder cette fonction dans le cas ou le est == 0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool hasAcceptableInput() { return le->hasAcceptableInput() ; }
    Si tu compile l'example http://qt.developpez.com/doc/3.3/sta...s-example.html, ca fonctionne?

    Tu compile en debug? as tu essayer du pas à pas?

    De ce que je voie, ton code semble correct.

    Y as juste le
    ((ValidatedItem*)this)->le dans un fonction const que je trouve immonde , y as le mots clef mutable pour cela. Mais c'est dans les exemples de Qt3....

  15. #15
    Membre confirmé Avatar de Mic75
    Homme Profil pro
    Développeur Frontend
    Inscrit en
    Janvier 2006
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur Frontend
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 143
    Par défaut
    J'ai identifié le problème : createEditor était bien appelée, le fait est que checkInput l'était avant, et comme elle provoquait l'erreur de violation mémoire, l'exécution plantait avant d'atteindre createEditor.

    Dans tous les cas j'ai abandonné la dérivation de QTableItem qui me semble bien trop lourde pour ce que je veux faire, à savoir ajouter un simple QValidator aux cellules d'un QTable.

Discussions similaires

  1. test et validation de votre programme!!!
    Par l'indien dans le forum C
    Réponses: 8
    Dernier message: 25/06/2003, 15h43
  2. validation d'un XML schema
    Par nicolas_jf dans le forum Valider
    Réponses: 2
    Dernier message: 05/05/2003, 11h25
  3. est ce un XSchema Valide?
    Par Slash dans le forum Valider
    Réponses: 4
    Dernier message: 06/03/2003, 14h01
  4. tester si une date est valide
    Par Andry dans le forum Langage
    Réponses: 5
    Dernier message: 17/09/2002, 11h54
  5. [VB6] Evenement validate
    Par grosjej dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 05/09/2002, 15h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo