Daten aus Textdatei in TChart darstellen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Icanyounothear
Beiträge: 4
Registriert: So 16. Feb 2020, 20:19

Daten aus Textdatei in TChart darstellen

Beitrag von Icanyounothear »

Moin ersteinmal,

ich bin noch eher neu was das Programmieren mit Lazarus angeht.
Ich möchte gerne ein Programm schreiben mit dem man den Verlauf des eigene Körpergewichts in einem Graphen(TChart) darstellt. Die Daten für die Darstellung( Datum und Gewicht) möchte ich gerne, zuerst aus dem Programm in eine Textdatei schreiben und diese dann später wieder einlesen und als TChart darstellen.

Meine Idee dazu ist nun gewesen die Daten in einem Array in der .txt abzuspeicher und sie dann später wieder auszulesen.
Haken an der ganzen Sache für mich, ich habe keine Ahnung wie ich das umsetzen soll.
Ich habe nun schon mehrere Stunden gesucht, aber noch keine Lösung gefunden.
Falls es einen einfacheren Weg gibt teilt es mir bitte mit, ansonsten wären ein Quellcode oder eine detailierte Erklärung sehr hilfreich.

schon einmal danke im vorraus !

Icanyounothear

edit1: Die daten sollen aus 2 Edit-Felder kommen
Zuletzt geändert von Icanyounothear am So 16. Feb 2020, 23:03, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 4888
Registriert: Fr 8. Apr 2011, 09:01

Re: Daten aus Textdatei in TChart darstellen

Beitrag von wp_xyz »

Icanyounothear hat geschrieben:Die daten sollen aus 2 Edit-Felder kommen

Versteh ich nicht: Da passen ja nur zwei Gewichtsangaben rein. Oder meinst du: in zwei Edit-Feldern sollen Datum und Gewicht eingegeben, in einer Text-Datei zu den bereits vorhandenen Werten angehängt und gleichzeitig mit TAChart geplottet werden? Wenn das so ist, willst du auch eine Möglichkeit haben, die Datei auf Knopfdruck einzulesen und zu plotten.

Icanyounothear
Beiträge: 4
Registriert: So 16. Feb 2020, 20:19

Re: Daten aus Textdatei in TChart darstellen

Beitrag von Icanyounothear »

Moin,
danke für die schnelle Antwort.
Ich möchte gerne über einen längeren Zeitraum immer wieder Datum(edit1) sowie Körpergewicht(edit2) speichern, das Datum soll in der Tabelle dem Gewicht zugeordnet werden und die gespeicherten Daten auf Knopfdruck in dem TChart darstellen lassen.

Edit1: Die Inhalte aus edit1 und edit2(oder auch Memo1 und Memo2) sollen
Zusammenhängend gespeichert werden, sodass zu einem späteren Zeitpunkt, nach Anhäufung einiger Daten daraus ein Graph erzeugt werden kann.

Ich hoffe es ist nun klar geworden was ich machen möchte.

Gruß
Icanyounothear

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Daten aus Textdatei in TChart darstellen

Beitrag von fliegermichl »

Hallo,

Ich würde dafür ein Stringgrid mit zwei Spalten verwenden. Mit den entsprechenden Optionen lassen sich da die Einträge direkt bearbeiten und neu anlegen.
Einen "speichern" Button noch dazu und mit Stringgrid.SaveToCSVFile kann der Inhalt einfach abgespeichert werden.

Icanyounothear
Beiträge: 4
Registriert: So 16. Feb 2020, 20:19

Re: Daten aus Textdatei in TChart darstellen

Beitrag von Icanyounothear »

Moin fliegermichl,
und danke für deine Antwort.

Kann man denn in einem Stringgrid, floating point numbers und ein Datum eintragen?
Wie kann man, falls obiges der Fall ist, die einzelnen Werten, aus den Zeilen, vor dem Speichern und vor der wieder Ausgabe zb. mit einer Zahl l multiplizieren/dividieren ?
Kann man dann aus der Gespeicherten Werten ein Tchart erstellen?
Wenn ja, wie?

fliegermichl hat geschrieben:
Ich würde dafür ein Stringgrid mit zwei Spalten verwenden. Mit den entsprechenden Optionen lassen sich da die Einträge direkt bearbeiten und neu anlegen.
Einen "speichern" Button noch dazu und mit Stringgrid.SaveToCSVFile kann der Inhalt einfach abgespeichert werden.

wp_xyz
Beiträge: 4888
Registriert: Fr 8. Apr 2011, 09:01

Re: Daten aus Textdatei in TChart darstellen

Beitrag von wp_xyz »

Die erste Frage, die du dir stellen musst, ist, wie die Daten in der Datei gespeichert sind. Ich würde eine Text-Datei vorschlagen, Zeile für Zeile ein Datenpunkt, wobei Datum und Gewicht durch ein Trennzeichen separiert sind, etwa ein Strichpunkt. Etwa so

Code: Alles auswählen

Datum;Gewicht
01.01.2020;70,1
02.01.2020;69,8
03.01.2020;69,7
04.01.2020;70,0
05.01.2020;70,5
06.01.2020;71,0
(Normalerweise würde ich eine landesunabhängige darstellung der Daten bevorzugen, aber das würde hier vom Thema ablenken.)

Die nächste Frage wäre, wie die Daten im Programm (nach dem Laden der Datei) gespeichert sein sollen. Ich nehme mal an, du speichert die Daten in einem Stringgrid, mit dem du sie auch gleich anzeigen kannst. Das ist nicht die beste Lösung (in meinen Augen sogar die schlechteste), aber du kommst so am schnellsten zum Ziel, denn das StringGrid hat eine Methode LoadFromCSVFile:

Code: Alles auswählen

procedure TForm1.DatenLaden(const Dateiname: String);
begin
  StringGrid1.LoadFromCSVFile(Dateiname, ';', true);
  // Das "true" bedeutet, dass die Datei die Spaltenüberschriften enthält.
  DatenPlotten;
end;

Hier wird auch schon eine Methode "DatenPlotten" aufgerufen, mit der die Daten im Chart dargestellt werden sollen. Als Vorbereitung dafür klickst du auf dem eben eingefügten Chart mit der rechten Maustaste, wählst "Datenreihe bearbeiten", dann "Hinzuf +" > "Liniendiagramm". Nun ist eine (leere) TLineSeries im Diagramm vorhanden. Um die Daten aus dem StringGrid in die LineSeries zu übertragen, durchläufst du das StringGrid Zeile für Zeile (aber ohne die Titelzeite, also ab Zeilenindex 1, denn die Nummerierung beginnt bei 0) wandelst die im Grid angezeigten Strings in entsprechende Zahlenwerte um und fügst diese per LineSeries.AddXY(x,y) hinzu. All das passiert in der Methode "DatenPlotten":

Code: Alles auswählen

procedure TForm1.DatenPlotten;
var
  i: Integer;
  datum: TDate;
  gewicht: Single;
begin
  for i := 1 to StringGrid1.RowCount-1 do begin
    datum := StrToDate(StringGrid1.Cells[0, i]);
    gewicht := StrToFloat(StringGrid1.Cells[1, i]);
    Chart1LineSeries1.AddXY(datum, gewicht);
  end;
end;

Das ganze wird im OnCreate-Ereignis des Formulars aufgerufen:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  DatenLaden('Daten.txt');
end;

Wenn du jetzt das Programm laufen lässt, siehst du schon die Daten im Grid und im Chart. Allerdings ist die x-Achse mit den zum Datum gehörenden Zahlenwerten beschriftet. Um diese als Datum formuatiert anzuzeigen, klicke eine TDateTimeIntervalChartSource (Lasche "Chart") aufs Formular. Expandiere im Objekt-Inspektor für den Chart die Eigenschaft "BottomAxis", dann "Marks" und setze "Marks.Source" auf die DatetimeIntervalChartSource, sowie "Marks.Style" auf "smsLabel". Nun sind noch die Achsenlabels zu nah beieinander, aber das kann man beheben, indem man bei DateTimeIntervalChartSource.Params den Wert für MaxLength erhöht, etwa auf 100.

Um neue Daten hinzuzufügen, setze zwei TEdit-Komponenten aufs Formular, ändere ihren Namen zu "edDatum" und "edGewicht" (das ist verständlicher als Edit1 und Edit2), lösche das Feld "Text" und schreibe als "TextHint" den String "Datum" bzw. "Gewicht" - das erscheint, wenn das Eingabefeld leer ist. Schließlich fehlt noch ein Button (Lasche "Standard"). Ändere die "Caption" zu "Neuer Wert" und "Name" zu "btnNeu". Der Button soll beim Klicken die Werte von den Edits ins StringGrid übertragen und den Chart neu generieren. Doppel-klicke auf dem Button und schreibe in den erscheinenden Code-Rumpf diesen Code:

Code: Alles auswählen

procedure TForm1.btnNeuClick(Sender: TObject);
var
  datum: TDate;
  gewicht: Single;
begin
  // Eingabeprüfung
  if (edDatum.Text = '') or (edGewicht.Text = '') then begin
    ShowMessage('Eingabe unvollständig.');
    exit;
  end;
  if not TryStrToDate(edDatum.Text, datum) then begin
    ShowMessage('Kein gültiges Datum.');
    edDatum.SetFocus;
    exit;
  end;
  if not TryStrToFloat(edGewicht.Text, gewicht) then begin
    ShowMessage('Keine gültige Zahl.');
    edGewicht.SetFocus;
    exit;
  end;
 
  // Werte ins Grid übernehmen
  StringGrid1.RowCount := StringGrid1.RowCount + 1;
  StringGrid1.Cells[0, StringGrid1.RowCount-1] := DateToStr(datum);
  StringGrid1.Cells[1, StringGrid1.RowCount-1] := edGewicht.Text;
 
  // Daten neu plotten
  DatenPlotten;
end;

Um die geänderten Daten zu speichern, rufe die Methode SaveToCSVFile des StringGrid auf

Code: Alles auswählen

procedure TForm1.DatenSpeichern(const Dateiname: String);
begin
  StringGrid1.SaveToCSVFile(Dateiname, ';', true);
end;

Ich könnte hier auch das komplette Programm anhängen, aber ich denke, der Lerneffekt ist größer, wenn du die oben genannten Bausteine selbst zusammenfügst.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Daten aus Textdatei in TChart darstellen

Beitrag von fliegermichl »

Man könnte auch die Optionen goAutoAddRows, goEditing und goAlwaysShowEditor des Stringgrids anhaken. Dann kann man sich die beiden Edit's und den Button sparen.

Icanyounothear
Beiträge: 4
Registriert: So 16. Feb 2020, 20:19

Re: Daten aus Textdatei in TChart darstellen

Beitrag von Icanyounothear »

Ersteinmal danke an euch alle,

@wp_xyz zu deinem Quelltext habe ich noch ein paar Fragen, wie ist denn Stringgrid deklariert, ist es eine globale variable?
Muss ich in der Form1 nur ein Tchart haben oder auch ein Stringgrid?

wp_xyz
Beiträge: 4888
Registriert: Fr 8. Apr 2011, 09:01

Re: Daten aus Textdatei in TChart darstellen

Beitrag von wp_xyz »

Was hast du denn schon mit Lazarus oder Delphi gemacht? Evtl solltest du dir ein einführendes Video anschauen - das hier (https://www.youtube.com/watch?v=_5nwM7tjCec) erscheint mir auf den 1.Blick recht gut. (Keine Schande - wir haben alle mal klein angefangen)

Wenn du von der Komponentenpalette (die Bilderleiste oben am Fenster) ein TStringGrid ins Formular klickst, wird automatisch eine Variable StringGrid1 im Kontext des Formulars deklariert. Auf die kannst du zugreifen. Du kannst aber auch im Objektinspektor (die Tabelle am linken Rand) die Eigenschaft "Name" suchen und dort die Komponente und damit die Variable umbenennen.

Wenn du nur die Daten plotten willst, brauchst du - nach deinem ursprünglichen Post - nur ein TChart, zwei TEdit und evtl. noch einen TButton. Das StringGrid habe ich mit dazugenommen, weil es eine einfache Möglichkeit bietet, die Datei einzulesen und zu speichern. Wenn du das nicht hast, musst du die Details dafür selbst programmieren.

Antworten