Entwickler-Ecke

Dateizugriff - Wie füge ich ner ComboBox ein neues Element hinzu?


Ecthelion - Fr 03.01.03 15:39
Titel: Wie füge ich ner ComboBox ein neues Element hinzu?
Ich hab da ein Programm, dass ähnlich wie die Desktop-Darstellung bei Windows einzelne Settings in einer Datei abspeichern soll, und die Settings selbst werden über ne ComboBox aufgerufen. Mit nem kleinen Extra-Formular (wie bei Windows) sollen dann neue Settings eingefügt werden können. Wie aber füge ich dann der ComboBox so'n Setting hinzu?

Oder andersrum: wie lade ich die Settings aus einer Datei in die ComboBox? Würde das erste Problem umgehen, weil einfach in Datei speichern und neu laden.

Danke.


Dev4u.ch - Fr 03.01.03 15:55

das erset ist speichern..
und das zweite ist laden..


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.Button1Click(Sender: TObject);
var
st: TStringlist;
begin
st := TStringlist.create;
st.assign(Combobox1.items);
st.savetofile('C:\test.txt');
st.free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
st: TStringlist;
begin
st := TStringlist.create;
st.loadfromfile('C:\test.txt');
combobox1.Items.assign(st);
st.free;
end;


Klabautermann - Fr 03.01.03 16:12

Hallo,

einen tStrings-Objekt (und auch die Liste der Kombobox basiert auf einem) bietet die Methode Add an um neue Einträge hizuzufügen.

Das ganze sieht dann so aus:

Quelltext
1:
ComboBox1.Items.Add('Neuer Eintrag');                    


Gruß
Klabautermann


Ecthelion - Fr 03.01.03 16:52

Danke zu beidem.

Das eine fügt also ein einzelnes Element hinzu, und mit dem andern kann ich aus ner Datei gleich ne ganze Palette laden. Kewl! :)


Ecthelion - Fr 03.01.03 19:13

Und wie läuft das, wenn in der Datei eben nicht nur Wörter stehen sondern ganze Datensätze, und ich jeweils einen bestimmten string aus diesen records in die liste einfügen will?


Christian S. - Fr 03.01.03 19:54

Du liest nacheinander alle Datensätze aus der Datei und fügst mit Add den entsprechenden String hinzu. z.B. so:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
AssignFile(myfile,'c:\daten.dat');
{$I-}
Reset(myfile);
{$I+}
IF IOResult=0 then
while not EOF(myfile) do
begin
  Read(myfile,datensatz);
  ListBox1.Items.Add(datensatz.name);
end;
CloseFile(myfile);

Am besten wäre es natürlich, die gelesen Datensätzen, anders als in meinem Beispiel, zur weiteren Verwendung direkt noch in einem Array zu hinterlegen, wenn Du sie einliest.

MfG,
Peter


Ecthelion - Fr 03.01.03 20:39

Danke, macht Sinn.

Bist Du der gleiche Peter Lustig wie der mit dem Löwenzahn? ;)


Christian S. - Fr 03.01.03 20:42

Nein :) , aber er ist sozusagen mein Namenspatron für meinen Nickname im Internet. Und man könnte sagen, dass unser Vorsatz der Gleiche ist: jedem alles so gut wie möglich erklären.


Ecthelion - Fr 03.01.03 21:17

Dann erklär mir mal nochmal die Sendung mit dem Feuerlöscher :P


Christian S. - Fr 03.01.03 21:30

Sorry, habe die Sendung schon lange nicht mehr gesehen. Aber bei konkreten Fragen stehe ich gerne bereit. :wink: Aber besser im Off-Topic, sonst bekommen wir noch einen auf den Deckel. :wink:


Ecthelion - Sa 04.01.03 14:02

Noch ne Frage: der Tip von ganz oben bezieht sich ja darauf, dass in der Datei nur Strings stehen. Für Records ist die Lustig-Variante wohl besser, aber da hab ich jetz nur ne Anleitung für's Laden. Wie speicher ich sowas?

Und wie muss die Datei selbst vereinbart werden? Als "file of datensatz"?


Christian S. - Sa 04.01.03 14:57

Hi!

Das machste am besten so:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
VAR  datei: FILE OF Tdatensatz;
     i : INTEGER;
begin
  AssignFile(datei,'C:\daten.dat');
  ReWrite(datei);
  for i:=0 TO High(datensatz) DO Write(datei,datensatz[i]);
  CloseFile(datei);
end;

datensatz ist dabei mein Array. (datensatz : Array OF TDatensatz;)

Vorsicht: mit dem ReWrite(datei)-Befehl wird die Datei komplett neu erstellt. Alles, was vorher drin gespeichert war, ist dann weg!!

MfG,
Peter


Ecthelion - Mo 06.01.03 10:18

Was hat das mit der High-Funktion auf sich? Hat das was mit nem Aray of Datensatz zu tun? Oder gar mit der Combobox selbst? Wenn nicht, wie laufe ich deren Inhalt von Anfang bis Ende durch, um dann anhand der Strings den entsprechenden Record zu finden und abzuspeichern?


Christian S. - Mo 06.01.03 16:38

Hi!

High(datensatz) gibt Dir den höchsten noch ansprechbaren Wert im Array Datensatz. Da es sich um ein dynamisches Array handelt, ist der ja nicht fest, sondern muss über diese Funktion ermittelt werden.

Zitat:
Wenn nicht, wie laufe ich deren Inhalt von Anfang bis Ende durch, um dann anhand der Strings den entsprechenden Record zu finden und abzuspeichern?
Kannst Du die Frage nochmal genauer erklären? Welchen entsprechenden Record? Du läufst mit meinem Quelltext mit der For-Do-Schleife schon alle Records durch und speicherst sie nach einander.

MfG,
Peter


Ecthelion - Di 07.01.03 16:22

Ist eigentlich egal, war ne dumme Idee. Die Combobox zeigt ja an, was in der Datei ist, nicht andersrum.

Also ich denke uns ist gut geholfen, danke.


Ecthelion - Di 07.01.03 20:41

mal ne andre frage: an welcher stelle im programm kann ich mein record vereinbaren? ich bekomm total dumme fehlermeldungen wenn ich's als type im private-bereich des hauptprogramms vereinbare...


Ecthelion - Di 07.01.03 20:57

"[Fehler] posmenuunit.pas(58): Typ 'tstandard' benötigt Finalization - nicht im Dateityp erlaubt"


Christian S. - Di 07.01.03 21:47

Dein Record vereinbarst Du, nach der Typedefinition für Deine Form. Es macht ja keinen Sinn, einen Typ innerhalb eines Typs (hier : deine Form) zu definieren.

Was die Fehlermeldung betrifft: wenn Du eine Datei als File Of TDatensatz oder so definierst, muss die exakte Größe des Datensatzes bekannt sein. Dass heißt wiederrum, dass z.B. Du angeben musst, wieviel Elemente ein Array innerhalb eines Datensatzes hat und (wahrscheinlich hier der Fehler), wieviel Zeichen ein String innerhalb Deines Typen hat.

Also nicht:

Quelltext
1:
2:
3:
4:
TDatensatz = RECORD
                      name : STRING
                      nummern : ARRAY OF INteger;
                    END;

sondern

Quelltext
1:
2:
3:
4:
TDatensatz = RECORD
                      name : STRING[120];
                      nummer : Array[0..20] Of INteger;
                    END;


MfG,
Peter


Ecthelion - Di 07.01.03 22:14

Ja, am string hat's gelegen. Jetz noch ein letztes Detail :): Wenn ich dann aus der Box ein Element auswähle, sollen sämtliche anderen Komponenten (Felder oder so), die zum Record mit diesem Namen gehören, ebenfalls geladen werden. Muss ich also mit jedem Klick auf einen Eintrag in der Combobox das gesamte Feld durchlaufen, bis ich einen Eintrag mit dem entsprechenden Namen gefunden hab. Und wie heißt das Ergebnis einer Auswahl aus einer Combobox in Delphi (also mit welcher Eigenschaft o.ä. nehme ich auf das Ausgewählte Bezug)?


Ecthelion - Di 07.01.03 22:28

Außerdem bekomme ich ne Exception bei CloseFile wenn ich Programm kompiliere und starte. Fehler 103.

Hab einfach ins FormCreate reingeschrieben dass er eben die Datei öffnen und die Einträge ins Feld schreiben soll, mit dem Modul das oben beschrieben wurde.


Christian S. - Mi 08.01.03 16:32

Zitat:
Und wie heißt das Ergebnis einer Auswahl aus einer Combobox in Delphi
*räusper* versuch's mal mit OnSelect.

Zitat:
also mit welcher Eigenschaft o.ä. nehme ich auf das Ausgewählte Bezug
Die Nummer des ausgewählten Eintrages erhälst Du mit ItemIndex (beginnend mit 0). Damit sollte auch schon klar sein, dass Du das Array nicht durchlaufen musst, um die anderen zugehörigen Eigenschaften zu finden, oder?

Fehlermeldung: mein Fehler: schreib' mal das CloseFile(myfile) mit in den Quelltext, der ausgeführt wird, wenn die IF-Bedingung erfüllt ist. Dann sollte es funktionieren.

MfG,
Peter


Ecthelion - Mi 08.01.03 17:32

Heißt das also, in der ComboBox stehen nicht nur die "Name"-Einträge sondern "dahinter" sind auch die anderen Einträge des Records enthalten? Also brauch ich gar kein Array?

OnSelect wäre übrigens nur das Ereignis für die Auswahl eines Elements. Wie aber heißt dann das Element selber?

So wie wenn ich in ein Edit-Feld was eingebe, dann ist OnChange (oder ne andre) dann sowas wie OnSelect, EditFeld.Text aber ist der Eintrag mit dem danach weitergearbeitet wird. Wie heißt jenes bei der ComboBox?


Christian S. - Mi 08.01.03 18:05

Zitat:
OnSelect wäre übrigens nur das Ereignis für die Auswahl eines Elements.
Oh, sorry, ich habe "Ereignis" anstatt "Ergebnis" gelesen. Den Text des ausgewählten Elementes kannst Du auch über die Eigenschaft ItemIndex erfahren. Der Text ist:

Quelltext
1:
ComboBox1.Items[ItemIndex]                    


Zitat:
Heißt das also, in der ComboBox stehen nicht nur die "Name"-Einträge sondern "dahinter" sind auch die anderen Einträge des Records enthalten? Also brauch ich gar kein Array?
Nein. In der Combobox steht nur der Name. Aber ItemIndex ist die Nummer des ausgewählten Items in der ComboBox. Und da Du die Items alle nacheinander aus dem Array "eingefüllt" hast, muss das auch gleichzeitig die Nummer des entsprechenden Elementes im Array sein, gelle? Damit musst Du also nicht nach dem Element, welches zur Auswahl in der ComboBox gehört suchen, sondern ItemIndex gibt Dir sofort dessen Nummer.

MfG,
Peter


Ecthelion - Mi 08.01.03 19:31

Kewl, das macht Sinn, dann nur noch formelle Fragen:

1. Das erste Item einer ComboBox, hat das den Index 0 oder den Index 1?

2. Wenn ich ein Array also vergrößern Will, setze ich das neue Item einfach an Position High(array)+1?


Christian S. - Mi 08.01.03 20:02

Prima, dass es jetzt klar ist!

zu 1: das erste Item hat den Index 0

zu 2: fast. Du musst für ein neues Item erst "Platz schaffen". Du musst also die Länge des Arrays um eins erhöhen und dann an die dadurch neu erstellte Position Deine Daten schreiben. Also so:

Quelltext
1:
SetLength(my_array,Length(my_array)+1);                    

Das neue (leere) Element wird hinten drangehängt, hat als nun den Index High(my_array). In Bezug auf die alte Länge des Arrays ist das, wie Du ganz richtig geschrieben hast, die Position High(my_array)+1. Nur das das nicht funktionieren würde, da High(my_array) Dir ja gerade den Index des letzten ansprechbaren Elements gibt. Dann ein Element anzusprechen zu versuchen, welches darüber liegt, geht natürlich nicht. Dafür die Verlängerung des Arrays.

MfG,
Peter


Ecthelion - Sa 11.01.03 13:53

http://www.auq.de/viewtopic.php?t=5711

Irgendwie läuft's immer noch nich so recht. Beim schreiben in das Array hängt er sich irgendwie auf (auch wenn mittlerweile OT)