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

Langage Delphi Discussion :

Recherche dans un TList<Objet>


Sujet :

Langage Delphi

  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut Recherche dans un TList<Objet>
    Bonjour,

    Suite à une interrogation sur un forum anglophone (vous devriez trouver facilement où), je me suis lancé le défi de répondre à la question : Dessiner des cases à cocher dans une cellule d'un stringgrid.
    Je pense avoir réussi le défi mais, pour cela, j'ai utilisé un simple TList<String> pour mémoriser les cellules devant contenir des cases à cocher.

    pour illustrer :
    Nom : Capture.PNG
Affichages : 269
Taille : 39,2 Ko
    vous remarquerez l'utilisation du style une petite victoire sur les TStyleObject dont je suis assez fier

    J'en viens à la partie langage
    Ma première idée avait été de créer une TList<Cellules> ou cellules était un objet avec 2 propriétés : col et row
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    type 
      TCell = class
        col : integer;
        row: integer;
      public
        contructor create(acol,arow : integer);  
     
    TSelectedCells = TList<TCell>;
    Seulement, je suis "tombé" sur un os, comment savoir si l'objet existe dans ma liste autant avec la TList<String> c'est facile : il suffit de faire un ListeString.indexOf('texte')>=0je n'ai aucune idée de la méthode pour un TCell .
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Bon, comme d'habitude, à peine posée et en guise d'échauffement avant les heures de boulot, je m'y suis mis

    mon "oubli" fut à la déclaration de ma liste.

    Voici une solution :
    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
      TCell = class
        col : integer;
        raw : integer;
      private
        Fischecked: boolean;
        procedure Setischecked(const Value: boolean);
      public
        property ischecked : boolean read Fischecked write Setischecked;
        constructor Create(acol,araw : Integer; ischecked : boolean = false);
      end;
     
      TSelectedCells = class(TList<TCell>)
      public
        function Find(const aCol,araw : integer): Integer;
      end;
     
     
    { TCell }
     
    constructor TCell.Create(acol, araw: Integer; ischecked: boolean=false);
    begin
    col:=acol;
    raw:=araw;
    Fischecked:=isChecked;
    end;
     
    procedure TCell.Setischecked(const Value: boolean);
    begin
      Fischecked := Value;
    end;
     
    { TSelectedCells }
     
    function TSelectedCells.Find(const aCol, araw: integer): Integer;
    begin
    for Result := 0 to Count-1 do
        if (Self[Result].col=aCol) AND (Self[Result].raw=araw) then
          exit;
      Result := -1;
    end;
    Point de détail : utiliser ou non des propriétés pour col et raw ?

    NB.
    J'ai utilisé à dessein un nom de fonction différent de IndexOf.

    Utilisation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     ListeCellulesaveccase:=TSelectedCells.Create([TCell.Create(0,2,true)]);
     
     if ListeCellulesavecCase.Find(0,2)>=0 then ....
    une autre solution serait de créer un comparateur mais cela me semble bien complexe !
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Points : 3 611
    Points
    3 611
    Par défaut
    la remarque qui sert à rien : ne pas confondre row et raw, c'est pas trop pareil et ça peut induire des bogues de cerveau

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 452
    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 452
    Points : 24 863
    Points
    24 863
    Par défaut
    A l'arrache pour le Comparer, surtout que je suis en 10 Seattle, je te le ponds en V11 avec le var inline avec surement une syntaxe approximative

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      TCellComparer = class(TComparer<TCell>)
      public
         function Compare(const Left, Right: TCell): Integer; override;
      end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    //------------------------------------------------------------------------------
    function TCellComparer.Compare(const Left, Right: TCell): Integer;
    begin
      // Le résultat est inférieur à zéro (<0) : Left se placera avant Right car Left est plus vers la gauche ou vers le haut que Right 
      // Le résultat est égal à zéro (=0)      : Left est égal à Right.
      // Le résultat est supérieur à zéro (>0) : Left se placera après Right car Left est plus vers la droite ou vers le bas que Right 
     
      // raw, pprem, je l'ai tellement pensé mais je n'ai rien dit vu mon anglais nullissime
      if Right.row = Left.row then
        Result := Right.col - Left.col 
      else
        Result := Right.row - Left.row ;
    end;


    Exemple d'utilisation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            var LCellArray: TArray<TCell> = FSelectedCells.ToArray();
     
            var LOrderer: TCellComparer = TCellComparer.Create();
            try
              TArray.Sort<TCell>(CellArray, LOrderer);
            finally
              LOrderer .Free();
            end;
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FSelectedCells := TSelectedCells.Create(TCellComparer.Create()); // Paramètre IComparer donc compteur de référence pour la libération
    TCellComparer sera utilisé par Sort et BinarySearch et pas évident à comprendre mais le IndexOf via le TListHelper va aussi utiliser le Comparer
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par pprem Voir le message
    la remarque qui ne sert à rien : ne pas confondre row et raw, c'est pas trop pareil et ça peut induire des bogues de cerveau
    un cas de dyslexie typique de ma part avec la langue de Shakespeare
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    A l'arrache pour le Comparer, ...
    Merci, je ne suis pas sûr de me lancer sur cette piste.
    Franchement cette histoire de cellule avec une case à cocher, c'est tordu
    Toutefois, c'est la première fois que je réussis à utiliser un TStyleObject.
    Bien évidemment, entre temps, je suis tombé sur quelques styles n'utilisant pas un TSyleObject (ni les mêmes noms de stylelookup d'ailleurs) mais un TPath pimenté d'un trigger pour la coche.
    C'est la première fois que je vais pester sur le fait que ce ne soit pas un TStyleObject qui soit utilisé, car obtenir une image à partir de ce style ça va être carabiné !
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  7. #7
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Pour ne pas rester sur un bec avec des styles avec TPath j'ai pondu le 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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject;
      const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF;
      const Row: Integer; const Value: TValue; const State: TGridDrawStates);
    var sb : TFMXObject;
        aRectF : TRectF;
        img : tfmxobject;
    begin
    if Assigned(Stylebook) then sb:=Stylebook.Style  else sb:=TStyleManager.ActiveStyle(Self);
    if Test.find(Column.Index,Row)>=0 then
     begin
        if Test[Test.Find(Column.Index,Row)].ischecked
          then img := sb.FindStyleResource('checkcellstyle.checkboxchecked')
          else img := sb.FindStyleResource('checkcellstyle.checkboxunchecked');
        if assigned(img) then
          begin
            aRectf:=Bounds;
            arectf.Left:=arectf.Right-20; // to adapt
            TStyleObject(img).DrawToCanvas(Canvas,arectf,1);
          end
        else begin
          img:= sb.FindStyleResource('checkcellstyle');
          if assigned(img) then img:=img.FindStyleResource('checkmark');
          if assigned(img) and (img is Tpath) then
           begin
            if Test[Test.Find(Column.Index,Row)].ischecked
              then Tpath(img).Fill.Color:=TColorAnimation(Img.Children[0]).StopValue
              else Tpath(img).Fill.Color:=TColorAnimation(Img.Children[0]).StartValue;
            var bmp:=Tpath(Img).MakeScreenshot;
            aRectf:=Bounds;
            arectf.Left:=arectf.Right-20; // to adapt
            Canvas.DrawBitmap(bmp,Trectf.Create(0,0,bmp.Width,bmp.Height),aRectf,1);
           end;
        end;
        end;
    end;
    dans le cas de ce type style par exemple goldenGraphite.style ou aquagraphite.style
    cela donne ceci
    Nom : Capture.PNG
Affichages : 198
Taille : 18,5 Ko

    maintenant que j'ai obtenu cette première "victoire", cela me conforte dans mon intention d'écrire un nouveau chapitre à mon carnet de plongées dans les Styles FMX
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

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

Discussions similaires

  1. Recherche dans un TList<String> insensible à la casse
    Par SergioMaster dans le forum Langage
    Réponses: 2
    Dernier message: 10/02/2020, 10h04
  2. Rechercher, dans un objet Recordset
    Par jmde dans le forum VBA Access
    Réponses: 7
    Dernier message: 12/12/2009, 01h44
  3. [A-03] Recherche dans objet OLE
    Par zilou1 dans le forum VBA Access
    Réponses: 1
    Dernier message: 21/01/2009, 16h06
  4. recherche par attribut dans une liste d'objet
    Par Jacobian dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 28/05/2008, 21h11
  5. Rechercher un objet dans un tableau d'objet
    Par mikaelm dans le forum Ruby
    Réponses: 6
    Dernier message: 11/06/2007, 17h58

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