Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Probleme mit der TreeView-Komponente...


Terra23 - Mo 25.06.12 20:03
Titel: Probleme mit der TreeView-Komponente...
Hi Leute!

Ich habe folgendes Problem:

In meinem Programm befülle ich ein TreeView, indem ich in ein Edit-Feld einen Text eingebe und mit Enter bestätige.

Es findet dann eine Abfrage statt, ob der Eintrag schon vorhanden ist.

Problem: Nur, wenn die Treeview-Knoten alle eingeklappt sind ODER ich mich im richtigen Knoten befinde, wird ein doppelter Eintrag erkannt. Ansonsten nicht. Ich veranschauliche das mal kurz...


Punkt 1
--A
--B
--C
--D
Punkt 2
--E
--F
--G
Punkt 3
--H
--I
--J

Ich will nun ein "A" hinzufügen. Befinde ich mich in "Punkt 1", erkennt er, dass der Eintrag schon existiert. Befinde ich mich bei "Punkt 2" oder "Punkt 3", dann erkennt er dies nicht und lässt mich das "A" hinzufügen.

Hier mal mein Code für euch (sorry, wenn er nicht sehr elegant aussieht):


Delphi-Quelltext
1:
2:
3:
If (Key=Char(VK_RETURN)) And (Edit1.Text<>'')
Then If NOT (NodeExists(Edit1.Text, NIL))
     Then Setliste.Items.AddChild(GetTreeItems(Setliste.Items, Art), Edit1.Text);


Art ist eine String-Variable und enthält den Knotennamen in den der Eintrag wandern soll (also "Punkt 1", "Punkt 2" oder "Punkt 3"). Setliste ist der Name meiner TreeView.

Ich habe das auch nur per Zufall bemerkt und weiß mir da echt keinen Rat.

Ich hoffe auf eure Hilfe.

Gruß,

Lex


Mathematiker - Mo 25.06.12 21:33

Hallo Terra 23,
ich kenne diesen Effekt vom Suchen nach Einträgen mit bestimmten Textteilen in einem Treeview.
Im Netz habe ich vor längerer Zeit als Ersatzmethode gefunden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
function NodeExists(Parent : TTreeNode; Text : String) : TTreeNode;
var i: Integer;
begin
     Result := nil;
     for i := 0 to Tree.Items.Count - 1 do
     begin
       if (Parent <> nilxor
          ((Parent = niland (Tree.Items.Level = 0)) then
      begin
        if (UpperCase(Tree.Items.Text) = UpperCase(Text)) then
        begin
          if (Parent = nilxor
             ((Parent <> niland (Parent = Tree.Items.Parent)) then
          begin
            Result := Tree.Items;
            Break;
          end;
        end;
      end;
     end;
end;

Für meine Zwecke war es geeignet. Allerdings arbeite ich mit Delphi 5. Vielleicht hilft es Dir ja auch.
Beste Grüße
Mathematiker


Terra23 - Mo 25.06.12 21:43

Danke, das werde ich mal ausprobieren. Muss es in der Zeile wirklich "Xor" heißen?

Gruß,

Terra


Terra23 - Mo 25.06.12 22:22

Funktioniert irgendwie nicht ... er kennt den Bezeichner "Tree" nicht. Habe die Einträge schon in den Namen des Items (TreeView1) geändert, aber das kennt er auch nicht... :(


Mathematiker - Mo 25.06.12 22:54

user profile iconTerra23 hat folgendes geschrieben Zum zitierten Posting springen:
Funktioniert irgendwie nicht ... er kennt den Bezeichner "Tree" nicht. Habe die Einträge schon in den Namen des Items (TreeView1) geändert, aber das kennt er auch nicht... :(

Tut mir leid. Tree ist bei mir der Name des Treeview.
Leider kann ich Dir nicht viel weiterhelfen. So richtig verstehte ich die Treeview-Komponente leider auch nicht.
Beste Grüße
Mathematiker


jaenicke - Di 26.06.12 06:25

Das sieht nach dem typischen Problem aus, wenn man die Daten in einer visuellen Komponente vorhält. Eigentlich müsste es genau umgekehrt sein: Die Daten liegen irgendwo und werden in der TreeView nur angezeigt.
Dann kannst du in den Daten suchen und die TreeView danach nur aktualisieren.

Oder du nimmst die VirtualTreeView und hängst an die einzelnen Datensätze gleich nur Pointer auf die Daten.

Was deinen Code angeht:
Da fehlt irgendwie die Implementierung von NodeExists, denn das gibt es so als einzelne Funktion ja nicht standardmäßig. Ich schätze mal die Funktion geht vom aktuellen Knoten aus und findet den deshalb nicht.


Narses - Di 26.06.12 07:50

Moin!

user profile iconTerra23 hat folgendes geschrieben Zum zitierten Posting springen:
Es findet dann eine Abfrage statt, ob der Eintrag schon vorhanden ist.
Ich nehme einfach mal an, du willst wissen, ob sich ein Node mit einem bestimmten Text irgendwo im Treeview befindet. Die Position ist dir eigentlich egal, du willst nur keine doppelten Namen in den Nodes haben, richtig? Dann sollte es das hier bereits tun:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
function IndexOfNode(ATreeView: TTreeView; AText: String): Integer;
begin
  for Result := 0 to ATreeView.Items.Count -1 do
    if (UpperCase(ATreeView.Items.Item[Result].Text) = UpperCase(AText)) then
      Exit;
  Result := -1;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if (IndexOfNode(TreeView1, Edit1.Text) >= 0then
    ShowMessage('gefunden')
  else
    ShowMessage('nicht drin');
Probier das mal aus. ;)


user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Im Netz habe ich vor längerer Zeit als Ersatzmethode gefunden:
Wo auch immer du diese Funktion her hast, die kann nicht korrekt sein, da fehlen Referenzen. z.B. ein .Item[i] bei den ganzen .Levels, nur als ein Beispiel. Ich halte diese Funktion für defekt. :nixweiss: (und glaube schlicht nicht, dass du sie so eingesetzt hast, ich kann sie mit D7 zumindest nicht mal compilieren, ohne die fehlenden Referenzen anzupassen, ganz zu schweigen von einer Tree-Referenz)


user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Oder du nimmst die VirtualTreeView und hängst an die einzelnen Datensätze gleich nur Pointer auf die Daten.
Ich hätte schwören können, dass du das schreiben wirst... 8) Warum handelst du mit denen eigentlich keine Provision aus? :idea: Das sollte sich echt lohnen, für dich... :zwinker:

cu
Narses


jaenicke - Di 26.06.12 07:52

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Oder du nimmst die VirtualTreeView und hängst an die einzelnen Datensätze gleich nur Pointer auf die Daten.
Ich hätte schwören können, dass du das schreiben wirst... 8)
Es hat eben Gründe warum die auch intern in Delphi benutzt wird. Selbst die kommerziellen Alternativen funktionieren zumindest teilweise schlechter. ;-) Und von der Standard-TTreeView braucht man wohl nicht groß als Vergleich zu reden.


Terra23 - Do 28.06.12 19:12

@Narses: Vielen Dank, mit dem Code hat es funktioniert. Und du hast auch meine Frage richtig verstanden. ;)

Das kann nicht jeder..