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

Delphi Discussion :

Chargement d'un fichier arborescence dans un composent TTreeView


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Par défaut Chargement d'un fichier arborescence dans un composent TTreeView
    Bonjour,
    J'ai une fonction qui charge un fichier text avec une arborescence (tree) tab délimiter dans un composent TTreeView,
    sous Firemonkey j'utilise TTreeViewItem.

    Le fichier text que je charge à ce format.
    Example;

    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
     
    RootA_0
    	child_A
    		child_AA
    		child_AB
    			child_ABA
    			child_ABB
    				child_ABBA
    				child_ABBB
    				child_ABBC
    				child_ABBD
    			child_ABC
    	child_B
    		child_BA
    	child_C
    		child_CA
    	child_D
    RootB_0
    Pendant la conversion des lignes, les textes à partir de child_ABC ne viennent pas à la bonne position.
    Ici je n'arrive pas à faire le bon retour.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    ...
    ...
    	child_ABBA
    	child_ABBB
    	child_ABBC
    	child_ABBD
    		child_ABC
    			child_B
    				child_BA
    					child_C
    					....

    Mon probleme est que j'arrive à ajouter des nodes dans l'arborescence enfant,
    mais je n'arrive pas a ajouté un node dans arborescence qui devient plus haute (parent).

    Voici la fonction que je utilise;
    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
     
    procedure TForm1.LoadTextFileTree(TreeView: TTreeView; FileName: string);
    var
      List: TStringList;
      I, TabCount, CurrentLevel: Integer;
      ParentNode, Node: TTreeViewItem;
      ParentObject: TFMXObject;
     
    begin
      List := TStringList.Create;
      try
        List.LoadFromFile(FileName);
        ParentNode := nil;
        CurrentLevel := 0;
        for I := 0 to List.count - 1 do
        begin
          TabCount := CountChar(List[I], #9);
          Node := TTreeViewItem.Create(TreeView);
          Node.Text := List[I].Replace(#9, '');
          Node.Tag := TabCount;
          if (TabCount = 0) or (ParentNode = nil) then
            TreeView.AddObject(Node)
          else if TabCount = CurrentLevel then
            ParentNode.Parent.AddObject(Node)
          else if TabCount > CurrentLevel then
            ParentNode.AddObject(Node)
          else if TabCount < CurrentLevel then
          begin
     
            while (TabCount <= CurrentLevel) and (ParentNode.Tag >= TabCount) do
            begin
     
    		// l'erreur d'affichage dois ce passer ici 
     
              ParentObject := ParentNode.Parent;
              ParentNode.Parent := ParentObject;
              dec(CurrentLevel);
            end;
            ParentNode.AddObject(Node)
     
          end;
     
          ParentNode := Node;
          CurrentLevel := TabCount;
        end;
      finally
        List.Free;
      end;
    end;
    Je vous remercie pour l'aide que vous m'apportez.

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 638
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    il manque une procédure récursive qui fera le boulot.
    Cela fait un bail que je n'ai pas retouché un remplissage de TreeView (à partir d'une BDD) mais le principe est le même

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 090
    Par défaut
    Tu dois réfléchir à tes ruptures et si le fichier n'est pas dans l'ordre, éventuellement faire cela en plusieurs passes ou via un balayage pour retrouver les parents.

    Si le fichier est aussi parfait que tu les montres, une récursivité qui remonte lorsque le nombre d'espaces est différent est la bonne approche, c'est plus difficile à penser mais plus facile à écrire une fois que l'on compris sa rupture de récursivité (descente et remontée)
    Tu as tenté un algo itératif, c'est possible mais cela oblige de retrouver le parent, c'est moins performant et potentiellement compliqué à écrire
    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

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 937
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 937
    Par défaut
    Le plus simple, sans récursivité ou multi-passes, est de conserver le chemin dans un tableau.

    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
    procedure TForm1.LoadTextFileTree(TreeView: TTreeView; FileName: string);
    begin
      const List = TStringList.Create;
      var   Path :TArray<TTreeViewItem> := [nil];
     
      try
        List.LoadFromFile(FileName);
     
        for var s in List do
        begin
          const Level = CountChar(s, #9);
          const Node  = TTreeViewItem.Create(TreeView);
     
          Node.Text := s.TrimLeft;
     
          if Level <> High(Path) then
            SetLength(Path, Level +1);
     
          Path[Level] := Node;
     
          if High(Path) > 0
          then Path[High(Path) -1].AddObject(Node)
          else TreeView.AddObject(Node);
        end;
     
      finally
        List.Free;
      end;
    end;
    Et pour info, en VCL et vu la structure du fichier, TreeView.LoadFromFile(...) suffirait.

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 090
    Par défaut
    J'avais fait pareil pour lire la base de registre en 1999, un tableau pour mémoriser les positions ... cela s'est révélé sous D4, 20x plus lent que la version récursive.
    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

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 937
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 937
    Par défaut
    Mémoriser des positions implique de retrouver l'objet par son index. Tu m'étonnes que c'était plus lent

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 090
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 090
    Par défaut
    Ne pas oublier BeginUpdate et EndUpdate si le fichier est volumineux


    Très lent, je débutais, je ne connaissais même pas le concept de récursivité, la seule chose que je considère notable appris à l'école !

    Sinon Ardely, ton code est proche de TTreeStrings.LoadTreeFromStream, pourquoi ne pas prendre le code Delphi et l'adapter ?
    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

  8. #8
    Membre éclairé
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Le plus simple, sans récursivité ou multi-passes, est de conserver le chemin dans un tableau.
    En cherchant sur le NET, je n'ai pas vu ton message, ce que j'ai posté plus tard.
    Je viens de faire quelque test, très satisfaisant.

    je vous suis très reconnaissant pour votre aide, Merci à tous

  9. #9
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 638
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Le plus simple, sans récursivité ou multi-passes, est de conserver le chemin dans un tableau.
    J'ai testé avec la 10.4.2, après quelques modifications de 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
    procedure TForm1.LoadTextFileTree(TreeView: TTreeView; FileName: string);
    begin
      const List = TStringList.Create;
      var   Path :TArray<TTreeViewItem> := [nil];
    
      try
        List.LoadFromFile(FileName,TEncoding.UTF8);
        TreeView.BeginUpdate;
        for var s in List do
        begin
          const Level = S.CountChar(#9);
          const Node  = TTreeViewItem.Create(TreeView);
    
          Node.Text := S.TrimLeft; 
          if Level <> High(Path) then
            SetLength(Path, Level +1);
    
          Path[Level] := Node;
    
          if High(Path) > 0
          then Path[High(Path) -1].AddObject(Node)
          else TreeView.AddObject(Node);
        end;
    
      finally
        List.Free;
        Treeview.ExpandAll;
        TreeView.EndUpdate;
      end;
    end;
    par contre, j'ai du mal à comprendre comment ce bloc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if High(Path) > 0
          then Path[High(Path) -1].AddObject(Node)
          else TreeView.AddObject(Node);
    fonctionne. Aucune notion de Parent dans Node et pourtant ça tourne


    Citation Envoyé par Andnotor Voir le message
    Et pour info, en VCL et vu la structure du fichier, TreeView.LoadFromFile(...) suffirait.
    Mais VCL.Treeview et FMX.Treeview sont différents c'est bien là un point négatif de FMX !

  10. #10
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 937
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 937
    Par défaut
    • Aucune certitude que le fichier soit en UTF8 ou UTF8 sans BOM.
    • S.CountChar(#9) si tu pars du principe qu'il n'y a pas de #9 dans la chaîne autre que pour son indentation.
    • AddObject (DoAddObject) ajoute un enfant et définit le parent.

  11. #11
    Membre éclairé
    Inscrit en
    Novembre 2006
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 321
    Par défaut
    Je pense que j'ai trouver un exemple, mais ce bout de code fonctionne avec le composent TTreeNode.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
          var
          ANode, NextNode: TTreeNode;   
         begin
     
           ...
    	NextNode := ANode.Parent;
            while NextNode.Level > ALevel do
                NextNode := NextNode.Parent;
              ANode := Items.AddChild(NextNode.Parent, CurrStr);
    	...
          end;

    Et, TTreeNode n'est pas disponible dans FireMonkey, ce composent fait partie de la VCL.

    J'ai beau à essayer de trouver à convertir "Items.AddChild(NextNode.Parent, CurrStr)" pour l'utilisé avec TTreeViewItem,
    mais je ne vois pas encore comment.

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

Discussions similaires

  1. Intégration de fichiers pdf dans un composant Swing
    Par m_piou dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 15/10/2007, 17h12
  2. Réponses: 2
    Dernier message: 05/03/2007, 14h21
  3. Réponses: 2
    Dernier message: 28/11/2006, 11h53
  4. Réponses: 3
    Dernier message: 16/11/2006, 14h23
  5. Réponses: 9
    Dernier message: 27/06/2006, 21h48

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