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

C++Builder Discussion :

Bug ajout d'une ligne dans un StringGrid [Débutant]


Sujet :

C++Builder

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2010
    Messages
    265
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 265
    Points : 108
    Points
    108
    Par défaut Bug ajout d'une ligne dans un StringGrid
    J'ai cherché pendant deux heures hier soir en vain pour trouver l'origine de ce bug très personnel, donc je me permet de mettre le code ici :
    Voici ce qui se passe :

    J'ai un StringGrid qui affiche les données contenues dans un fichier texte comme ceci:


    Quand je clique sur un bouton via un menu, je souhaite pouvoir ouvrir une nouvelle fiche vide comme ceci:



    J'ai simplement fait ceci via ce code:

    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
    void __fastcall TForm1::Nouveaufichier1Click(TObject *Sender)
    {
                     AdvStringGrid1->FixedRows=1;
                     AdvStringGrid1->RowCount=2;
                     for (int vide2=0;vide2<AdvStringGrid1->ColCount;vide2++)
                     {
                     for(int vide=1;vide<AdvStringGrid1->RowCount;vide++)
                     {
                      AdvStringGrid1->Cells[vide2][vide]="";
                     }
                     }
                     		TReplaceFlags Flags = Flags << rfReplaceAll;
     
    		AnsiString T1 = "Qualité\n";
    		AnsiString T2 = "Prénom\n";
    		AnsiString T3 = "Nom\n";
                    AnsiString T4 = "Poste\n";
                    AnsiString T5 = "Email\n";
                    AnsiString T6 = "Prononciation\n";
     
     
    		AnsiString N =  T1 + T2 + T3 + T4 + T5 + T6;
                    AdvStringGrid1->Rows[0]->Text = N;
    }
    le problème c'est que quand je clique 4 fois sur le bouton pour ajouter une ligne il me met ceci:



    Il me met donc 2 lignes de la fiche précédente...

    voici le code que j'utilise pour créer une nouvelle ligne:

    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
    void __fastcall jStringGrid::AddRow(int Index)
    {
     
    /*Déplace une ligne à une nouvelle position.
     
    void __fastcall MoveRow(int FromIndex, int ToIndex); */
    /*Appelez la méthode MoveRow pour déplacer la ligne d'indice FromIndex à la position spécifiée par le paramètre ToIndex.*/
    RowCount++;
    MoveRow(RowCount-1, Index);
    }
     
     
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    ( (jStringGrid*)AdvStringGrid1 )->AddRow(AdvStringGrid1->RowCount); // ajout de la nouvelle ligne à la "dernière ligne"
     
    }
    Sachant que dans le .h il y a donc la classe dérivée de StringGrid:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class jStringGrid : public TStringGrid
    {
    private :
        __fastcall jStringGrid(TWinControl *AOwner);
    public :
     
        __fastcall ~jStringGrid();
        void __fastcall AddRow(int Index);
    };
    Solution d'henderson sur un vieux sujet

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 676
    Points : 25 488
    Points
    25 488
    Par défaut
    Attention au AdvStringGrid de TMS en jStringGrid, il est vrai TAdvStringGrid hérite de TBaseGrid qui hérite de TStringGrid, c'est un peu moche ... tant que AddRow n'est pas virtuel, cela ne pose pas de problème mais cela reste moche ! Tu devrais l'appeler TStringGridHack (pour indiquer que ce n'est pas une classe a instancier mais juste un contournement)

    Tu ne fournis pas le code de AddRow, juste un header mais pas l'implémentation !
    De plus AddRow c'est une méthode tu TAdvStringGrid, tu caches son implémentation ou est-ce pour "hacker" une méthode protégée ?

    Voici une variante en Delphi assez élégante qui utilise le hack des méthodes protégées pour ajouter de nouvelles méthodes

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2010
    Messages
    265
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 265
    Points : 108
    Points
    108
    Par défaut
    Je pensais pas que ça pourrait poser problème. TAdvStringGrid était pour moi un TStringGrid avec un peu plus de propriétés mais héritait des principales

    Pour AddRow: j'ai choppé ça ici en cherchant dans la forum il y a quelques temps:
    http://www.developpez.net/forums/d80...-i-stringgrid/ (solution d'henderson).
    Je l'ai choppé et essayé tel quel je crois. Mais il y a simplement un bug qui revient souvent, c'est que la ligne qu'on ajoute n'est parfois pas vierge et contient les informations d'une autre ligne qu'on a supprimé auparavant par exemple...

  4. #4
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Salut dekalima
    Voici comment inserer detruire bouger une ligne une colonne d'un StringGrid, l'idee est de henderson
    Le .h
    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
    49
     
    //---------------------------------------------------------------------------
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <Grids.hpp>
    //---------------------------------------------------------------------------
    class jStringGrid : public TStringGrid
    {
    public :
        // Les méthodes que je souhaite rendre publiques
        // surchargent les méthodes existantes (celles de TCustomGrid)
        void __fastcall DeleteRow(int ARow);
        void __fastcall DeleteColumn(int ACol);
        void __fastcall InsertRow(int ARow);
        void __fastcall InsertColumn(int ACol);
        void __fastcall MoveColumn(int FromIndex, int ToIndex);
        void __fastcall MoveRow(int FromIndex, int ToIndex);
        // Et dans l'implémentation des ces méthodes
        // Je ferai appel aux méthodes héritées de TCustomGrid
    };
    class TForm1 : public TForm
    {
    __published: // IDE-managed Components
            TStringGrid *StringGrid1;
            TButton *Button1;
            TButton *Button2;
            TButton *Button3;
            TButton *Button4;
            TButton *Button5;
            TButton *Button6;
            void __fastcall Button1Click(TObject *Sender);
            void __fastcall Button2Click(TObject *Sender);
            void __fastcall Button3Click(TObject *Sender);
            void __fastcall Button4Click(TObject *Sender);
            void __fastcall Button5Click(TObject *Sender);
            void __fastcall Button6Click(TObject *Sender);
    private: // User declarations
    public:  // User declarations
            __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    Le .cpp
    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
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
     
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall jStringGrid::DeleteRow(int ARow)
    {
    TCustomGrid::DeleteRow(ARow);
    }
    //------------
    void __fastcall jStringGrid::DeleteColumn(int ACol)
    {
    TCustomGrid::DeleteColumn(ACol);
    }
    //------------
    void __fastcall jStringGrid::InsertRow(int ARow)
    {
    RowCount++;
    TCustomGrid::MoveRow(RowCount-1, ARow);
    }
    //------------
    void __fastcall jStringGrid::InsertColumn(int ACol)
    {
    ColCount++;
    TCustomGrid::MoveColumn(ColCount-1, ACol);
    }
    //------------
    void __fastcall jStringGrid::MoveColumn(int FromIndex, int ToIndex)
    {
    TCustomGrid::MoveColumn(FromIndex, ToIndex);
    }
    //------------
    void __fastcall jStringGrid::MoveRow(int FromIndex, int ToIndex)
    {
    TCustomGrid::MoveRow(FromIndex, ToIndex);
    }
    /*
    Salut !
    Globalement, using, dans cette classe, ne donne rien chez moi (BCB3 Pro).
    Donc je reprends l'idée du transtypage sur une classe dérivée.
    Depuis une classe dérivée, j'ai accès à toutes les méthodes membres.
    Pour ce type d'opération, cette classe n'a besoin ni de constructeur ni de destructeur.
    J'ai rajouté deux méthodes pour insérer une ligne et une colonne qui n'existent pas chez moi (donc au cas où ...)!
    class jStringGrid : public TStringGrid
    {
    public :
        // Les méthodes que je souhaite rendre publiques
        // surchargent les méthodes existantes (celles de TCustomGrid)
        void __fastcall DeleteRow(int ARow);
        void __fastcall DeleteColumn(int ACol);
        void __fastcall InsertRow(int ARow);
        void __fastcall InsertColumn(int ACol);
        void __fastcall MoveColumn(int FromIndex, int ToIndex);
        void __fastcall MoveRow(int FromIndex, int ToIndex);
        // Et dans l'implémentation des ces méthodes
        // Je ferai appel aux méthodes héritées de TCustomGrid
    };
    void __fastcall jStringGrid::DeleteRow(int ARow)
    {
    TCustomGrid::DeleteRow(ARow);
    }
    //------------
    void __fastcall jStringGrid::DeleteColumn(int ACol)
    {
    TCustomGrid::DeleteColumn(ACol);
    }
    //------------
    void __fastcall jStringGrid::InsertRow(int ARow)
    {
    RowCount++;
    TCustomGrid::MoveRow(RowCount-1, ARow);
    }
    //------------
    void __fastcall jStringGrid::InsertColumn(int ACol)
    {
    ColCount++;
    TCustomGrid::MoveColumn(ColCount-1, ACol);
    }
    //------------
    void __fastcall jStringGrid::MoveColumn(int FromIndex, int ToIndex)
    {
    TCustomGrid::MoveColumn(FromIndex, ToIndex);
    }
    //------------
    void __fastcall jStringGrid::MoveRow(int FromIndex, int ToIndex)
    {
    TCustomGrid::MoveRow(FromIndex, ToIndex);
    }
    Il est clair que cette façon de faire n'est pas très pratique à cause du transtypage qu'il faut sans cesse rédiger.
     
    Code :
    ( (jStringGrid*) StringGrid1 )->InsertRow(2);A mon avis, le mieux est d'en faire un composant pour les utilisateurs non familiarisés avec la conception et ma foi ... pour les autres aussi !
    Il leur sera plus facile de rédiger, sans avoir à comprendre ce que l'on y fait :
     
    Code :
    MyStringGrid1->InsertRow(2);J'espère que ça va faire ton bonheur !
    A plus !
    */
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    ( (jStringGrid*) StringGrid1 )->InsertRow(2);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    ( (jStringGrid*) StringGrid1 )->InsertColumn(2);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button3Click(TObject *Sender)
    {
    ( (jStringGrid*) StringGrid1 )->DeleteRow(2);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button4Click(TObject *Sender)
    {
    ( (jStringGrid*) StringGrid1 )->DeleteColumn(2);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button5Click(TObject *Sender)
    {
    ( (jStringGrid*) StringGrid1 )->MoveRow(2, 1);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button6Click(TObject *Sender)
    {
    ( (jStringGrid*) StringGrid1 )->MoveColumn(2, 1);
    }
    //---------------------------------------------------------------------------

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Août 2010
    Messages
    265
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 265
    Points : 108
    Points
    108
    Par défaut
    Merci, mais j'ai toujours un problème :

    Pour ajouter j'utilise:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    ( (jStringGrid*) AdvStringGrid1 )->InsertRow(AdvStringGrid1->RowCount);
    }
    J'ai mis AdvStringGrid1->RowCount pour qu'il me mette la ligne ajoutée toujours à la fin du tableau et pas toujours à l'indice 3 ( par exemple )

    J'ai fait de même pour la suppression:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ( (jStringGrid*) AdvStringGrid1 )->DeleteRow(AdvStringGrid1->Selection.Top);
    Pour que je supprime la ligne sélectionnée.

    Mais ce P*** de problème c'est que quand je prend une ligne pleine et que je la supprime , puis j'ajoute une ligne à la fin, elle apparait mais pas vide !
    Elle contient les infos de celle que je viens de supprimer juste avant!

    Je pense que c'est du à AdvStringGrid1->RowCount ou AdvStringGrid1->Selection.Top car avec 2 par exemple j'ai pas ce problème...
    Tu vois un moyen de remedier à ce problème?


    EDIT: en fait ça flanche aussi avec les simples chiffres par moment,

    Comment on pourrait faire en sorte de vider totalement la ligne qu'il s'apprête à ajouter?

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Août 2010
    Messages
    265
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 265
    Points : 108
    Points
    108
    Par défaut
    Je pense avoir trouvé en faisant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AdvStringGrid1->Rows[AdvStringGrid1->RowCount]->Clear();
    Esperons qu'aucun autre problème ne va survenir

  7. #7
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Je verrais plutot quelque chose comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ( (jStringGrid*) AdvStringGrid1 )->DeleteRow(AdvStringGrid1->RowCount);
    Il sera peut etre necessaire d'ajuster " RowCount - 1 " ou " RowCount + 1 "

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 29/03/2011, 15h05
  2. [C#] Problème d'ajout d'une ligne dans une DataTable
    Par therock dans le forum Windows Forms
    Réponses: 3
    Dernier message: 09/11/2006, 08h27
  3. Ajouter une ligne dans un Stringgrid
    Par jouze dans le forum Composants VCL
    Réponses: 6
    Dernier message: 20/02/2006, 21h40
  4. [C#] Ajout d'une ligne dans un dataset
    Par frechy dans le forum Windows Forms
    Réponses: 9
    Dernier message: 22/12/2004, 09h35
  5. Déplacer la sélection d'une ligne dans un stringgrid
    Par jer64 dans le forum Composants VCL
    Réponses: 5
    Dernier message: 14/03/2003, 00h57

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