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 :

Trier un QTableWidget sur plusieurs colonnes


Sujet :

Qt

  1. #1
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2015
    Messages
    252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2015
    Messages : 252
    Points : 272
    Points
    272
    Par défaut Trier un QTableWidget sur plusieurs colonnes
    Bonjour,

    je cherche comment trier un QTableWidget sur plusieurs colonnes.
    J'ai 2 colonnes NOM et GROUPE. Je veux trier soit
    par NOM et GROUPE
    par GROUPE et NOM
    A la rigueur une solution simple est de créer 2 nouveaux QTableWidgetItem et d'y concaténer les 2 colonnes une fois avec NOM en tête, et l'autre fois avec GROUPE en tête.

    Sauf que cette solution ne permet pas d'obtenir le résultat que je cherche : le problème est avec le tri par GROUPE décroissant. Je veux en effet que les groupes soient décroissants mais je veux que les noms restent croissants dans ce tri.
    Autrement dit, je veux afficher
    GROUPE2 NOM A
    GROUPE2 NOM B
    GROUPE1 NOM X
    GROUPE1 NOM Y... si on préfère, la requête serait ici ORDER BY groupe DESC, nom ASC.

    Pas de QTableView SVP.
    Merci.

  2. #2
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2015
    Messages
    252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2015
    Messages : 252
    Points : 272
    Points
    272
    Par défaut
    Bon,

    après avoir bien regardé sur internet sans trouver de méthode adaptée au QTableWidget, j'ai transposé une vieille méthode que j'ai dû développer, il y a plusieurs années, dans les TStringGrids de Lazarus quand je travaillais sur le composant natif. D'ailleurs, j'ai totalement transposé le fonctionnement.

    J'ajoute une QTableWidgetItem réservée au tri que j'utilise systématiquement quelque soit le ui->table->horizontalHeader()->sortIndicatorSection()
    Cet Item est construit à chaque changement de SortIndicatorSection.
    Dans le cas que j'évoquais, l'item de tri comprend le Groupe et une méthode InvertLetters(Nom)... Le InvertLetters commence par mettre les lettres (en Latin et) en majuscules et renverse une à une les lettres dans la pile 65-90 des valeurs ASCII :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     c = s.at(i);
     d_ascii =  c.toLatin1();
     if (d_ascii < 78)
         f_ascii = 90- (d_ascii -65);
     else
         f_ascii = 65+ (90 -d_ascii);
     m_res += QString (QChar(f_ascii));
    Cette simple permutation de valeurs ASCII autour du centre de symétrie 77-78 permet d'obtenir l'effet recherché. Donc si je clique sur l'entête de la colonne "Nom", pour un Qt::AscendingOrder, j'obtiens l'équivalent d'un ORDER BY groupe ASC, nom ASC ou dans l'autre sens (DescendingOrder) un ORDER BY groupe DESC, nom ASC évidemment sans recharger la table.
    Compte tenu du fait que la transformation s'exécute en RAM, la latence est acceptable. Il faudrait optimiser le petit bout de code probablement mais pour l'instant cela me conviendra.

    Comme d'habitude, s'il y a mieux je suis preneur : je suis peut être passé à côté de l'essentiel mais au moins le but recherché est atteint.

  3. #3
    Membre habitué
    Homme Profil pro
    Inscrit en
    Juillet 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 107
    Points : 189
    Points
    189
    Par défaut
    Salut,
    Drôlement compliqué ta solution.
    Sache que tu peux faire plusieurs sortByColumn à la suite.
    Prends l'exemple "Custom Sort/Filter Model Example" disponible dans la liste des exemples dans QtCreator.
    Dans la fonction createMailModel du main.cpp , remplace les addMail... par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    addMail(model, "GROUPE_1", "NOM_X",
    		QDateTime(QDate(2006, 12, 31), QTime(17, 03)));
    addMail(model, "GROUPE_1", "NOM_Y",
    		QDateTime(QDate(2006, 12, 22), QTime(9, 44)));
    addMail(model, "GROUPE_2", "NOM_A",
    		QDateTime(QDate(2006, 12, 25), QTime(11, 39)));
    addMail(model, "GROUPE_2", "NOM_B",
    		QDateTime(QDate(2007, 01, 02), QTime(16, 05)));
    Puis dans le window.cpp, recherche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    proxyView->sortByColumn(1, Qt::AscendingOrder);
    et ajoute à la suite (donc juste derrière le premier sortByColumn) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    proxyView->sortByColumn(0, Qt::DescendingOrder)
    et tu auras le comportement souhaité.
    Certes c'est du QTableView, mais QTableWidget hérite de QTableView donc cela devrait fonctionner.

  4. #4
    Membre habitué
    Homme Profil pro
    Inscrit en
    Juillet 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 107
    Points : 189
    Points
    189
    Par défaut
    A toi ensuite de gérer ta pile de sortByColumn comme le fait qtitandatagrid : http://www.devmachines.com/qtitandatagrid-overview.html

  5. #5
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2015
    Messages
    252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2015
    Messages : 252
    Points : 272
    Points
    272
    Par défaut
    Bonjour,
    Merci pour ta réponse.

    Citation Envoyé par loupium Voir le message
    Sache que tu peux faire plusieurs sortByColumn à la suite.
    Ah ? Sous quelles conditions ?
    La portabilité View/Widget ? Dans ce cas précis, je ne sais pas. Mes recherches Web sur la question me montrent que l'utilisation d'un QSortFilterProxy est problématique et presque dans tous les cas non fonctionnelle. Ce qui ne signifie pas que cela ne fonctionne pas : ceux qui arrivent à l'utiliser dans ces circonstances n'ont pas de raison de laisser de messages. Mais pour tous ceux qui peinent, la conclusion est presque dans tous les cas : "Utilisez un QTableView à la place d'un QTableWidget." Et dans le cas précis, je ne veux pas de QTableView.

    J'essaierai de dégager le code minimal pour atteindre mon objectif dans l'exemple que tu cites parce que franchement, en l'état, il est tout à fait inexploitable pour mon problème à peu de frais.

    Quant à mon approche, elle ne me semble pas spécialement compliquée et elle est transposable dans n'importe quel langage et indépendante des objets, en tout cas sur des Grids "mémoire". Elle n'est pas nécessairement faite pour Qt mais transposable à peu de frais et en peu de lignes

  6. #6
    Membre habitué
    Homme Profil pro
    Inscrit en
    Juillet 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 107
    Points : 189
    Points
    189
    Par défaut
    Tu réédites tes anciens messages ?
    Car cela fait 2 fois que je vois un message différent !

  7. #7
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2015
    Messages
    252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2015
    Messages : 252
    Points : 272
    Points
    272
    Par défaut
    Les anciens non sauf éventuellement pour corriger l'orthographe mais le dernier oui, cela m'arrive pendant que je teste. J'avais plutôt l'habitude d'utiliser des tchats beaucoup plus interactifs...

    Donc, ta première phrase m'a interpellé. J'ai vu ce cumul de Sort plusieurs fois sur le net. Et je n'y suis pas arrivé.
    J'ai donc retesté.

    Et cela semble fonctionner. Mais il ne faut pas inverser les tris !?
    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
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        int colCount = 2;
        int rowCount = 4;
     
        ui->table->setRowCount(rowCount);
        ui-> table->setColumnCount(colCount);
     
        ui-> table->verticalHeader()->setVisible(false);
        ui-> table->setAlternatingRowColors(true);
     
     
        QTableWidgetItem* item0 = new QTableWidgetItem();
        item0->setText("Nom");
        ui->table->setHorizontalHeaderItem(0,item0);
     
        QTableWidgetItem* item1 = new QTableWidgetItem();
        item1->setText("Groupe");
        ui->table->setHorizontalHeaderItem(1, item1);
     
        ui->table->verticalHeader()->setDefaultSectionSize(24);
     
     
        ui->table->setItem(0,0,new QTableWidgetItem("NOM B"));
        ui->table->setItem(0,1,new QTableWidgetItem("GROUPE X"));
        ui->table->setItem(1,0,new QTableWidgetItem("NOM A"));
        ui->table->setItem(1,1,new QTableWidgetItem("GROUPE X"));
        ui->table->setItem(2,0,new QTableWidgetItem("NOM D"));
        ui->table->setItem(2,1,new QTableWidgetItem("GROUPE Y"));
        ui->table->setItem(3,0,new QTableWidgetItem("NOM C"));
        ui->table->setItem(3,1,new QTableWidgetItem("GROUPE Y"));
     
        ui->table->sortByColumn(0,Qt::AscendingOrder);
        ui->table->sortByColumn(1,Qt::DescendingOrder);
    }
    "Naturellement", j'ai pensé trier les groupes d'abord puis les noms ensuite comme on l'écrit en SQL et l'idée de faire l'inverse ne m'a même pas effleuré . Or visiblement, il faut faire l'inverse.
    Et si cette méthode fonctionne, comment le "cumul" s'arrête-t-il ? Il semble que de placer un ui->table->sortByColumn(0,Qt::AscendingOrder); dans un QPushButton annule le cumul. Ce serait donc la succession immédiate de l'écriture de plusieurs sortByColumn qui déclenche le cumul.

    Encore merci pour ton aide. Il y avait plus simple en effet. Je teste sur mon projet réel.

  8. #8
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2015
    Messages
    252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2015
    Messages : 252
    Points : 272
    Points
    272
    Par défaut
    La succession de ui->table->sortByColumn fonctionne impeccablement sur le projet réel. Encore merci.

  9. #9
    Membre habitué
    Homme Profil pro
    Inscrit en
    Juillet 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 107
    Points : 189
    Points
    189
    Par défaut
    De rien.
    En effet, je m'étais trompé sur l'ordre des sortByColumn.
    Sinon, je me demande s'il n'est pas plus judicieux en terme de performance de désactiver le tri le temps de la configuration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    proxyView->setSortingEnabled(false);
    proxyView->sortByColumn(0, Qt::DescendingOrder);
    proxyView->sortByColumn(1, Qt::AscendingOrder);
    proxyView->setSortingEnabled(true);
    A voir et à test sur de grosse liste.

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

Discussions similaires

  1. [WD18] Excel Ole Automation Trier sur plusieurs colonnes
    Par dany13 dans le forum WinDev
    Réponses: 13
    Dernier message: 04/07/2015, 07h48
  2. [OpenOffice][Tableur] Comment trier numéros sur plusieurs colonnes par ordre croissant
    Par bordelaplage dans le forum OpenOffice & LibreOffice
    Réponses: 8
    Dernier message: 10/04/2015, 23h16
  3. Trier sur plusieurs colonnes
    Par tidusff10 dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 09/06/2012, 19h17
  4. trier un stringgrid sur plusieurs colonnes
    Par renegade55 dans le forum Composants VCL
    Réponses: 2
    Dernier message: 13/12/2005, 16h30
  5. Query sur plusieurs colonnes avec count(distinct...)
    Par Jeankiki dans le forum Langage SQL
    Réponses: 2
    Dernier message: 18/08/2004, 15h22

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