| Autor |
Beitrag |
chickenfigt1989
      
Beiträge: 444
Erhaltene Danke: 2
|
Verfasst: Mi 29.02.12 00:28
Soo
Neues Problem Neues Glück.
Mit folgenden Code hab ich ein OnKlick Ereignis der Einträge von der Listbox:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TForm2.ListBox1Click(Sender: TObject); var i: integer; begin for i := 0 to ListBox1.Count - 1 do if ListBox1.Selected[i] then label2.Caption := Listbox1.Items[i]; end; |
Nun wird ja dem Label2 die Caption von dem Listbox Eintrag zugewiesen.
Wenn ich aber da drauf klick will ich die ganze Adresse haben.
Nur weis ich nicht genau wie ich das Realisieren soll.
Meine Idee war ja zuerst das ich die Einträge aus der Ini in ein Memo ausgeben lasse.
Oder gibt es da ne bessere und einfachere Methode?
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 29.02.12 00:37
Moin!
chickenfigt1989 hat folgendes geschrieben : | | Mit folgenden Code hab ich ein OnKlick Ereignis der Einträge von der Listbox: |
Wie ich schon im anderen Thread schrieb, was hälste denn hiervon:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm2.ListBox1Click(Sender: TObject); var i: Integer; begin i := ListBox1.ItemIndex; if (i >= 0) then Label2.Caption := Listbox1.Items.Strings[i] else Label2.Caption := ''; end; |
chickenfigt1989 hat folgendes geschrieben : | Wenn ich aber da drauf klick will ich die ganze Adresse haben.
Nur weis ich nicht genau wie ich das Realisieren soll. |
Das alte Problem der Datenhaltung in der GUI.  Die "große" Lösung sieht etwa so aus: - Du definierst dir ein Datensatz-Objekt (Klasse), dass jeweils einen Datensatz speichert
- Du lädst die Daten aus der Datei in jeweils eins dieser Datenkontainer-Objekte rein und bewahrst diese z.B. in einer TObjectList auf (dann musst du dich nicht um die Speicherverwaltung kümmern)
- Nach dem Laden aller Objekte leerst du den Inhalt der Listbox und schreibst in einer Schleife für jedes Datenobjekt ein Element in die Listbox, .Strings[] kriegt den "Namen" des Datensatzes ab, .Objects[] eine Referenz auf das eigentliche (unsichtbare) Datenobjekt (das in der TObjectList liegt)
- wird ein Eintrag aus der Listbox angeklickt, kannst du über die Referenz in .Objects[] des Eintrags auf das eigentliche Datenobjekt im Hintergrund zugreifen und die kompletten Adressdaten lesen
Willste das mal so ausprobieren oder ist dir das noch zu schwer?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
chickenfigt1989 
      
Beiträge: 444
Erhaltene Danke: 2
|
Verfasst: Mi 29.02.12 00:48
Naja schon bisschen zu hoch fürs erste
Und so gehts nicht irgendwie oder?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm2.ListBox1Click(Sender: TObject); var i: Integer; IniFile: TIniFile; Filename: String; begin Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini'; inifile := TIniFile.Create(filename); i := ListBox1.ItemIndex; if (i >= 0) then Label2.Caption := Listbox1.Items.Strings[i] + IniFile.ReadString('Daten', 'Straße'+IntToStr(i), '') else Label2.Caption := ''; end; |
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 29.02.12 00:52
Moin!
chickenfigt1989 hat folgendes geschrieben : | Naja schon bisschen zu hoch fürs erste  |
Ist schon OK, gute Selbsteinschätzung vermeidet Überforderungsfrust.
chickenfigt1989 hat folgendes geschrieben : | | Und so gehts nicht irgendwie oder? |
Anfänger neigen leider oft zum "geht doch"-Ansatz, egal wie er aussieht.  Klar geht das so auch, aber du willst doch nicht wirklich bei jedem Klick einen Diskzugriff starten, oder?!
Es gäbe noch eine Variante über eine indexsynchrone Stringliste, in der du die Daten lagerst. Sowas vielleicht?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
chickenfigt1989 
      
Beiträge: 444
Erhaltene Danke: 2
|
Verfasst: Do 01.03.12 21:38
Ne da hast du recht das will ich natürlich nicht.
Was ist eine indexsynchrone Stringliste und gibt es da irgendwie Tutorials oder so dazu?
lg
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 01.03.12 22:58
Moin!
chickenfigt1989 hat folgendes geschrieben : | | Was ist eine indexsynchrone Stringliste und gibt es da irgendwie Tutorials oder so dazu? |
Tutorials dazu weiß ich grad nicht, aber wenn du jetzt Zeit hast, ziehen wir das eben durch.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
chickenfigt1989 
      
Beiträge: 444
Erhaltene Danke: 2
|
Verfasst: Do 01.03.12 23:23
wie lang wird es den ungefähr dauern?
Weil so halbe stunde hätt ich noch Zeit.
Hab halt etz bisschen was geändert:
Nun sieht es so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| procedure TForm2.ListBox1Click(Sender: TObject); var i: Integer; IniFile: TIniFile; Filename: String; begin Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini'; inifile := TIniFile.Create(filename); i := ListBox1.ItemIndex; if (i >= 0) then Richedit1.Lines.clear;
Richedit1.Lines.add( Listbox1.Items.Strings[i]); i:=(i+1); Richedit1.Lines.add(IniFile.ReadString('Daten', 'Straße'+IntToStr(i), '' )); Richedit1.Lines.add(IniFile.ReadString('Daten', 'Nr'+IntToStr(i), '' )); Richedit1.Lines.add(IniFile.ReadString('Daten', 'Plz'+IntToStr(i), '' )); Richedit1.Lines.add(IniFile.ReadString('Daten', 'Ort'+IntToStr(i), '' )); Richedit1.Lines.add(IniFile.ReadString('Daten', 'Vorwahl'+IntToStr(i), '' )); Richedit1.Lines.add(IniFile.ReadString('Daten', 'Rufnummer'+IntToStr(i), '' )); end; |
Nun wen ich einen Eintrag in der Listbox anklicke erscheinen die ganzen Daten in dem Richedit
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 01.03.12 23:35
Moin!
chickenfigt1989 hat folgendes geschrieben : | wie lang wird es den ungefähr dauern?
Weil so halbe stunde hätt ich noch Zeit. |
Könnte passen, sonst machen wir später weiter, hetzt ja keiner.
chickenfigt1989 hat folgendes geschrieben : | | Nun wen ich einen Eintrag in der Listbox anklicke erscheinen die ganzen Daten in dem Richedit |
Ja, der Code ist funktional korrekt.  Allerdings greifst du bei jedem Klick auf die Platte zu, das ist weder effizient noch performant.
Deshalb folgender Ansatz: - Du brauchst eine (klassen-)globale Stringliste, in die du beim Laden der Daten aus der Datei die Details zu einem Datensatz im CommaText-Format (CSV) ablegst.
- Beim Klick auf einen Eintrag in der Listbox holst du aus der Stringliste die unter dem gleichen Index abgelegten Detail-Daten und zeigst sie z.B. in einem Memo oder RichtEdit an. Deshalb heißt das Konzept "indexsynchron", weil die Indizes in der Listbox zu denen in der Stringliste synchron sein müssen, damit das funktioniert.
Also, los geht´s: - die Klassendeklaration im public-Abschnitt um Daten: TStringList; erweitern
- In der FormCreate-Methode die Stringliste initialisieren: Daten := TStringList.Create;
- In der FormDestroy-Methode die Stringliste wieder freigeben: Daten.Free;
- Jetzt zu der Lade-Methode: wie sieht die aktuell bei dir aus? Zeig mal den Code.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
chickenfigt1989 
      
Beiträge: 444
Erhaltene Danke: 2
|
Verfasst: Do 01.03.12 23:38
Ja mir wär morgen lieber da ich da ein bisschen mehr Zeit habe.
Werde das was du geschrieben hast mal morgen durcharbeiten und mich dann wieder melden.
Wegen der Lade Methode wenn du die meinst wie ich die Ini lade dann ist es so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm2.ListBox1Click(Sender: TObject); var i: Integer; IniFile: TIniFile; Filename: String; begin Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini'; inifile := TIniFile.Create(filename); |
Wenn du die nicht meinst müsstest du mir nochmal genauer erklären welche du meinst.
lg
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 01.03.12 23:41
Moin!
chickenfigt1989 hat folgendes geschrieben : | | Ja mir wär morgen lieber da ich da ein bisschen mehr Zeit habe. |
Alles klar, kein Thema. Ich weiß allerdings nicht genau, wann ich morgen online bin.  Wir werden sehen.
chickenfigt1989 hat folgendes geschrieben : | | Werde das was du geschrieben hast mal morgen durcharbeiten und mich dann wieder melden. |
Hmm, so wirklich viel "durcharbeiten" kann man da noch nicht, es passiert ja bis jetzt kaum was.
chickenfigt1989 hat folgendes geschrieben : | Wegen der Lade Methode wenn du die meinst wie ich die Ini lade dann ist es so:
[...]
Wenn du die nicht meinst müsstest du mir nochmal genauer erklären welche du meinst. |
So gesehen meine ich den Teil, der die Listbox mit Daten füllt (die Details holst du ja aktuell beim Klick erst aus der Datei).
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
chickenfigt1989 
      
Beiträge: 444
Erhaltene Danke: 2
|
Verfasst: Do 01.03.12 23:42
Ja werden uns bestimmt morgen sehen.
Hier:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TForm2.FormShow(Sender: TObject); var Anzahl: Integer; i: Integer; IniFile: TIniFile; Filename: String; begin Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini'; inifile := TIniFile.Create(filename); Anzahl:= IniFile.ReadInteger('Daten', 'Count', 0); for i := 1 to Anzahl do begin
Listbox1.Items.Add(IniFile.ReadString('Daten', 'Vorname'+IntToStr(i), '')+' ' +IniFile.ReadString('Daten', 'Nachname'+IntToStr(i), ''));
end; |
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 01.03.12 23:44
Moin!
Jap, das meinte ich. Ich klimpere gleich noch in diesem Beitrag meinen Vorschlag für diesen Code-Teil rein, dann hast du bis morgen was zum Durchsehen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
chickenfigt1989 
      
Beiträge: 444
Erhaltene Danke: 2
|
Verfasst: Do 01.03.12 23:45
ok dann werde ich mir das Morgen mal ansehen und mal sehen wie weit ich Morgen komm und danach meld ich mich hier mal wieder
G8n
lg
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Fr 02.03.12 00:09
Moin!
Hier der Vorschlag:
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:
| procedure TForm2.FormCreate(Sender: TObject); var Anzahl: Integer; i: Integer; IniFile: TIniFile; Filename: String; tmpSL: TStringList; begin Daten := TStringList.Create; tmpSL := TStringList.Create; try Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini'; IniFile := TIniFile.Create(Filename); try Anzahl:= IniFile.ReadInteger('Daten', 'Count', 0); for i := 1 to Anzahl do begin Listbox1.Items.Add( IniFile.ReadString('Daten', 'Vorname'+IntToStr(i), '') +' ' +IniFile.ReadString('Daten', 'Nachname'+IntToStr(i), '') ); tmpSL.Clear; tmpSL.Add(IniFile.ReadString('Daten', 'Straße'+IntToStr(i), '')); tmpSL.Add(IniFile.ReadString('Daten', 'Nr'+IntToStr(i), '')); tmpSL.Add(IniFile.ReadString('Daten', 'Plz'+IntToStr(i), '')); tmpSL.Add(IniFile.ReadString('Daten', 'Ort'+IntToStr(i), '')); tmpSL.Add(IniFile.ReadString('Daten', 'Vorwahl'+IntToStr(i), '')); tmpSL.Add(IniFile.ReadString('Daten', 'Rufnummer'+IntToStr(i), '')); Daten.Add(tmpSL.CommaText); end; finally IniFile.Free; end; finally tmpSL.Free; end; end; | Erläuterungen: - die try-finally-end Blöcke nennt man Ressource-Schutz-Block.
Wenn man Objekte erzeugt und diese später nicht wieder frei gibt, dann wird der dafür verwendete Speicher "unbenutzbar" und ist bis zum Programmende verloren. Sowas nennt man auch "Speicher-Leck", weil du immer mehr Speicher im Programm "verlierst", irgendwann gibt´s dann einen Absturz des Programms... Um sich dagegen abzusichern, benutzt man try-finally-Blöcke: selbst wenn eine Exception auftritt, der Code im finally-Abschnitt wird auf jeden Fall noch bearbeitet (hier: Speicher wieder freigeben).
- In der for-Schleife wird nun jeweils ein Eintrag in die Listbox geschrieben und direkt dazu die restlichen Daten geladen und im CSV-Format in die Stringliste Daten gelegt. Jetzt ist z.B. zum Index 2 der Name in der Listbox und die Details in der Stringliste (=Indexsynchron).
- Um die Daten in das CSV-Format zu bringen, benutzen wir eine weitere Stringliste (tmpSL). Da schreiben wir einfach die Einzeldatenfelder rein und holen sie alle zusammen per .CommaText wieder aus. Tipp schonmal vorab: das geht später beim Auslesen wieder genau so, nur anders rum!

Dann bis morgen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Fr 02.03.12 00:51
Hey,
@chickenfigt1989: wenn du das Bsp. mit der Stringlist von Narses verstanden hast, dann würde ich dir empfehlen, das ganze dann noch auf die Objekt-Liste umzubauen (so wie oben schon erwähnt). Da du dich ja jetzt schon in das Thema eingearbeitet hast dürfte der Umstieg auf die Objekt-Liste nicht alzu schwer sein. Und du hast für Zukünftige Projekte schon einen Anstz für das Problem. Und sowas läuft dir mit Sicherheit öfter über den Weg.
Hier mal ein Ansatz einer Objekt-Liste, hatte grad Langeweile^^ Außerdem könnte das für andere, die ähnliche Probleme damit haben auch interessant sein:
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:
| TDataObject = class(TObject) public FirstName, LastName, Street, HouseNumber, ZipCode, City, TelPrefix, TelNumber: String;
procedure LoadFromIni(Ini: TIniFile; index: Integer); end;
procedure TDataObject.LoadFromIni(Ini: TIniFile; index: Integer); begin FirstName := Ini.ReadString('Daten', 'Vorname' + IntToStr(index), ''); LastName := Ini.ReadString('Daten', 'Nachname' + IntToStr(index), ''); Street := Ini.ReadString('Daten', 'Straße' + IntToStr(index), ''); HouseNumber := Ini.ReadString('Daten', 'Nr' + IntToStr(index), ''); ZipCode := Ini.ReadString('Daten', 'Plz' + IntToStr(index), ''); City := Ini.ReadString('Daten', 'Ort' + IntToStr(index), ''); TelPrefix := Ini.ReadString('Daten', 'Vorwahl' + IntToStr(index), ''); TelNumber := Ini.ReadString('Daten', 'Rufnummer' + IntToStr(index), ''); end;
procedure TForm1.FormCreate(Sender: TObject); var Count, i: Integer; DataObj: TDataObject; Filename: String; Ini: TIniFile; begin DataObjList := TObjectList.Create(); ListBox1.Items.Clear; Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini'; Ini := TIniFile.Create(Filename); try Count := Ini.ReadInteger('Daten', 'Count', 0); for i := 1 to Count do begin DataObj := TDataObject.Create; DataObj.LoadFromIni(Ini, i); DataObjList.Add(DataObj); ListBox1.Items.AddObject( DataObj.FirstName + ' ' + DataObj.LastName, DataObj); end; finally Ini.Free; end; end;
procedure TForm1.ListBox1Click(Sender: TObject); var i: Integer; obj: TDataObject; begin i := ListBox1.ItemIndex; if (i >= 0) then begin obj := (ListBox1.Items.Objects[i] as TDataObject); obj := (DataObjList[i] as TDataObject); if Assigned(obj) then begin Label2.Caption := obj.Street + ' ' + obj.HouseNumber; end; end; end; |
So kann man direkt auf die einzelnen Daten zugreifen und muss nicht erst den Kommastring wieder zerlegen. Natürlich kann man mit Objekten noch viel mehr anstellen, aber das is dann eher was für Fortgeschrittene und Profis
MfG Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
|