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 :

Couleur de fond d'une cellule. Qt_QTableView_QSqlTableModel


Sujet :

Qt

  1. #1
    Membre confirmé Avatar de gael21
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2016
    Messages : 44
    Par défaut Couleur de fond d'une cellule. Qt_QTableView_QSqlTableModel
    Bonsoir.
    Mon souci ce soir est un souci populaire mais dont les reponses proposées ne s'appliquent pas à mon cas. En tout cas j'y arrive pas. J'ai un QTableView, alimenté par un QSqlTableModel, et je veux que certaines cellules aient un fond de couleur suivant ceertaines conditions. On m'a demandé de ré-implémenter la methode data() et je l'ai fait. Sauf que ca ne marche pas. voicil'implementation de la methode data(), suivi d'une capture d'ecran de mon tableau. Svp aidez moi
    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
    22
     
    QVariant Paiement::data(const QModelIndex &index, int role) const
    {
        int row = index.row();
        int col = index.column();
     
            switch(index.column()){
            case 4: //Column 4
                switch(role){
                case Qt::DisplayRole:
                     return QBrush(Qt::green);
                case Qt::BackgroundRole:
                    if(m_modele->data(m_modele->index(1, 3)) > 20000)
                        return QBrush(Qt::red);
                case Qt::ForegroundRole:
                    if(m_modele->data(m_modele->index(1, 3)) > 20000)
                        return QColor(Qt::black);
                }
             }
            return QVariant();
     
    }
    Nom : Capture1.PNG
Affichages : 428
Taille : 153,9 Ko

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Et si tu travaillais dans l'autre sens, à savoir:
    1. déterminer le role (switch role + case ....)
    2. vérifier si tu es sur la bonne colonne (if(col == XXX) else)
    3. tester la valeur de la donnée (ne pas oublier de fournir une valeur à renvoyer pour le cas où le test de valeur donne false)

    Je sais pas, moi, quelque chose qui serait proche de
    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
    22
    23
    24
     
    QVariant Paiement::data(const QModelIndex &index, int role) const
    {
        int row = index.row();
        int col = index.column();
        switch(role){ 
            case Qt::DisplayRole:
                return QBrush(Qt::green);
            case Qt::BackgroundRole:
                if(col == 4){ // si c'est la colonne 4
                    if(m_modele->data(m_modele->index(1, 3)) > 20000){ // si la valeur est supérieure à 2000
                        return QBrush(Qt::red);
                    } else { // sinon, quelle couleur va-t-on renvoyer ? blanc?
                       return  QBrush(Qt::white);
                    }
               }else{ si c'est pas la colonne 4, on utilise le blanc
                   return  QBrush(Qt::white);
               }
            /* ... */
         }
     
            return QVariant();
     
    }
    Mais attention, avec cette logique qui prend en compte la colone, il n'y aura que la colone 4 dont la couleur de fond changera. Ce n'est pas impossible, mais ne serait-il pas "plus visible" de faire changer la couleur de fond de toute la ligne

    Soyons clairs : je ne fais qu'exprimer ce qui ressort de ton code d'origine et la question qu'il me fait me poser. La réponse ne m'intéresse que très moyennement (dans le sens où cela nécessitera peut-être une modification de la logique), et dépend de tes propres souhaits
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Ce membre m_modele ne me dit rien de bon. Si tu redéfinis la fonction membre virtuelle data(), c'est que tu te situes (normalement, à moins qu'il s'agisse d'une classe Proxy) dans la classe qui hérite de QSqlTableModel. Et le modèle que tu devrais manipuler, c'est l'instance courante et non un membre.

    Ensuite, le role Qt::DisplayRole demande ce qui va être affiché comme texte. Là tu renvoies un QBrush. Et puisqu'il est question de « couleur de fond », c'est Qt::BackgroundRole qu'il faut utiliser. Qt::ForegroundRole représente la couleur du texte. Tu peux regarder le documentation de l'énumération Qt::ItemDataRole pour voir les différents roles.

    index(1, 3) représente le même élément (le montant d'EXAM dans ton aperçu), ceci peu importe la case à colorer considérée. C'est l'index en paramètre de la fonction qu'il te faut utiliser (à moins que ce soit vraiment ce que tu veux, mais j'en doute).

    Enfin, si tu veux pouvoir visualiser correctement les autres éléments, ne renvoie pas un QVariant() vide à la fin, fait appel à la fonction membre de la classe mère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return /*LaClasseDontTuHérites*/::data(index, role);
    qui appliquera le traitement par défaut.
    Dernière modification par Invité ; 19/07/2019 à 00h43.

  4. #4
    Membre confirmé Avatar de gael21
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2016
    Messages : 44
    Par défaut
    Bonsoir.
    Je vous remercie pour votre soutien.
    Koala01, J'ai suivi la logique inversée que tu m'as recommandé, en me servant de l'exemple que tu m'as donné. Sauf que ça ne marche pas. C'est vrai que l'idéal serait de changer la couleur de fond de toute une ligne. Mais je ne n'arrive même pas à changer pour une seule cellule.
    Je pense que mon problème c'est dans la façon d'utiliser cette méthode après.
    J'aimerai savoir si cette méthode data(index, role) est du même style que QPainter::paint(), ou encore QWidget::mousePressEvent(QMouseEvent *e), c-a-d qu'une fois qu'on la redéfinit, on n'a plus besoin de l'appeler plus loin car elle fait directement son taf en coulisse.

    Winjerome, je n'ai pas hérité de QSqlTableModel. en fait, mon m_modele est une instance directe de cette classe, sans héritage. Je me sens le plus à l'aise avec cette classe pour parcourir une table de ma base de données, comparé à un QStandardItemModel où je ne sais rien du tout, malgré qu'elle offre plus de flexibilité.
    index(1, 3) est juste un index que j'ai pris à la volé pour illustrer mon problème.
    Mais pour le return de la méthode data(index, role), je sèche là bas car n'ayant pas hérité de QStandardItemModel ou de QItemDelegate/QStyledItemDelegate ou de quelque chose du genre, je me demande comment je peux faire un return comme tu me l'as recommandé sans avoir de classe mère.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par gael21 Voir le message
    J'aimerai savoir si cette méthode data(index, role) est du même style que QPainter::paint(), ou encore QWidget::mousePressEvent(QMouseEvent *e), c-a-d qu'une fois qu'on la redéfinit, on n'a plus besoin de l'appeler plus loin car elle fait directement son taf en coulisse.
    Oui c'est du même acabit.

    Citation Envoyé par gael21 Voir le message
    Winjerome, je n'ai pas hérité de QSqlTableModel. en fait, mon m_modele est une instance directe de cette classe, sans héritage.
    Si tu n'hérites pas d'une classe Qt qui possède déjà cette fonction membre data(), alors tu n'effectues aucune redéfinition, et la tienne ne sera jamais appelée.
    Ta tableView récupère les données à afficher en appelant la fonction membre data() de son modèle pour chacune des cases (index) et roles.

  6. #6
    Membre confirmé Avatar de gael21
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2016
    Messages : 44
    Par défaut
    Ca craint!
    La classe QSqlTableModel hérite de la méthode data(index, role) de la classe QAbstractItemModel. Et puisque j'utilise directement une instance de QSqlTableModel, je pensais pouvoir avoir aussi accès. Mais s'il te plaît, peux-tu me dire comment faire dans mon cas?
    Et pour ce que ca vaut, la classe qui gère mon affichage hérite de cette classe(QSqlTableModel).
    voici l'un des header que j'utilise pour afficher mes tableaux. Leurs structures sont identiques
    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
    22
    23
    24
    25
    26
     
    #include <QSqlTableModel>
    #include <QString>
    #include <QDebug>
    #include <QSqlRelationalTableModel>
    #include <QHeaderView>
    #include <QSqlError>
    #include <QSqlQuery>
    #include <QTableView>
    #include <QObject>
     
    class Nom_Code_List_Paie : public QSqlTableModel
    {
        Q_OBJECT
    public:
        explicit Nom_Code_List_Paie(QString nom, int code, QString table,
                  QTableView *tableView, QSqlTableModel *modele);
        virtual ~Nom_Code_List_Paie();
        QVariant data(const QModelIndex &index, int role = Qt::BackgroundRole) const;
     
    private:
        QString m_nom, m_table;
        int m_code;
        QTableView *m_tableView;
        QSqlTableModel *m_modele;
    };

  7. #7
    Invité
    Invité(e)
    Par défaut
    Alors non, c'est une classe à part qu'il te faut utiliser.
    On va partir sur l'héritage de la classe QIdentityProxyModel qui reste le plus simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class BackgroundProxyModel : public QIdentityProxyModel {
    public:
        BackgroundProxyModel(QObject *parent = nullptr) : QIdentityProxyModel(parent) {}
     
        QVariant data(const QModelIndex &index, int role/* attention à ne pas changer la valeur par défaut */) const override {
            // note : s'il s'agit du montant, (toujours selon l'aperçu) c'est l'indice 3 (base 0)
            if (index.column() == 3 && role == Qt::BackgroundRole) {
                if(index.data() > 20000) {
                    return QBrush(Qt::green);
                }
            }
            return QIdentityProxyModel::data(index, role);
        }
    };
    Puis, là où tu instancies ton QSqlTableModel et le donnes en modèle à ton tableView, tu modifies le code en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    auto model = new QSqlTableModel(/*...*/);
     
    auto proxyModel = new BackgroundProxyModel(tableView);
    proxyModel->setSourceModel(model);
    tableView->setModel(proxyModel); // on donne le proxy à la place du modèle
    Ce proxy, qui utilise en interne le QSqlTableModel, va servir d'intermédiaire en récupérant les données de ce modèle et fournissant les données modifiées par ton code au tableView.

  8. #8
    Membre confirmé Avatar de gael21
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2016
    Messages : 44
    Par défaut
    Bonsoir et merci Jérôme
    ton message résout mon problème.
    Mais s'il te plais j'ai un petit truc que me dérange. Dans ma classe BackgroundProxyModel, j'ai ajouté une méthode qui récupère une valeur contenue dans une autre table, et me sers de cette valeur comme condition pour modifier la couleur de fond d'une ligne(c'est plus intéressant de colorier toute la ligne. Cependant, ma méthode n'a pas l'air d'être exécutée. pour m'en rassurer, j'ai ajouter un qDebug() dans le cas où elle s'exécute et dans le cas où elle ne s'exécute pas. Mais je ne reçois aucun des deux messages. Du coup j'aimerai savoir pourquoi.
    en fait, j'ai ajouté un attribut au constructeur de cette classe. et cet attribut n'est rien d'autre que le matricule d'un eleve précis. Et ma méthode est là pour utiliser ce matricul pour interroger au moyen d'une requête SQL une table afin de recupérer une valeur que j'ai appelé m_code. et c'est cette valeur que je veux utiliser pour conditionner la coloration des lignes.
    voici le header de ma classe, suivi de l'implémentation de cette methode.
    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 <QIdentityProxyModel>
    #include <QVariant>
    #include <QBrush>
    #include <QSqlQuery>
    #include <QWidget>
    #include <QDebug>
    #include <QString>
    class BackgroundProxyModel : public QIdentityProxyModel
    {
     public:
        BackgroundProxyModel(int mat, QObject *parent = NULL);
     
        QVariant data(const QModelIndex &index, int role) const override;
        int get_valeur_code();
     
        ~BackgroundProxyModel();
     
     private:
        int m_matricule, m_code;
    };
    et la methode
    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
    22
    23
    24
     
    int BackgroundProxyModel::get_valeur_code()
    {
        QString str_code = " SELECT code FROM eleve "
                                "WHERE code_elev = ?;";
        QSqlQuery req_code;
        int valeur(0);
        req_code.prepare(str_code );
        req_code.addBindValue(m_matricule);
        if(req_code.exec())
        {
            if(req_code.first())
            {
                valeur = req_code.value(0).toInt();
                qDebug()<<"cest     bon";
    //deja ceci ne marche pas qDebug()<<req_code.lastError().text();
            }
        }
        else
            qDebug()<<"cest    pas    bon";
     
     
        return valeur;
    }

  9. #9
    Invité
    Invité(e)
    Par défaut
    Il peut y avoir deux causes :

    • soit tu ne passes plus par ce proxy et passes de nouveau (depuis la résolution du problème précédent) directement par le modèle d'origine,
    • soit (plus probable à mon avis) il n'y a pas d'élément correspondant dans la table, et la condition if(req_code.first()) est fausse. Tu n'affiches rien en passant par ce chemin .


    Plutôt que des qDebug(), place un point d'arrêt (breakpoint) au début de ta fonction. Cela te permettra en premier lieu de voir si elle est exécutée (le programme s'arrêtera dessus), puis au pas à pas de voir quel chemin est emprunté. Voir le tutoriel Le débogage d'une application : méthodes et exercices à ce sujet.

  10. #10
    Membre confirmé Avatar de gael21
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2016
    Messages : 44
    Par défaut
    Bonjour et merci pour le lien concernant le debeuggage
    J'ai lu la documentation de QIdentityProxyModel et on me fait comprendre que cette classe ne fait AUCUN TRI, NI FILTRAGE. Du coup je me dis que c'est pour cette raison que le code SQL n'est pas exécuté. Mais je suis en train de lire le document du lien que tu m'as envoyé, et je pense que je vais regarder de ce côté et dans le cas échéant, je pousserai les recherches.
    Toutefois, mon problème d'origine étant résolu grâce toi (Jérôme) et Koala01, Je tiens à vous remercier. Merci vraiment et à bientôt.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 26/08/2010, 09h20
  2. Modifier couleur de fond d'une cellule d'un tableau dynamiquement.
    Par fred61 dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 27/03/2009, 03h19
  3. Couleur de fond d'une cellule variable
    Par Cafu3 dans le forum Débuter
    Réponses: 2
    Dernier message: 19/03/2009, 11h56
  4. [VB.NET][DataGridView]:couleur de fond d'une cellule
    Par BigTicket42 dans le forum Windows Forms
    Réponses: 8
    Dernier message: 13/05/2008, 23h07
  5. mise à jour de la couleur de fond d'une cellule
    Par Lady_jade dans le forum Général JavaScript
    Réponses: 10
    Dernier message: 02/11/2005, 12h18

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