Einzelnen Beitrag anzeigen

silver-moon-2000

Registriert seit: 18. Feb 2007
Ort: Schweinfurt
170 Beiträge
 
Delphi XE Professional
 
#1

TChart zeigt nichts an

  Alt 16. Okt 2014, 16:30
Hallo zusammen,

ich komme mir ziemlich blöd vor, weil ich mir sicher bin, dass es ein ganz einfacher Fehler ist, aber ich finde ihn nicht

Es geht darum, dass ich Messwerte in einem TChart anzeigen will. Es werden nacheinander mehrere Messungen (Messwerte kommen über einen am USB-Port hängenen Mikrocontroller) aufgenommen und die sollen alle im Chart angezeigt werden.
Ich versuche, die Rechnerei so gering wie möglich zu halten und speichere daher die LineSeries der älteren messungen zwischen anstatt sie bei jedem Update des Charts neu zu berechnen.

Das Problem jedoch ist, dass das Chart sich weigert, die LineSeries' anzuzeigen.
Ich habe mein Projekt mal auf das Folgende runterbrechen können:

FListData := TObjectList<TMessung> enthält die Messungen, die angezeigt werden sollen, FListSeries := TObjectList<TLineSeries> enthält die LineSeries, die bereits angelegt worden sind, damit sie nicht jedes Mal neu berechnet werden müssen.

Delphi-Quellcode:
procedure TfrmMain.btStartClick(Sender: TObject);
//-> Neue Messung starten
// -> Neue Mess-Liste anlegen (am Anfang der Liste), Messbeginn der neuen Liste auf "jetzt" setzen
// -> Timer starten
begin
  FListData.Insert(0, TMessung.Create);
  FListData[0].recordStart := Now;
  FAngle := 0;
  Timer1.Enabled := True;
end;


procedure TfrmMain.Timer1Timer(Sender: TObject);
//-> wird später durch einen zyklisch sendenden Mikrocontroller am USB-Port ersetzt
// -> Messwerte werden momentan "zufällig" ermittelt
// -> Messwerte werden der neuen Messung (die am Anfang
var torque : Double;
begin
  Inc(FAngle);
  torque := 50 * Random - 25; //Zufallswerte -25 .. +25
  FListData[0].AddValue(FAngle, torque);
  DisplayValues;
end;


procedure TfrmMain.DisplayValues;
//-> zeigt die Daten im Chart an
// -> versucht, so wenig wie möglich neu zu berechnen, daher werden die "alten" Lineseries' zwischengespeichert, damit sie eben nicht neu berechnet werden müssen
// -> schaut bei jedem Aufruf, ob der Messbeginn der aktuellen Messung mit dem gemerkten Messbeginn übereinstimmt
// -> wenn ja, ist seit dem letzten Aufruf keine neue Messung begonnen worden, die neuen Werte können einfach der aktuellen messung angehängt werden
// -> wenn nein: In der Zwischenzet ist eine neue Messung begonnen worden oder alle messungen gelöscht oder oder oder...
// -> lösche in dem Fall alle LineSeries und baue sie neu auf
var ls : TLineSeries;
    i, j : Integer;
    startAngle : Integer;
const
  COLOR_LIST : array [0 .. 3] of TColor = (clRed, clBlue, clGreen, clYellow);
begin
  //Titel setzen
  chDisplay.Title.Text.Clear;
  chDisplay.Title.Font.Color := clBlue;
  chDisplay.Title.Text.Add('Test Display');

  //alle bisherigen Line-Series' löschen
  //-----------------------------------------------edit--------------------------------------------------------------------------
  chDisplay.SeriesList.Clear; //<-[edit] hier steckt das problem
  //Lösung: die obere Zeile mit dem Clear löschen, stattdessen die beiden folgenden Zeilen eintragen
  while chDisplay.SeriesList.Count > 0 do //<- [edit] so funktioniert es
    chDisplay.RemoveSeries(0);
  //-----------------------------------------------edit--------------------------------------------------------------------------

  //Legende nur anzeigen, wenn mehr als eine Messung existiert.
  chDisplay.Legend.Visible := FListData.Count > 1;

  //Test ob die aktuelle Messung (Index 0) in FListData dieselbe ist, die sie beim letzten Aufruf war (wenn ja, stimmen die Aufnahmedaten überein)
  if FListData[0].RecordStart <> FRecStartCurrent then //der aktuelle Graph ist nicht mehr der "alte aktuelle" Graph, eine neue Messung wurde begonnen, alles neu aufbauen
  begin
    //eine neue Messung ist seit dem letzten Aufruf gestartet worden, lösche die Line-Series' und abue sie neue auf
    FRecStartCurrent := FListData[0].RecordStart;
    FListSeries.Clear;
    for i := 0 to FListData.Count - 1 do
    begin
      ls := TLineSeries.Create(nil);
      try
        ls.BeginUpdate;
        ls.Title := FormatDateTime('hh:mm:ss', FListData[i].RecordStart);
        ls.LinePen.Color := COLOR_LIST[i mod (High(COLOR_LIST) + 1)];
        ls.LinePen.Width := 2;
        startAngle := FListData[i].values[0].Angle;
        for j := 0 to FListData[i].values.Count - 1 do
          ls.AddXY(FListData[i].values[j].Angle - startAngle, FListData[i].values[j].Torque);
        ls.EndUpdate;
        FListSeries.Add(ls);
      except
       //
      end;
    end;
  end
  else
  begin //die erste messung ist noch die aktuelle, einfach alle Punkte seit dem letzten Update dazutun, die anderen Lineseries' nicht anfassen
    startAngle := FListData[0].values[0].Angle;
    FListSeries[0].BeginUpdate;
    for i := FListSeries[0].Count to FListData[0].values.count - 1 do
      FListSeries[0].AddXY(FListData[0].values[i].Angle - startAngle, FListData[0].values[i].Torque);
    FListSeries[0].EndUpdate;
  end;

 for i := FListSeries.Count - 1 downto 0 do
   chDisplay.AddSeries(FListSeries[i]);
end;
Wie beschrieben, wird verglichen, ob die erste Messung nach wie vor die aktuelle ist. Wenn ja, werden die Daten einfach an die erste Messung angehängt, wenn nein, wird alles verworfen und neu aufgebaut.

Das Problem ist nun, dass die Graphen im Chart einmal kurz angezeigt werden, nämlich immer dann, wenn eine neue LineSeries angelegt worden ist. Sobald der zweite Timer-Aufruf kommt, die Daten also eigentlich an die neuste Messung angehängt werden sollen, verschwinden die Messungen vom Chart.

Ein chDisplay.Invalidate; nützt genauso wenig wie ein ls.parentChart := chDisplay; Wie gesagt, ich bin mir sicher, dass es ein dämlicher und einfacher Fehler ist, aber ich seh' momentan den Wald vor lauter Bäumen nicht mehr... Mit anderen Worten: HILFE!!!!!11einself
Tobias
Bitte nicht hauen , ich weiß es nicht besser

Geändert von silver-moon-2000 (16. Okt 2014 um 17:01 Uhr) Grund: Lösung in den Quellcode eingetragen, falls es jemanden interessiert
  Mit Zitat antworten Zitat