Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - OnKlick Listbox


chickenfigt1989 - Mi 29.02.12 00:28
Titel: OnKlick Listbox
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 - Mi 29.02.12 00:37

Moin!

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
Mit folgenden Code hab ich ein OnKlick Ereignis der Einträge von der Listbox:
Wie ich schon im anderen Thread [http://www.delphi-forum.de/viewtopic.php?p=659787#659787] 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 >= 0then
    Label2.Caption := Listbox1.Items.Strings[i]
  else
    Label2.Caption := '';
end;


user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
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:Willste das mal so ausprobieren oder ist dir das noch zu schwer? :nixweiss:

cu
Narses


chickenfigt1989 - 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 >= 0then
    Label2.Caption := Listbox1.Items.Strings[i] + IniFile.ReadString('Daten''Straße'+IntToStr(i), '')
  else
    Label2.Caption := '';
    end;


Narses - Mi 29.02.12 00:52

Moin!

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
Naja schon bisschen zu hoch fürs erste :(
Ist schon OK, gute Selbsteinschätzung vermeidet Überforderungsfrust. ;)

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
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?! :shock:

Es gäbe noch eine Variante über eine indexsynchrone Stringliste, in der du die Daten lagerst. Sowas vielleicht? :nixweiss:

cu
Narses


chickenfigt1989 - 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 - Do 01.03.12 22:58

Moin!

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
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


chickenfigt1989 - 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 >= 0then
    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 - Do 01.03.12 23:35

Moin!

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
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. ;)

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
Nun wen ich einen Eintrag in der Listbox anklicke erscheinen die ganzen Daten in dem Richedit
Ja, der Code ist funktional korrekt. :nixweiss: Allerdings greifst du bei jedem Klick auf die Platte zu, das ist weder effizient noch performant. :idea:

Deshalb folgender Ansatz:Also, los geht´s:cu
Narses


chickenfigt1989 - 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 - Do 01.03.12 23:41

Moin!

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
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. :nixweiss: Wir werden sehen. ;)

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
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. :?

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
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


chickenfigt1989 - 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 - Do 01.03.12 23:44

Moin!

user profile iconchickenfigt1989 hat folgendes geschrieben Zum zitierten Posting springen:
Hier:
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


chickenfigt1989 - 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 - Fr 02.03.12 00:09

Moin!

Hier der Vorschlag:

Delphi-Quelltext
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); // beim Programmstart
// FormShow ist für sowas nicht geeignet, da es jedes mal aufgerufen wird, wenn das Formular sichtbar wird!
  var
    Anzahl: Integer; // Anzahl der Datensätze in der INI
    i: Integer; // Laufvariable für die Schleife
    IniFile: TIniFile; // Objekt zum Zugriff auf die INI
    Filename: String// Dateiname der INI auf der Platte
    tmpSL: TStringList; // temporäre Stringliste
begin
  Daten := TStringList.Create; // hier sollen die Daten aufgehoben werden (muss in der Klassendeklaration unter public bekannt gemacht werden!)

  tmpSL := TStringList.Create; // Objekt erzeugen
  try // (1) falls eine Exception in diesem Block auftritt, weiter bei finally(1)
    Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini';
    IniFile := TIniFile.Create(Filename); // Ini-Datei zum Zugriff bereit machen
    try // (2) falls eine Exception in diesem Block auftritt, weiter bei finally(2)
      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), '')
        ); // Name in die Listbox eintragen
        tmpSL.Clear; // Stringliste leeren
        // restliche Daten laden
        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); // und im CSV-Format in die Daten-Stringliste schreiben
      end;
    finally // (2) auf jeden Fall...
      IniFile.Free; // die Ini-Datei wieder freigeben (sonst: Speicherleck!)
    end;
  finally // (1) auf jeden Fall...
    tmpSL.Free; // die Stringliste wieder freigeben (sonst: Speicherleck!)
  end;
end;
Erläuterungen:Dann bis morgen.

cu
Narses


Bergmann89 - 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:


Delphi-Quelltext
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:
//////////////////////////////////////////////////////////////////////////////////////////////
//ich stehe im "interface"-Abschnitt des Codes (am bestten über "TForm1 = class(TForm)" )
TDataObject = class(TObject)
public
  FirstName, LastName, Street, HouseNumber, ZipCode,
  City, TelPrefix, TelNumber: String;

  procedure LoadFromIni(Ini: TIniFile; index: Integer); //läd das Objekt aus einer Ini
end;

//////////////////////////////////////////////////////////////////////////////////////////////
//der nachfolgende Code steht im "implementation"-Teil des Codes
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(); //Objekt-Liste anlegen
  ListBox1.Items.Clear; //ListBox leeren

  Filename := ExtractFilePath(ParamStr(0)) +'adressen.ini';
  Ini := TIniFile.Create(Filename); // Ini-Datei zum Zugriff bereit machen
  try
    Count := Ini.ReadInteger('Daten''Count'0);
    for i := 1 to Count do begin
      DataObj := TDataObject.Create;  //neues Datenobjekt anlegen
      DataObj.LoadFromIni(Ini, i);    //Objekt läd sich selbst aus Ini
      DataObjList.Add(DataObj);       //Objekt in der Liste speichern

      ListBox1.Items.AddObject(       //hängt das Objekt zusätzlich in die ListBox
                                      //ist das selbe wie das normale Add, bloß mit Objekt als extra Parameter  
        DataObj.FirstName + ' ' + DataObj.LastName, //String der in der Listbox dargestellt wird
        DataObj);                                   //Objekt das zusätzlich in der ListBox gespeichert wird
    end
  finally
    Ini.Free;
  end;
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
  i: Integer;
  obj: TDataObject;
begin
  i := ListBox1.ItemIndex;
  if (i >= 0then begin
    obj := (ListBox1.Items.Objects[i] as TDataObject); //Objekt aus der ListBox holen
    //ODER (da ListBox und Objekt-Liste indexgleich sind)
    obj := (DataObjList[i] as TDataObject); //Objekt aus der Liste holen
    //das "as TDataObject" benötigt man, weil in der Liste nur ein Objekt liegt,
    //du aber ein TDataObject benötigst. Stichwort "casten" goolge hilft da weiter ;)
    
    if Assigned(obj) then begin //wenn das Objekt exestiert
      Label2.Caption := obj.Street + ' ' + obj.HouseNumber; //Zugriff auf die Daten des Objekts
    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.