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 :

Rafraichissement de la vue QTableView


Sujet :

Qt

  1. #1
    Membre actif
    Avatar de katanaenmousse
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    220
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 220
    Points : 232
    Points
    232
    Par défaut Rafraichissement de la vue QTableView
    Bonjour à tous,

    lorsque je charge un nouveau QSqlQueryModel dans mon QTableView j'obtiens des bugs d'affichage sur les couleurs du fond des lignes du tableau.

    Il est vrai que mon modèle contient 40 colonnes et plus de 40 000 lignes en moyenne et que parfois il peut en contenir jusqu'à 150 000.

    Dans mon modèle j'utilise en plus un code pour changer la couleur du fond des lignes en fonction du contenu de la colonne 38.
    Voici le code utilisé :
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    QVariant ModeleFenTrafic::data(const QModelIndex &index, int role) const {  
         static std::set<int> ligneVertes;
         switch(role) {
             case Qt::BackgroundRole:
     
             int ligneCourante=index.row();
             int lignePrecedente=ligneCourante-1;
             if(lignePrecedente<=0) lignePrecedente=0; 
             if(ligneSuivante>=index.model()->rowCount()) ligneSuivante=index.model()->rowCount(); 
             // je ne m'intéresse qu'à la colonne 38 
             QString valeurPrecedente=index.model()->data(index.model()->index(lignePrecedente,38)).toString();
             QStringvaleurCourante=index.model()->data(index.model()->index(ligneCourante,38)).toString(); 
             if(valeurCourante==valeurPrecedente) 
             {  
                  std::set<int>::iterator it=find(lignesVertes.begin(),lignesVertes.end(),lignePrecedente);
                 if(it!=lignesVertes.end())
                 { 
                      lignesVertes.insert(index.row()); 
                      QBrush newBackground(Qt::green); 
                      return newBackground; 
                 } 
                 else 
                 { 
                      QBrush newBackground(Qt::blue); 
                      return newBackground; 
                 } 
             } 
             else 
             {
                 std::set<int>::iterator it=find(lignesVertes.begin(),lignesVertes.end(),lignePrecedente);
                 if(it!=lignesVertes.end())
                { 
                       QBrush newBackground(Qt::blue); 
                       return newBackground; 
                   }
                   else 
                   {
                       lignesVertes.insert(index.row()); 
                       QBrush newBackground(Qt::green); 
                       return newBackground; 
                    } 
              } 
              break;
         } 
    return QSqlQueryModel::data(index,role); 
    }
    


    pour mettre mon QTableView à jour je fais simplement
    tableau->setModel(monModele);

    Mais là, le modèle est bien chargé, les données sont les bonnes et tout est bien raffraichi dans mon QTableView sauf la couleur des lignes après environ 20 000 lignes (tout se passe bien par contre pour les 20 000 premières lignes environ)

    Après ces 20 000 premières lignes les couleurs de fond des lignes ne correspondent plus.
    Toutefois si je refais remonter les lignes du QTableView avec la molette de la souris, puis que je refais descendre les lignes pour les afficher à nouveau, là, elles sont de la bonne couleur.
    Je pense donc à un problème de raffraichissement de l'affichage.

    Comment résoudre ce souci selon vous? Quelqu'un aurait des pistes?
    Merci à vous


    KatanaEnMousse
    Une fois qu'une réponse qui vous convient a été trouvée à votre sujet, pensez à le mettre en résolu.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Il n'y a rien à faire: une vue de 40 champs pour 40 000 (ou pire, pour 150 000) enregistrements, moi, ca me semble excessif. Ne serait-ce que parce que tu as forcément un(e) pauvre malheureux (se) qui va s'user les yeux à essayer de comprendre toutes les informations que tu lui envoies!

    Et le simple fait de trouver "l'information qui l'intéresse" parmi 40 champs "qui n'ont rien à voir" d'un seul enregistrement, moi, ca me semble pour le moins compliqué. Alors, s'il faut -- en plus -- trouver le seul enregistrement qui l'intéresse parmi 40 000 (ou pire 150 000) autre, tu imagines un peu la galère que cela pourrait être

    S'il s'agissait de traiter dynamiquement tous ces enregistrements, je suis persuadé qu'un ordinateur devrait être capable de le faire. Mais, dés que tu fais entrer un humain dans la danse, je crois sincèrement que tu devrais t'arranger pour que la réponse aux différentes requêtes soit "moins importante".

    Après tout, nous sommes dans le domaine d'une vue, et qui plus est, d'une vue tabulaire. Dés lors, pourquoi veux tu impérativement surcharger cette vue en fournissant les 40 champs pour les 40 000 enregistrements Ne pourrais tu pas envisager de "peaufiner" tes requêtes pour fournir, par exemple, seulement 10 champs pour, mettons, un petit millier d'enregistrements à la fois

    Bien sur, cela signifierait que tu aurais sans doute quatre vues différentes (une pour chaque groupe de 10 champs à montrer), et que tu aurais sans doute 40 à 150 pages par vues (une par groupe de 1 000 enregistrements). Mais cela ne pourrait-il pas très nettement faciliter le travail de la personne qui pose les yeux dessus

    Et, par la même occasion, cela te permettrait de "contourner" le problème du bug à l'affichage, vu qu'il n'y aurait plus jamais 20 0000 lignes à afficher

    Soyons bien clair : je n'ai absolument aucune idée du genre de base de données que tu attaques. Les valeurs que je donnes ici (10 champs pour 1 000 enregistrements) sont tout à fait arbitraires, et sujettes à adaptation de ta part. Mais, de manière générale, il faut toujours te dire que, quand tu arrives au niveau de la vue, il y aura "quelqu'un" qui voudra l'analyser. Et qu'il faut prendre soin de son pauvere malheureux cerveau
    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
    Membre actif
    Avatar de katanaenmousse
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    220
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 220
    Points : 232
    Points
    232
    Par défaut
    Merci Koala pour ta réponse (une fois de plus)

    Il n'y a rien à faire: une vue de 40 champs pour 40 000 (ou pire, pour 150 000) enregistrements, moi, ca me semble excessif. Ne serait-ce que parce que tu as forcément un(e) pauvre malheureux (se) qui va s'user les yeux à essayer de comprendre toutes les informations que tu lui envoies!

    Et le simple fait de trouver "l'information qui l'intéresse" parmi 40 champs "qui n'ont rien à voir" d'un seul enregistrement, moi, ca me semble pour le moins compliqué. Alors, s'il faut -- en plus -- trouver le seul enregistrement qui l'intéresse parmi 40 000 (ou pire 150 000) autre, tu imagines un peu la galère que cela pourrait être
    Je suis moi même habitué à afficher des tableaux plus courts et plus parlants donc en général je te rejoins sur ce point. Toutefois mon code est en fait le code d'un programme que j'ai développé en Python / Gtk et qui a donné lieu à plusieurs versions.
    Celle que les utilisateurs préfèrent est la version qui affiche ce fameux tableau de 100 000 ou 150 000 lignes. les données sont chronologiques et de ce fait l'utilisateur s'y repère simplement avec dans les 40 colonnes toutes les infos qu'il souhaite sans devoir requeter à nouveau la base. c'est un choix qu'a été fait par plus de 340 utilisateurs sur presque 400. Deplus une fonction dans le tableau permet de retrouver un enregistrement spécifique rapidement.
    Pour cette raison je souhaite conserver la possibilité d'afficher les 100 ou 150 000 lignes. Sachant qu'une autre fenetre permet d'afficher une vue par un nombre de lignes maxi défini par l'utilisateur dans les parametres du logiciel.
    Je dis ça pour répondre à ton commentaire tout à fait légitime et que tu comprennes l'importance pour moi d'afficher toutes les lignes.

    Pour revenir à mon problème,
    j'ai lancé un débugage en affichant dans un fichier texte les valeurs de la ligne précédente et de la ligne courante ainsi que le résultat du test de présence de la valeur précédente dans le set.
    Et là j'ai un résultat surprenant. J'ai parfois ceci:
    ligne précédente n° 21572 = "ABCDEF" est dans le set ligneVerte -- ligne courante n° 21573 = "GFTDS" : est différente de précédente - doit être bleue - donc pas d'ajout au set
    ligne précédente n° 21573 = "GFTDS" est dans le set ligneVerte -- ligne courante n° 21574 = "GFTDS" : est égale à précédente - doit être verte - donc ajout au set

    On voit donc bien que la ligne 21573 qui est bleu et n'est pas ajouté au set ne devrait pas se retrouver dans le set lorsque l'on teste la ligne précédente (voir erreur soulignée ci dessus) de la ligne 21574
    Et je ne comprends pas comment elle peut se retrouver dans le set. Surtout qu'avant les 20 000 lignes cette erreur ne se produit pas.
    KatanaEnMousse
    Une fois qu'une réponse qui vous convient a été trouvée à votre sujet, pensez à le mettre en résolu.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par katanaenmousse Voir le message
    Merci Koala pour ta réponse (une fois de plus)



    Je suis moi même habitué à afficher des tableaux plus courts et plus parlants donc en général je te rejoins sur ce point. Toutefois mon code est en fait le code d'un programme que j'ai développé en Python / Gtk et qui a donné lieu à plusieurs versions.
    Celle que les utilisateurs préfèrent est la version qui affiche ce fameux tableau de 100 000 ou 150 000 lignes. les données sont chronologiques et de ce fait l'utilisateur s'y repère simplement avec dans les 40 colonnes toutes les infos qu'il souhaite sans devoir requeter à nouveau la base. c'est un choix qu'a été fait par plus de 340 utilisateurs sur presque 400. Deplus une fonction dans le tableau permet de retrouver un enregistrement spécifique rapidement.
    Pour cette raison je souhaite conserver la possibilité d'afficher les 100 ou 150 000 lignes. Sachant qu'une autre fenetre permet d'afficher une vue par un nombre de lignes maxi défini par l'utilisateur dans les parametres du logiciel.
    Je dis ça pour répondre à ton commentaire tout à fait légitime et que tu comprennes l'importance pour moi d'afficher toutes les lignes.
    Oh, tu sais, moi, je me contentais d'une réflexion d'ordre tout à fait générale sur ce point.

    Si les utilisateur préfèrent s'user les yeux, nous n'allons pas les contredire, hein
    Pour revenir à mon problème,
    j'ai lancé un débugage en affichant dans un fichier texte les valeurs de la ligne précédente et de la ligne courante ainsi que le résultat du test de présence de la valeur précédente dans le set.
    Et là j'ai un résultat surprenant. J'ai parfois ceci:
    ligne précédente n° 21572 = "ABCDEF" est dans le set ligneVerte -- ligne courante n° 21573 = "GFTDS" : est différente de précédente - doit être bleue - donc pas d'ajout au set
    ligne précédente n° 21573 = "GFTDS" est dans le set ligneVerte -- ligne courante n° 21574 = "GFTDS" : est égale à précédente - doit être verte - donc ajout au set

    On voit donc bien que la ligne 21573 qui est bleu et n'est pas ajouté au set ne devrait pas se retrouver dans le set lorsque l'on teste la ligne précédente (voir erreur soulignée ci dessus) de la ligne 21574
    Et je ne comprends pas comment elle peut se retrouver dans le set. Surtout qu'avant les 20 000 lignes cette erreur ne se produit pas.
    Juste par acquit de conscience, quel est le type réel de la donnée qui sert de comparaison Ne serait-ce pas -- à tout hasard -- un float ou un double

    Et, sinon, je viens de constater que tu as choisi d'utiliser un std::set static dans la fonction elle-même, ce qui correspond à l'alternative à l'utilisation d'une donnée membre marquée mutable.

    Se pourrait-il -- à tout hasard -- que tu travailles avec le résultat de deux requêtes qui fournissent deux résultat "presques similaires", à l'exception d'un enregistrement de plus / de moins au alentours du 21 572eme

    Comme tu ne maintiens la liste des lignes qui doivent être colorées que "par le bout des ongles" (au travers d'une seule valeur issue d'un QItemIndex), cela rejoindrait le problème contre lequel j'ai essayé de te mettre en garde lorsque j'ai évoqué la solution: si deux requêtes fournissent des résultats "presque similaires", les éléments placés dans ligneVertes du fait de la première requête resteront dans ligneVertes quand tu traitera le résultat de la deuxième requête.

    Malgré toute l'aversion que je peux comprendre que tu aies et tous les risques liés à cette pratique, as-tu tenté de définir ligneVertes comme étant une donnée membre mutable Cela pourrait peut-être corriger un problème dont tu n'aies même pas forcément conscience et qui serait lié à la création de plusieurs modèles qui partageraient le contenu de ligneVertes de par son aspect static actuel.

    L'étape suivante étant -- bien sur -- de déterminer à quel endroit du code le modèle serait "re créé" de manière injustifiée
    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

  5. #5
    Membre actif
    Avatar de katanaenmousse
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    220
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 220
    Points : 232
    Points
    232
    Par défaut
    merci Koala pour tes précieux conseils, sans toi je n'en serai sûrement pas arrivé jusque là.

    Pour ceci :
    Oh, tu sais, moi, je me contentais d'une réflexion d'ordre tout à fait générale sur ce point.
    Je l'avais bien pris comme tel mais je tenais à t'expliquer pourquoi j'avais fait ce choix particulier.

    pour en revenir au problème de l'affichage des lignes vertes:

    J'ai remplacé le static stc::set par un mutable QList<int>, le problème reste le même...

    Pour ce point :
    si deux requêtes fournissent des résultats "presque similaires", les éléments placés dans ligneVertes du fait de la première requête resteront dans ligneVertes quand tu traitera le résultat de la deuxième requête.
    Je n'ai qu'une requête qui n'est pas renouvelée sans la destruction complète de l'objet qui contient la variable mutable. Donc aucun souci à priori.


    Par contre, suite à ta remarque :
    L'étape suivante étant -- bien sur -- de déterminer à quel endroit du code le modèle serait "re créé" de manière injustifiée
    je me pose la question de savoir si ces erreurs ne pourraient pas être liées à ce bout de code qui sert à remplir mon modèle avec la réponse à la requete Sql:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    monModelSqlQuery.setQuery(requeteSql, connexionBdd);
    while(monModelSqlQuery.canFetchMore())
    {
          monModelSqlQuery.fetchMore();
    }
    Ce bout de code n'aurait il pas des conséquences sur la re creation de mon modèle?
    KatanaEnMousse
    Une fois qu'une réponse qui vous convient a été trouvée à votre sujet, pensez à le mettre en résolu.

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par katanaenmousse Voir le message

    J'ai remplacé le static stc::set par un mutable QList<int>, le problème reste le même...
    Il n'est pas exclu qu'il y ait un bug au niveau des QAbstractItemModel dans Qt à ce niveau là...

    Si oui, il y a fort à parier que c'est un problème qui s'accroche depuis de nombreuses versions, et nous devrions donc pouvoir le retrouver dans le bugtracker, et le seul moyen de l'éviter sera le contournement honteux : éviter d'avoir plus de 20 000 lignes de données à traiter à la fois

    Est-ce que le problème se pose toujours à peu près à partir de la même ligne (à une ou deux centaines près, dirions nous)
    Je n'ai qu'une requête qui n'est pas renouvelée sans la destruction complète de l'objet qui contient la variable mutable. Donc aucun souci à priori.
    Je ne dispose que d'une infime partie de ton code, et je ne connais absolument pas ton projet. Je m'efforce donc d'ouvrir un maximum de voies de réflexion, pour être sur de ne rien "laisser au hasard"
    Par contre, suite à ta remarque :

    je me pose la question de savoir si ces erreurs ne pourraient pas être liées à ce bout de code qui sert à remplir mon modèle avec la réponse à la requete Sql:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    monModelSqlQuery.setQuery(requeteSql, connexionBdd);
    while(monModelSqlQuery.canFetchMore())
    {
          monModelSqlQuery.fetchMore();
    }
    Ce bout de code n'aurait il pas des conséquences sur la re creation de mon modèle?
    A priori, j'aurais tendance à dire que non, car c'est bel et bien la manière conseillée lorsque ton système de base de données n'est pas capable de fournir le nombre d'enregistrements renvoyé par une requête.

    Comme je ne sais déjà pas quelle base de données est utilisée en arrière plan, je ne sais pas s'il y a ne serait-ce que moyen de faire autrement

    Et, quand bien même il y aurait moyen de s'y prendre autrement, je ne vois pas vraiment la raison pour laquelle cette technique se mettrait subitement à partir en couille

    Maintenant, en fonction du système de gestion de base de données que tu utilises, il se peut que tu puisse récupérer le nombre d'enregistrements renvoyés par la requête, et qu'il soit alors "plus facile" de travailler en les récupérant d'une autre manière.

    Bien que je n'y croies pas trop, si tu as cette possibilité, autant l'essayer pour voir si le problème persiste ou non. Mais comme je te l'ai dit, je ne vois pas trop pourquoi la première technique partirait en couille.

    Cependant, je ne participe à Qt que de manière très intermittente et je ne fais absolument pas attention à tous les rapports de bugs qui peuvent être émis. Je n'écarte donc pas non plus la possibilité qu'il y ait un rapport de bug pour lequel le work around consisterait -- en attendant de trouver un correctif au problème -- à utiliser une autre méthode si le système de gestion de base de données est capable d'indiquer le nombre d'enregistrements renvoyés par la requête.

    Autant éviter de fermer la moindre porte avant d'avoir été vérifier précisément ce qui se cache derrière
    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

  7. #7
    Membre actif
    Avatar de katanaenmousse
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    220
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 220
    Points : 232
    Points
    232
    Par défaut
    si oui, il y a fort à parier que c'est un problème qui s'accroche depuis de nombreuses versions, et nous devrions donc pouvoir le retrouver dans le bugtracker, et le seul moyen de l'éviter sera le contournement honteux : éviter d'avoir plus de 20 000 lignes de données à traiter à la fois
    En fait j ai essayé avec 500 lignes en conservant mutable QList<int>
    Résultat même souci
    Je remarque aussi que Certaines cellules ne sont même pas complètement colorées quand je descends l ascenseur du QTableView, ce qui fait penser à un bug d affichage.
    Pour la base c est SQLite et MySQL (selon le choix utilisateur le code modifie les requêtes )
    Bref je vais devoir abandonner la couleur de fond si ça continue... je désespère
    KatanaEnMousse
    Une fois qu'une réponse qui vous convient a été trouvée à votre sujet, pensez à le mettre en résolu.

Discussions similaires

  1. action sans rafraichissement de la vue
    Par pupkri64 dans le forum Struts 2
    Réponses: 12
    Dernier message: 07/02/2013, 20h35
  2. Rafraichissement d'une vue
    Par JPLafrite dans le forum Eclipse Platform
    Réponses: 3
    Dernier message: 01/06/2009, 19h14
  3. Rafraichissement de la vue à partir du bean
    Par Esil2008 dans le forum JSF
    Réponses: 11
    Dernier message: 28/11/2008, 11h31
  4. Rafraichissement vue matérialisée
    Par zach dans le forum Langage SQL
    Réponses: 17
    Dernier message: 31/08/2005, 17h49

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