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

Composants FMX Delphi Discussion :

Grilles, et tri (visuel dans le titre des colonnes)


Sujet :

Composants FMX Delphi

  1. #1
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 135
    Points : 41 300
    Points
    41 300
    Billets dans le blog
    63
    Par défaut Grilles, et tri (visuel dans le titre des colonnes)
    Bonjour,

    Conscient de la critique de Gilles à propos des grilles FMX et comme j'étais sur ma lancée

    , je me suis un peu plus penché sur la question.

    L'objectif, comment modifier l'entête des colonnes de grille sans pour autant créer un style personnalisé ce qui est souvent rébarbatif.

    Donc, contrairement à ce que j'ai pu initier en 2019 https://www.developpez.net/forums/d1...omiser-grille/ , et reporter dans un billet de mon blog
    j'entame une démarche par code

    Vous ne le saviez peut-être pas, mais il est tout à fait possible :
    • de modifier la hauteur du titre ;
    • de modifier sa présentation ;
    • d'ajouter des composants à un entête de colonne.


    Partant de ce principe, je commence à obtenir des résultats
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    /// Changement de hauteur
    procedure TForm131.btnHeaderSizeClick(Sender: TObject);
    var
      Header: THeader;
    begin
      Header:= THeader(StringGrid1.FindStyleResource('header'));
      Header.Height := 40;
    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
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    /// Changement de présentation (globale)
    procedure TForm131.StringGrid1ApplyStyleLookup(Sender: TObject);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
      I: Integer;
    begin
      Header:= THeader((Sender as TStringGrid).FindStyleResource('header'));
      if Assigned(Header) then
        begin
          for I := 0 to pred(Header.Count) do
            begin
              HeaderItem:= Header.Items[I];
              HeaderItem.StyledSettings := HeaderItem.StyledSettings - [TStyledSetting.Size, TStyledSetting.FontColor];
              HeaderItem.Font.Size := 20;
              HeaderItem.FontColor:= TAlphaColors.Blue;
              HeaderItem.TextSettings.HorzAlign := TTextAlign.Center;
              HeaderItem.TextSettings.VertAlign := TTextAlign.Center;
          end;
          Header.Height := 32;
      end;
    end;
    et enfin ajout d'image (ici un tpath)
    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
    procedure TForm131.btnAddPathClick(Sender: TObject);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
    begin
      Header:= THeader(StringGrid1.FindStyleResource('header'));
      if assigned(Header) then HeaderItem:= Header.Items[0];
     
      with Tpath.Create(HeaderItem) do
       begin
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         Data.Data:='M3 13H15V11H3M3 6V8H21V6M3 18H9V16H3V18M22.54 16.88L20.41 19L22.54 21.12'+
                    'L21.12 22.54L19 20.41L16.88 22.54L15.47 21.12L17.59 19L15.47 16.88'+
                    'L16.88 15.47L19 17.59L21.12 15.46L22.54 16.88';
         Width:=Header.Height;
         OnClick:=ClickSort;
       end;
    end;
    Nom : Capture.PNG
Affichages : 287
Taille : 10,6 Ko
    en encadré, ce que j'envisage comme présentation de la partie tri (j'ai opté pour un GridPanelLayout contenant un label pour l'ordre de tri et 3 TPath, l'événement à gérer sera le onclick du GridPanelLayout)

    Pour aller plus loin et rendre les choses plus faciles je me suis même mis en tête de créer un Helper (ma marotte du moment)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     TColumnHelpers = Class helper for TCustomGrid
      public
        procedure SetAColumnAsSortable(const Column : TColumn; const HeaderHeight : Single =0 );
        function IsColumnSortable(const Column : TColumn) : Boolean;
      end;
    Voilà (enfin) ma question, il va me falloir accéder à des propriétés (ce qu'un helper ne permet pas), évènements et fonctions spécifiques, pour ne pas avoir à modifier le composant, je songeais utiliser le tagobject de chaque colonne avant de me lancer dans cette aventure, est-ce possible ?

  2. #2
    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 614
    Points
    3 614
    Par défaut
    Utiliser le TagObject est une solution mais normalement les propriétés "tag" sont réservées au développeur final et ne devraient pas être modifiées dans les composants.

    Là, à toi de voir si tu fermes l'accès à cette propriété pour les développeurs qui utiliseront ton code. Après tout c'est une approche qui te permet de faire tes essais sans trop te prendre la tête, donc je dirais GO.

    L'autre solution que tu peux tenter, que j'appelle généralement "l'astuce de Paul Toth" (puisque c'est de lui que je la tiens et que je n'y avais pas pensé avant), c'est de surcharger la classe en l'appelant avec le même nom pour ajouter des fonctionnalités en code sans avoir à réimporter le composant dans l'IDE (par contre ton unité contenant le code devra être chargée en dernier dans l'interface de l'unité qui utilise la grille).

    un truc du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    type
    TGrid = class(FRM.JeNeSaisPlusQuelleUnite.TGrid)
    end;

  3. #3
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 135
    Points : 41 300
    Points
    41 300
    Billets dans le blog
    63
    Par défaut
    surcharger la classe en l'appelant avec le même nom pour ajouter des fonctionnalités en code
    ce truc-là, je l'envisage aussi (je ne savais pas que Paul en avait fait un "truc"), c'est ce que j'entends aussi par dériver le composant de base.
    Je l'ai déjà fait pour je ne sais plus quel composant ni dans quelles circonstances

    tu fermes l'accès à cette propriété pour les développeurs qui utiliseront ton code.
    exact, mais qui utilise tagobject

  4. #4
    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 614
    Points
    3 614
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    exact, mais qui utilise tagobject
    euh... moi

  5. #5
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 135
    Points : 41 300
    Points
    41 300
    Billets dans le blog
    63
    Par défaut
    Après avoir longtemps galéré sur le dessin (https://www.developpez.net/forums/d2...ayout-runtime/)

    J'arrive au bout de la méthode utilisée à base de Helpers et de l'utilisation d'un "simple" TagObject. De plus en plus complexe, il est évident qu'une "surclasse" du composant serait plus facile.
    Nom : Capture.PNG
Affichages : 220
Taille : 48,8 Ko

    En effet, même s'il me reste quelques petits bogues (ordre du tri, largeur du gridpanellayout), c'est surtout la question application du tri sur lequel je m'attache aujourd'hui.

    Plusieurs questions restent en suspens :
    - déclencher le tri
    - trier un tableau (stringgrid) s'il n'est pas lié à une source de données, plus exactement s'il s'agit d'un remplissage par code ou par liaisons d'objets (prototypebindsource et oncreateADapter pour les "vrais objets".
    N.B. si le tableau est lié, je n'ai envisagé qu'une liaison à une source de données Firedac permettant d'utiliser IndexFieldNames. En parlant de ceci, toujours en clin d'œil à Gilles , il serait aussi possible d'ajouter un Combobox ou un Searchbox, selon la même technique que pour le tri et d'utiliser la propriété Filter des sources de données Firedac.

    un petit retour sur le code de mon TagObject
    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
     TGridObject = class
      private
        FGridSelectedRange: TRect;
        FGridSelectedCols: TList<Integer>;
        FGridSelectedRows: TList<Integer>;
        FGridSelColor: TAlphaColor;
        FGridSelOpacity: Single;
        FGridHeaderBrush : TBrush;
        FGridHeaderStrokeBrush : TStrokeBrush;
        FGridSelBrush : TBrush;
        FSelectionMode : TGridSelectionMode;
        FOwner: TStringGrid;
        FSortableColumns: TList<TColumn>;
        FSortedColumns: integer;
        procedure SetGridSelOpacity(const Value: Single);
        procedure SetGridSelColor(const Value: TAlphaColor);
        procedure SetSortedColumns(const Value: integer);
      public
       property GridSelColor  : TAlphaColor read FGridSelColor;
       property GridSelOpacity  : Single read FGridSelOpacity write SetGridSelOpacity;
       property GridSelectedCols : TList<Integer> read FGridSelectedCols; // write SetGridSelectedCols;
       property GridSelectedRows : TList<Integer> read FGridSelectedRows; // write SetGridSelectedRows;
       property GridSelectedRange : TRect read FGridSelectedRange;  // write SetGridSelectedRange;
       property GridSelBrush : TBrush read FGridSelBrush;
       property GridHeaderBrush : TBrush read FGridHeaderBrush;
       property GridHeaderStrokeBrush : TStrokeBrush read FGridHeaderStrokeBrush;
       property SelectionMode : TGridSelectionMode read FSelectionMode;
       property SortableColumns : TList<TColumn> read FSortableColumns;
       property SortedColumns : integer read FSortedColumns write SetSortedColumns;
       property Owner : TStringGrid read FOwner; // write Setowner;
       constructor Create(Owner : TStringGrid);
      end;
    Tout d'abord, je me heurte à l'ordre de ma liste de colonnes "triables" SortableColumns, il faudrait qu'elle soit triée en ordre ascendant en fonction du tag de l'entête de colonne (mauvais choix, je pense, j'aurai certainement dû utiliser le tag de colonne. Facile à corriger). Bon, étant donné que c'est un TList<TColumn> ce n'est qu'un peu de code de tri à écrire donc solvable.

    Le tri d'une liaison à des objets (OnCreateAdapter) puisqu'un TList<unobjet> sera utilisé, c'est encore gérable, quoi que je n'aie, jusqu'à présent, codé des tris que sur un seul critère.
    Le tri d'un tableau non lié ou d'un TPrototypeBindSource, par contre, je ne sais pas vraiment par quel bout commencer

  6. #6
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 135
    Points : 41 300
    Points
    41 300
    Billets dans le blog
    63
    Par défaut
    Des recherches pour une autre personnalisation des cellules m'ont fait découvrir une unité FMX.Grid.Style
    Quelqu'un a déjà utilisé et si oui comment faire ?

    J'y vois de gros élagages s'il est possible d'utiliser cette unité en exemple la propriété HeaderItem[const Index: Integer]

  7. #7
    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 614
    Points
    3 614
    Par défaut
    malheureusement elle ne simplifie rien aux opérations, c'est utilisé en interne par l'affichage des grilles sous forme de style

  8. #8
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 135
    Points : 41 300
    Points
    41 300
    Billets dans le blog
    63
    Par défaut
    Je reprends le fil de cette discussion après des évolutions imprévues suite à la discussion récente initiée par navig
    en résumé j'en étais à ce stade : la possibilité d'utiliser un seul TSKSVG (faut oser )

    Nom : Capture.PNG
Affichages : 18
Taille : 5,0 Ko

    Donc dans la suite de cette discussion voici mes objectifs :
    1. Améliorer l'utilisation du SVG via l'utilisation de "variables" traitées via des remplacements de chaines.
    2. Continuer la piste du helper.
    3. Me pencher (enfin) sur la partie tri.
    4. Finalement, pourquoi pas tant que l'on y est ajouter une recherche via un TEdit et dans l'absolu compléter ce dernier par une liste des valeurs possibles (à la mode tableur).



    Les objectifs sont nombreux, je ne sais pas si je les tiendrai tous n'ayant aucune urgence professionnelle

    un préalable : il faudra désormais une version 12.1 minimum (ce qui tombe à pic car la version community en est à ce stade)
    Pourquoi ?
    Tout d'abord pour l'utilisation du multistring pour la déclaration du SVG, je suis feignant , cependant cela ôte la possibilité d'ajouter des commentaires
    Je ne sais pas trop ce que cela apporte niveau dessin (mes précédents posts étant fait avec une version plus ancienne 10.1)
    Il y a une histoire de THeader avec la version 12.1, du moins d'après mes souvenirs de note de version (si quelqu'un a des infos dessus, merci de m'en faire part, je n'avais pas suivi l'affaire)
    C'est surtout pour le dernier point que la version 12.1 et son QBE me semble nécessaire (évitant ainsi des manipulations du Datasource de départ j'espère)

    Et voilà le résultat partiel pour l'objectif 1
    Nom : Capture.PNG
Affichages : 18
Taille : 6,3 Ko
    le 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
    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
    procedure TForm1.Grid1DrawColumnHeader(Sender: TObject; const Canvas: TCanvas;
      const Column: TColumn; const Bounds: TRectF);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
      svgfinal : String;
     
    const svgsort = '''
        <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.993 511.993" xml:space="preserve" fill="#000000">
        <g>
        <rect x="0.000" y="0.362" style="fill:#00A1A7;" width="100.000" height="73.038"></rect>
        <rect x="0.000" y="146.444" style="fill:#00A1A7;" width="150.000" height="73.038"></rect>
        <rect x="0.000" y="292.519" style="fill:#00A1A7;" width="250.000" height="73.038"></rect>
        <rect x="0.000" y="438.594" style="fill:#00A1A7;" width="300.000" height="73.038"></rect>
        </g>
        <circle cx="400" cy="100" r="100" style="stroke:none; fill:red" />
        <text x="370" y="150" style="font-family: Times New Roman;
                       font-size  : 150;
                       fill       : white;">$TRI</text> 
        <g>
        </g>
        </svg>
    ''';
     
     
    begin
      svgfinal:=svgsort;
      svgfinal:=StringReplace(svgfinal,'fill:#00A1A7;','fill:green;',[rfreplaceall]);
      Header:= THeader(Grid1.FindStyleResource('header'));
      if assigned(Header) then HeaderItem:= Header.Items[column.index] else exit;
     
    case Column.Index of
      0 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
     
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SvgFinal:=StringReplace(svgfinal,'$TRI',(Column.Index+1).toString,[]);  // bien sûr ce n'est pas la valeur de l'ordre de tri, ici c'est juste une test 
     
         SVG.Source:=svgfinal;
     
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
      end;
      1 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVGfinal:=StringReplace(SVGfinal,'$TRI',(Column.Index+1).toString,[]);  // bien sûr ce n'est pas la valeur de l'ordre de tri, ici c'est juste une test 
         SVG.Source:=svgfinal;
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
     end;
    end;
    commentaires sur mon SVG, pour l'instant je n'ai utilisé qu'une seule "variable" $TRI
    <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlnslink="http://www.w3.org/1999/xlink" viewBox="0 0 511.993 511.993" xml:space="preserve" fill="#000000">
    <g>
    // remplacement de la valeur y pour l'ordre descendant
    // remplacement de la couleur fill:#00A1A7; au besoin
    <rect x="0.000" y="0.362" style="fill:#00A1A7;" width="100.000" height="73.038"></rect>
    <rect x="0.000" y="146.444" style="fill:#00A1A7;" width="150.000" height="73.038"></rect>
    <rect x="0.000" y="292.519" style="fill:#00A1A7;" width="250.000" height="73.038"></rect>
    <rect x="0.000" y="438.594" style="fill:#00A1A7;" width="300.000" height="73.038"></rect>
    </g>
    <circle cx="400" cy="100" r="100" style="stroke:none; fill:red" /> // fil:red devra être fill:none si non utilisée, fill:<valeur> si besoin
    <text x="370" y="150" style="font-family: Times New Roman;
    font-size : 150;
    fill : white;">$TRI</text> // ma variable
    <g>
    </g>
    </svg>
    J'attends vos suggestions

    une critique cependant cette fonctionnalité n'est visible qu'au runtime, au temps pour le wyseewyg intégrer ça de façon à l'obtenir demandera au minimum la création d'un composant (,d'un style ?) et je nse sais quoi d'autre mais passons déjà les premières étapes
    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

  9. #9
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 135
    Points : 41 300
    Points
    41 300
    Billets dans le blog
    63
    Par défaut mi-parcours, objectif 1
    Il reste des peaufinages, mais à mi-parcours de la matinée voici le résultat
    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
    procedure TForm1.Grid1DrawColumnHeader(Sender: TObject; const Canvas: TCanvas;
      const Column: TColumn; const Bounds: TRectF);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
     
    function typetri(tritype : smallint) : string;  // todo ajouter valeur par défaut 0 pour tritype et couleurs (traits, cercle)
    // tritype contient le sens si >0 DESC si<0 ASC  et l'ordre de tri 
    const svgsort = '''
        <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.993 511.993" xml:space="preserve" fill="#000000">
        <g color="#00A1A7">
        <rect x="0.000" y="$T1"  fill="currentColor" width="100.000" height="73.038"></rect>
        <rect x="0.000" y="$T2"  fill="currentColor" width="150.000" height="73.038"></rect>
        <rect x="0.000" y="$T3"  fill="currentColor" width="250.000" height="73.038"></rect>
        <rect x="0.000" y="$T4"  fill="currentColor" width="300.000" height="73.038"></rect>
        </g>
        <circle cx="400" cy="$CPOS" r="100" style="stroke:none; fill:$CFIL" />
        <text x="370" y="$TPOS" style="font-family: Times New Roman;
                       font-size  : 150;
                       fill       : white;">$TRI</text>
        <g>
        </g>
        </svg>
    ''';
     begin
       result:=svgsort;
       if tritype=0 then
        begin
         result:=StringReplace(result,'$T1','146.444',[]);
         result:=StringReplace(result,'$T2','0.362',[]);
         result:=StringReplace(result,'$T3','438.594',[]);
         result:=StringReplace(result,'$T4','292.519',[]);
         result:=StringReplace(result,'g color="#00A1A7"','g color="silver"',[rfreplaceall]);
         result:=StringReplace(result,'$CFIL','none',[]);
         result:=StringReplace(result,'$TRI','',[]);
        end
       else begin
         if tritype>0 then begin
         // type de tri Descendant
         result:=StringReplace(result,'$T1','0.362',[]);
         result:=StringReplace(result,'$T2','146.444',[]);
         result:=StringReplace(result,'$T3','292.519',[]);
         result:=StringReplace(result,'$T4','438.594',[]);
         result:=StringReplace(result,'$CFIL','red',[]);
         result:=StringReplace(result,'$CPOS','100',[]);
         result:=StringReplace(result,'$TPOS','150',[]);
         result:=StringReplace(result,'$TRI',tritype.ToString,[]);
         end
         else begin
        // type de tri Ascendant
         result:=StringReplace(result,'$T1','438.594',[]);
         result:=StringReplace(result,'$T2','292.519',[]);
         result:=StringReplace(result,'$T3','146.444',[]);
         result:=StringReplace(result,'$T4','0.362',[]);
         result:=StringReplace(result,'$CFIL','red',[]);
         result:=StringReplace(result,'$CPOS','400',[]);
         result:=StringReplace(result,'$TRI',Abs(tritype).ToString,[]);
         result:=StringReplace(result,'$TPOS','450',[]);
         end;
       end;
     end;
     
    begin
    //  svgfinal:=svgsort;
    //  svgfinal:=StringReplace(svgfinal,'fill:#00A1A7;','fill:green;',[rfreplaceall]);
      Header:= THeader(Grid1.FindStyleResource('header'));
      if assigned(Header) then HeaderItem:= Header.Items[column.index] else exit;
     
    case Column.Index of
      0 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
     
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVG.Source:=typetri(1);
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
      end;
      1 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVG.Source:=typetri(-2);
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
       end;
      2 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVG.Source:=typetri(0);
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
     end;
    end;
    Nom : Capture.PNG
Affichages : 11
Taille : 11,8 Ko

    quelques explications :
    le bouton permet d'augmenter la taille du header

    la colonne hello est triée en premier en ordre DESCendant
    la colonne world est triée en second en ordre ASCendant
    à moins que je ne sois dyslexique et que ce soit l'inverse

    et enfin la dernière colonne n'est pas triée mais pourrait l'être
    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

  10. #10
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 135
    Points : 41 300
    Points
    41 300
    Billets dans le blog
    63
    Par défaut Suite
    Quelque chose ne me plaisait pas dans mon code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
    j'ai remplacé par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     for var aSVG in HeaderItem.Children do if (aSVG is TSkSvg) then aSVG.Destroy;
    Encore que je ne comprenne pas trop pourquoi je dois détruire, il y a certainement mieux, mais j'ai fait la constatation que, si non, j'avais plusieurs SVG pour un même Header

    Ensuite j'ai voulu bruler les étapes et passer à la 4, l'ajout d'un TEdit et là je "tombe" sur 2 os
    Nom : Capture.PNG
Affichages : 7
Taille : 4,3 Ko
    une nouvelle fois 2 SVG et un Edit un peu à revoir niveau alignement (j'ai fait ça à l'arrache)
    mais c'est surtout le deuxième os qui me met dans la panade : on ne peut pas saisir quoique ce soit dans la zone d'édition

    Même si j'ai, bien sûr, une autre piste, ça fait mal !

    je repars donc sur mon planning le traitement du Onclick sur le SVG
    Nom : Capture.PNG
Affichages : 8
Taille : 12,4 Ko
    et donc, le tri
    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

Discussions similaires

  1. Aligner les titres des colonnes dans un datagrid
    Par bonnet85 dans le forum VB 6 et antérieur
    Réponses: 0
    Dernier message: 02/04/2008, 16h01
  2. Probleme d'affichage dans les titres des fenetres
    Par pierrot10 dans le forum Windows XP
    Réponses: 4
    Dernier message: 24/01/2008, 09h01
  3. Affichage du titre des colonnes dans un DBGrid
    Par Debure dans le forum C++Builder
    Réponses: 6
    Dernier message: 05/10/2005, 23h41
  4. DBGrid, comment dessiner dans les titres des colonnes
    Par dleu dans le forum Bases de données
    Réponses: 9
    Dernier message: 04/11/2004, 17h49
  5. [dbGrid]Image dans le titre des colonnes d'un dbGrid
    Par dleu dans le forum Bases de données
    Réponses: 1
    Dernier message: 31/08/2004, 18h01

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