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 :

Problème avec QTableWidget


Sujet :

Qt

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut Problème avec QTableWidget
    Bonjour à tous,

    J'ai comme projet de réaliser une zone de saisie qui se présenterai comme Excel. J'ai donc choisi un QTableWidget pour y arriver. Il faut que l'utilisateur puisse réaliser les opérations de base (ajout d'une ligne au dessus, ajout d'une ligne en dessous, suppression d'une ligne, effacer le contenu d'une cellule) tout cela à la souris mais aussi avec le clavier.

    Mon problème se situe dans la suppression d'une ligne. En effet, j'aimerai (cahier des charges..) que quand l'utilisateur appuis sur "Del", si une cellule est sélectionnée alors cela efface le contenu et si une ligne est sélectionnée cela supprime la ligne.

    J'arrive a catcher l'appuis de la touche "Del" (QAction, signal, slot), le clique sur une case SIGNAL(cellCliked(int, int)) de ma QTableWidget et aussi la selection d'une ligne entière SIGNAL(sectionClicked(int)) du verticalHeader de ma QTableWidget. Mais impossible de combiner tout cela pour obtenir le résultat voulu.

    J'y suis arrivé en mettant un booléen à true dans lorsque une ligne est sélectionnée et à false lorsque que c'est juste une cellule. Quand l'utilisateur appuis sur "Del" en fonction du booléen je sais c que je doit faire mais je trouve cela "crade". N'y a t'il pas de moyen plus simple pour savoir dans le slot qui exécute la suppression si c'est une ligne ou cellule qui est sélectionnée?

    Merci d'avance.

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2009
    Messages : 1 009
    Par défaut
    Pas bien, de lier l'événement (clic) à la conséquence de l'état (suppression des sélectionnés), tu auras un problème si l'utilisateur utilise plutôt le clavier ou autre.
    Donc tu as des méthodes pour connaitre les items sélectionnés. Je pense que le plus simple est d'utiliser selectedRanges(). Comme ça ton travail se résume à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    appuiSurSuppr()
    {
        //Je regarde ce qui est sélectionné
        //Si c'est une ligne
        //{
        //    suppression de la ligne du tableau
        //} sinon {
        //    suppression du contenu des cases sélectionnées
        //}
    }

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Merci de ta réponse.

    Néanmoins j'avais déjà essayé cette méthode et je viens de réessayer dans le doute et les résultats ne sont pas ceux souhaités.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void Test::delFct()
    {
      QList<QTableWidgetSelectionRange> ranges = table->selectedRanges();
      std::cout << ranges.size() << std::endl;
    }
    Quand je sélectionne une case : 1
    Quand je sélectionne une ligne : 1
    Quand je sélectionne plusieurs cases ou ligne en cliquant glissant : 1

    Seulement quand je sélectionne des cases ou des lignes en maintenant CTRL que cela passe à 2, 3, .. Une sélection quoi !

    J'ai aussi essayé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void Test::delFct()
    {
      QList<QTableWidgetItem*> ranges = table->selectedItems();
      std::cout << ranges.size() << std::endl;
    }
    J'obtiens toujours zéro peut importe ce que je sélectionne et comment je le fais..

    A moins que je m'y prenne vraiment mal je vois plus quoi faire..

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2009
    Messages : 1 009
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    Néanmoins j'avais déjà essayé cette méthode et je viens de réessayer dans le doute et les résultats ne sont pas ceux souhaités.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void Test::delFct()
    {
      QList<QTableWidgetSelectionRange> ranges = table->selectedRanges();
      std::cout << ranges.size() << std::endl;
    }
    Quand je sélectionne une case : 1
    Quand je sélectionne une ligne : 1
    Quand je sélectionne plusieurs cases ou ligne en cliquant glissant : 1

    Seulement quand je sélectionne des cases ou des lignes en maintenant CTRL que cela passe à 2, 3, .. Une sélection quoi !
    C'est exactement ce à quoi on s'attend, qu'est-ce que tu ne comprends pas dans la notion de "rangée" ? Ce qui t'intéresse c'est combien d'items y'a dans chaque rangée, et s'ils forment des lignes ou non.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Autant pour moi j'ai répondu trop vite. Je viens de jeter un coup d'œil et j'arrive à parcourir les cases sélectionnées de toutes les sélections grâce au code suivant :

    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
     
    void Test::delFct()
    {
      QList<QTableWidgetSelectionRange> ranges = table->selectedRanges();
     
      i = 0;
      while (i < ranges.size)
      {
        int y = ranges[i].topRow();
        while (y <= ranges[i].bottomRow())
        {
           int x = ranges[i].leftColumn();
           while (x <= ranges[i].rightColumn())
           {
             //si il y a quelque chose dans la case
                //j'efface le contenu de la case
             x++;
           }
           //si x + 1 == nombre de colonne et qu'il n'y avait rien dans les cases de la ligne
              //j'efface la ligne
           y++;
        }
      i++;
      }
    }
    Je m'excuse d'avance pour ce code crade mais je devait vous montrez l'endroit ou je bloque. Je n'arrive pas à savoir si la cellule est vierge d'écriture ou non et aussi comment l'effacer.

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2009
    Messages : 1 009
    Par défaut
    Crade en effet, bien compliqué disons

    Une "case" de QTableWidget, c'est soit un widget, soit un item "basique" (QTableWidgetItem). Donc premièrement, choper l'item, deuxièmement choper le texte de l'item.

    Voilà une solution, prémâchée, je me permets étant donné que ce n'est pas compliqué, pour te montrer comment rendre ton code lisible. Si y'a un truc pas clair par contre (après avoir consulté la documentation) il faut le dire.
    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
    void Test::delFct()
    {
        foreach ( const QTableWidgetSelectionRange& range, table->selectedRanges() )
        {
            for ( int row = range.topRow(); row <= range.bottomRow(); row++ )
            {
                if ( range.leftColumn() == 0 &&
                     range.rightColumn() == ( table->columnCount() - 1 ) )
                {
                    table->removeRow ( row );
                }
                else
                {
                    for ( int column = range.leftColumn(); column <= range.rightColumn(); column++ )
                    {
                        QTableWidgetItem* pCase = table->item ( row, column );
                        if ( pCase && !pCase->text().isEmpty() ) // /!\ toujours tester le pointeur car peut être nul = vide
                            delete pCase; // le destructeur de QTableWidgetItem s'occupe de faire ça bien, cf son code
                    }
                }
            }
        }
    }

  7. #7
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Merci beaucoup de ta réponse.

    Crade en effet, bien compliqué disons
    A ce point la?! Mis à part que je déteste les "for" je trouve pas

    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
    void    Test::delFct()
    {
      QList<QTableWidgetSelectionRange> ranges = table->selectedRanges();
     
      int   i = 0;
      while (i < ranges.size())
        {
          int y = ranges[i].topRow();
          while (y <= ranges[i].bottomRow())
            {
              if (ranges[i].leftColumn() == 0 && ranges[i].rightColumn() == table->columnCount() - 1)
                table->removeRow(table->currentRow());
              else
                {
                  int x = ranges[i].leftColumn();
                  while (x <= ranges[i].rightColumn())
                    {
                      //QTableWidgetItem *pCase = table->item(y, x);                                                                                        
                      //if (pCase && !pCase->text().isEmpty())                                                                                              
                      //delete pCase;                                                                                                                       
                      if (table->item(y, x) && table->item(y, x)->text().isEmpty() == false)
                        delete (table->item(y, x));
                      x++;
                    }
                }
              y++;
            }
          i++;
        }
    }
    J'ai changé la ligne 13 car ton code ne permettait pas de supprimer 2 lignes ou plus d'un coup.
    J'ai pas compris aussi pourquoi tu crées un QTabWidgetItem* alors que cela à l'air de fonctionner en manipulant directement la cellule.

    J'ai maintenant un autre problème mais il s'agit plus de questions d'ordre informatique pur donc je pense ouvrir un nouveau topic.

    Merci pour tout.

  8. #8
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2009
    Messages : 1 009
    Par défaut
    Si c'est résolu, alors

    C'est crade dans le sens où c'est très peu lisible, i/x/y, des while au lieu des for... Pour moi un beau code se lit comme un livre De plus, avec Qt il y a des chances qu'un beau code soit optimisé (indépendamment des optimisations qu'un compilateur peut apporter, je ne connais pas le sujet).

    Par exemple, tu appelles l'opérateur [] à chaque fois que tu fais ranges[i], donc tu fais une "recherche" à chaque fois. Le foreach permet de manière élégante de manier une référence sur le résultat d'une recherche faite une fois pour toute (tu as fait la même recherche 6 fois !). Tu as les itérateurs sinon, si tu aimes bien te compliquer la vie ^^. Ou alors tu déclares une référence sur ranges[i] une seule fois...

    Quand tu dis que je "crée" un QTableWidgetItem*, je ne crée rien du tout, je stocke dans une variable le résultat (adresse d'un item) renvoyé par item(y, x). Là tu as fait la même requête 3 fois.

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

Discussions similaires

  1. VC++ Direct3D8, problème avec LPD3DXFONT et LPD3DTEXTURE8
    Par Magus (Dave) dans le forum DirectX
    Réponses: 3
    Dernier message: 03/08/2002, 11h10
  2. Problème avec [b]struct[/b]
    Par Bouziane Abderraouf dans le forum CORBA
    Réponses: 2
    Dernier message: 17/07/2002, 10h25
  3. Problème avec le type 'Corba::Any_out'
    Par Steven dans le forum CORBA
    Réponses: 2
    Dernier message: 14/07/2002, 18h48
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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