Partage
  • Partager sur Facebook
  • Partager sur Twitter

Selectionner plusieurs ligne d'un QTableWidget

selectRow(int row) multiple !

Sujet résolu
    6 juillet 2019 à 21:05:40

    Bonjour à tous,

    Je cherche à forcer la sélection de plusieurs ligne de mon QTableWidget.

    J'ai trouvé la methode QTableView::selectRow(int row);

    Ce que je cherche est exactement le principe de selectRow mais avec la possibilité de sélectionner plusieurs lignes, comme un utilisateur peu le faire avec sa souris ou son clavier. en Gros je veux trouver OU créer une méthode du genre selectRows(QVector<int> rows);

    J'ai fouillé la doc  mais soit les méthodes ne correspondent pas a mes attentes, soit je me perd de méthodes en méthodes jusqu'a ne plus savoir ou j'en suis ^^.

    Je suis sur que quelque chose m’échappe, j’ai donc besoin de vous.

    La finalité est la suivante, un utilisateur sélectionne les lignes désirés et effectue une action sur celles-ci. Par exemple l'utilisateur sélectionne la ligne 1,2,6 et 7 et souhaite les descendre d'une position devenant 2,3,7 et 8.

    Le problème c'est que ma sélection reste sur les lignes 1,2,6 et 7. J'aimerais donc forcer la sélection des lignes 2,3,7 et 8 pour suivre l'action demandé, et, laisser la possibilité de faire une nouvelle action sur les même lignes.

    Voici deux fonctions que j'utilise et qui illustre mes propos. Dans la deuxième j'aimerais effectuer la multi sélection énoncer ci-dessus. Pour plus de lisibilité j'ai retiré la gestion des exceptions.

    //Retourne un tableaux d'indexes des lignes selectionnées
    
    QVector<int> m_tableWidget::getRowsSelectedIndexes () const {
        QList<QModelIndex> selectedIndex = this->selectedIndexes();
        QVector<int> rowsIndex;
        for (int i=0; i<selectedIndex.count(); i++) {
            rowsIndex.append(selectedIndex[i].row());
        }
        std::sort(rowsIndex.begin(),rowsIndex.end());
    
        return rowsIndex;
    }



    //Fonction pour monter les lignes sélectionnées d'une position
    
    void upSelectionSlot () {
        QVector<int> rowsSelectedIndexes = ui->tableWidgetFilesList->getRowsSelectedIndexes();
            for (int i=0; i<rowsSelectedIndexes.size();i++) {
                int rowIndex = rowsSelectedIndexes[i];
                QTableWidgetItem *itemToUp = ui->tableWidgetFilesList->takeItem(rowIndex,0);
                QTableWidgetItem *itemToDown = ui->tableWidgetFilesList->takeItem(rowIndex-1,0);
                ui->tableWidgetFilesList->setItem(rowIndex-1, 0, itemToUp);
                ui->tableWidgetFilesList->setItem(rowIndex, 0, itemToDown);
    
                m_file fileToMove = m_filesList[rowIndex];
                m_filesList.removeAt(rowIndex);
                m_filesList.insert(rowIndex-1,fileToMove);
    
                //Je selectionne les lignes avec leur nouvelle position : probleme je ne peux le faire que sur une seule ligne !!!
                ui->tableWidgetFilesList->selectRow(rowIndex-1);
            }
    }


    Merci d'avance

    -
    Edité par Galiroé 6 juillet 2019 à 21:09:30

    • Partager sur Facebook
    • Partager sur Twitter
    Les meilleurs développeurs sont fainéants mais efficace !
      10 juillet 2019 à 16:19:03

      Bonjour,
      Le comportement de selectRow dépend du mode de sélection.  Je crois que dans la plupart des modes il remplace la sélection par la ligne sélectionnée, alors qu'en mode sélection multiple:
      ui->tableWidgetFilesList->setSelectionMode(QAbstractItemView::MultiSelection);
      selectRow ajoute la ligne à la sélection sans toucher à celles déjà sélectionnées. Donc tu pourrais par exemple, changer le mode en MultiSelection au début de la fonction upSelectionSlot() et le remettre à la valeur que tu avais auparavant à la fin de la fonction.
      Tu peux aussi éditer directement la sélection de la vue, puisqu'elle dispose de son propre modèle, renvoyé par QTableWidget::selectionModel. Mais c'est un peu moins pratique à utiliser avec QTableWidget, puisqu'il faut récupérer les QModelIndex pour les passer à la fonction QItemSelectionModel::select et que la fonction indexFromItem qui permet de récupérer le QModelIndex correspondant à un QTableWidgetItem est protected.
      • Partager sur Facebook
      • Partager sur Twitter
        12 juillet 2019 à 12:29:35

        Merci alexisdm !

        J'ai compris mon erreur. En effet j’étais en mode QAbstractItemView::ExtendedSelection.

        J'ai, bêtement, pensé que je pouvais sélectionner plusieurs lignes comme je parvenais à le faire lors de mes tests (souris, clavier)!

        Et naturellement, j'ai cru que select QTableView::selectRow(int row); ne pouvais  sélectionner qu'une ligne à la fois...

        J'ai appliqué ton astuce et grâce au mode multiselection ça fonctionne parfaitement.

        Au sujet des modèles pour éditer la vue. J'avais bien vu cette possibilité dans la doc. Mais la complexité associée à une doc en anglais m’ont complétement égaré sans comprendre le fonctionnement final.

        Pour ma culture Qt, pense tu pouvoir m'expliquer comment faire ?
        • Partager sur Facebook
        • Partager sur Twitter
        Les meilleurs développeurs sont fainéants mais efficace !
          15 juillet 2019 à 15:45:28

          Finalement ce n'est pas si compliqué avec QItemSelectionModel, puisqu'il peut fournir les QModelIndex directement:

          void MainWindow::upSelectionSlot () {
              QItemSelectionModel *selection = ui->tableWidgetFilesList->selectionModel();
              QModelIndexList selectedRows = selection->selectedRows();
              std::sort(selectedRows.begin(),selectedRows.end());
          
              for (QModelIndex row : selectedRows) {
                  int rowIndex = row.row();
                  // Si la ligne est déjà tout en haut ou
                  // si la ligne précédente est déjà sélectionnée (ligne déjà déplacée)
                  // on passe à la ligne sélectionnée suivante
                  if( rowIndex == 0 || selection->rowIntersectsSelection(rowIndex-1, QModelIndex()) )
                      continue;
          
                  // Désélectionne l'ancienne ligne
                  selection->select(row, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
                  QModelIndex previousRow = row.sibling(rowIndex - 1, 0);
          
                  QTableWidgetItem *itemToUp = ui->tableWidgetFilesList->takeItem(rowIndex,0);
                  QTableWidgetItem *itemToDown = ui->tableWidgetFilesList->takeItem(rowIndex-1,0);
                  ui->tableWidgetFilesList->setItem(rowIndex-1, 0, itemToUp);
                  ui->tableWidgetFilesList->setItem(rowIndex, 0, itemToDown);
          
                  m_file fileToMove = m_filesList[rowIndex];
                  m_filesList.removeAt(rowIndex);
                  m_filesList.insert(rowIndex-1,fileToMove);
          
                  selection->select(previousRow, QItemSelectionModel::Select | QItemSelectionModel::Rows);
              }
          }



          • Partager sur Facebook
          • Partager sur Twitter
            17 juillet 2019 à 11:37:45

            Ça fonctionne parfaitement merci !

            Grace à ton exemple j'ai pu utiliser les index dans d'autres parties de mon code (comme la suppression d’éléments sélectionnés).

            Par contre, si ça peu aider quelqu'un, QtCreator n'a pas aimé le :

            //Range-based for loop
            for (QModelIndex row : selectedRows) {
            
                [...]
            
            }

            Donc j'ai ajouté la ligne suivante au .pro de mon projet.

            CONFIG += C++11


            Merci encore pour ton aide

            -
            Edité par Galiroé 17 juillet 2019 à 11:58:55

            • Partager sur Facebook
            • Partager sur Twitter
            Les meilleurs développeurs sont fainéants mais efficace !

            Selectionner plusieurs ligne d'un QTableWidget

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown