TLineSeries zur Laufzeit mit UserDefinesChartSource erstelle

Für Fragen von Einsteigern und Programmieranfängern...

Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Beitragvon ErnstVolker » 12. Feb 2019, 18:25 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Hhmm. Wer lesen kann ist klar im Vorteil. Ich Trottel!!! Wenn man schon kopiert, dann wenigstens richtig.

Für Dein Beispiel trifft das auch vollumfänglich zu. Bei mir noch nicht ganz. Die Kurve folgt zwar jetzt der Maus, schiebt aber immer nur kleine Stückchen und irgendwann ist die Maus von der Kurve so weit weg, dass die Kurve stehen bleibt.
ErnstVolker
 
Beiträge: 195
Registriert: 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon ErnstVolker » 12. Feb 2019, 18:49 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Ich habe gerade noch was bei mir festgestellt. Und zwar hat es den Anschein, dass sich nicht die Kurve über das Chart schiebt sondern die Achsen wandern.
ErnstVolker
 
Beiträge: 195
Registriert: 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon wp_xyz » 12. Feb 2019, 19:08 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Weil bei der Veränderung der Werte in der List-Source die Achsengrenzen neu berechnet werden, habe ich in dem Demo-Projekt die Achsengrenzen eingefroren (Chart.Extent - siehe Ende von FormCreate, nachdem die unverschobenen Daten in der Series sind). Wenn der grobe Rahmen der Achsengrenzen feststeht und du "schöne" Werte an den Achsengrenzen haben willst, kannst du den Extent auch im Objektinspektor setzen.

Wenn sich die Maus von der Kurve löst, ist wahrscheinlich der GrabRadius des CurveMoverTool zu klein. Ich musste auf einen Wert von 100 gehen, damit es zuverlässig läuft. Man kann auch noch weiter nach oben gehen, es hätte den Seiteneffekt (auch schon bei 100), dass keine Sicherheit mehr gegeben ist, welche Kurve beim Anklicken gewählt wird, aber nachdem du die Kurve über die Listbox auswählst und die Auswahl über AffectedSeries steuerst, macht das nicht aus. Allerdings kann man bei zu heftigen Mausbewegungen die Kurve aus dem Viewport "schubsen" - und wenn sie nicht mehr zu sehen ist, kriegt man sie auch nicht mehr rein; als Abhilfe könnte evtl. helfen, wenn MouseInsideOnly auf true gesetzt wird, so dass das Verschieben stoppt, wenn die Maus den Viewport verlässt.
wp_xyz
 
Beiträge: 2832
Registriert: 8. Apr 2011, 08:01

Beitragvon ErnstVolker » 12. Feb 2019, 21:30 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Aahh jetzt ja!

Hab' vielen Dank. Jetzt funzt es wie es soll. Das mit dem automatischen Berechnen der Achsen beim Schieben ist ja ganz schön, z.B. wenn man in den negativen Zeitbereich geht, aber es schiebt nicht gut. Ich hatte sowieso vor, die Achsenskalierung des Charts zur Laufzeit über SpinEdit oder FloatSpinEdit vor zu geben. Hab' ich bei Python und NSP auch so gemacht.

Vielen Dank nochmal und viele Grüße

Volker
ErnstVolker
 
Beiträge: 195
Registriert: 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon ErnstVolker » 21. Feb 2019, 09:18 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Kann man das Einfrieren der Achsengrenzen ("Chart.Extent.FixTo()") auch wieder aufheben, damit sich beim Hinzufügen einer weiteren Kurve im Diagramm die Achsengrenzen neu berechnen können?

Danke!
ErnstVolker
 
Beiträge: 195
Registriert: 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon wp_xyz » 21. Feb 2019, 16:19 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Zum Chart.Extent gehört auch "Use*"-Eigenschaften, also wenn du diese auf false setzt, passt sich das entsprechende Achsen-Ende wieder den Daten an:
Code: Alles auswählen
var
  ext: TDoubleRect;
...
  Chart1.Extent.UseYMin := false// Minimum der y-Achse lösen
  Chart1.Extent.UseYMax := false// dto für Maximum
  Chart1.AddSeries(<neue Series>);
  ext := Chart1.GetFullExtent;     // neuen Wertebereich abfragen
  Chart1.Extent.FixTo(ext);        // und wieder den Chart.Extent einfrieren
 
// oder, falls die x-Achse beibehalten werden soll, statt FixTo
  Chart1.Extent.YMax := ext.b.y;
  Chart1.Extent.YMin := ext.a.y;
  Chart1.Extent.UseYMax := true;
  Chart1.Extent.UseYMin := true;
wp_xyz
 
Beiträge: 2832
Registriert: 8. Apr 2011, 08:01

Beitragvon ErnstVolker » 11. Mär 2019, 20:09 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Hallo Guten Abend,

ich bin dabei einen Text an einem Datenpunkt darzustellen. Hierzu verweise ich nochmal auf den Quellcode Eingangs:

Code: Alles auswählen
function TFrm_GUI.ErzeugeSerie(AChart: TAGraph.TChart): TASeries.TLineSeries;
begin
  Result := TLineSeries.Create(AChart.Owner);
  with TLineSeries(Result) do
  begin
    Title := tb_Titel.Text;
    ShowPoints := True;
    ShowLines := True;
    LinePen.Style := psSolid;
    SeriesColor := btn_Farbe.ButtonColor;
    Pointer.Brush.Color := SeriesColor;
    Pointer.Pen.Color := SeriesColor;
    OnCustomDrawPointer := @MeineKurvePointerHandler;
    Source := @Frm_WZ.MeineChartQuelleGetChartDataItem;
  end;
  AChart.AddSeries(Result);
end;


und hänge noch einen Auszug aus der Prozedur MeineKurvePointerHandler an:

Code: Alles auswählen
procedure TFrm_GUI.MeineKurvePointerHandler(ASender: TChartSeries;
  ADrawer: IChartDrawer; AIndex: Integer; ACenter: TPoint);
const
  dx = 8;
  dy = 8;
var
  kurve: TLineSeries;
  rx, ry: Integer;
  pen: TPen;
  vMark: Array of Integer;
begin
  kurve := TLineSeries(ASender);
  rx := kurve.Pointer.HorizSize;
  ry := kurve.Pointer.VertSize;
  ADrawer.Brush := kurve.Pointer.Brush;
  ADrawer.Pen := kurve.Pointer.Pen;
  ADrawer.SetBrushColor(kurve.SeriesColor);
 
  if (AIndex = 200) then begin // Ende der Reaktionsphase (0,8 s)
     ADrawer.Ellipse(ACenter.X-rx, ACenter.Y-ry, ACenter.X+rx, ACenter.Y+ry);
     kurve.ListSource.Item[AIndex]^.Text:='Ein Wert';
  end;


Ich möchte jetzt an den markierten Datenpunkt am Index 200 noch den Beispieltext 'Ein Text' anhängen, aber der Text wird nicht angezeigt. Auch nicht nach einer kurzen Pan-Verschiebeung.
In einem Beispiel von wp_xyz kann ich den Text anfügen, er wird aber erst angezeigt nachdem man die Kurve gezoomt oder per Pan verschoben hat. Auszug Beispiel:

Code: Alles auswählen
procedure TForm1.Chart1LineSeries1CustomDrawPointer(ASender: TChartSeries;
  ADrawer: IChartDrawer; AIndex: Integer; ACenter: TPoint);
const
  dx = 8;
  dy = 8;
var
  rx, ry: Integer;
  pen: TPen;
begin
  // Hervorgehobener Datenpunkt bei s = 70
  if InRange(TLineSeries(ASender).ListSource.Item[AIndex]^.X, 69.98, 70.02) then begin
    rx := TLineSeries(ASender).Pointer.HorizSize;
    ry := TLineSeries(ASender).Pointer.VertSize;
    ADrawer.Brush := TLineSeries(ASender).Pointer.Brush;
    ADrawer.Pen := TLineSeries(ASender).Pointer.Pen;
    ADrawer.Polygon([
      Point(ACenter.X, ACenter.Y-ry),
      Point(ACenter.X+rx, ACenter.Y),
      Point(ACenter.X, ACenter.Y+ry),
      Point(ACenter.X-rx, ACenter.Y),
      Point(ACenter.X, ACenter.Y-ry)
    ], 0, 5);
    TLineSeries(ASender).ListSource.Item[AIndex]^.Text := 'Hase';
  end;


Hier wird der "Hase" ;-) am Datenpunkt angezeigt.

Auch wenn ich "kurve.Marks.Visible:=True;" noch anfüge tut sich nix.

Hat jemand eine Idee? DANKE!
ErnstVolker
 
Beiträge: 195
Registriert: 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon wp_xyz » 11. Mär 2019, 22:14 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Du musst die Datenpunkt-Labels schon beim Erzeugen der Daten für die Series festlegen, nicht erst während der Ausgabe, da ist es zu spät und wird nicht mehr berücksichtigt. Wenn du zu Beginn die x,y-Werte der Series per AddXY hinzufügst, dann gib den Text einfach als dritten Parameter an. Wenn dann LineSeries.Marks.Style auf smsLabel gesetzt ist, wird das Label automatisch ohne weiteren Code angezeigt, wobei man unter Marks noch weitere Parameter zur Formatierung findet.
Code: Alles auswählen
if LineSeries.Count = 200 then 
  LineSeries.AddXY(x, y, 'Mein Text')
else
  LineSeries.AddXY(x, y);
wp_xyz
 
Beiträge: 2832
Registriert: 8. Apr 2011, 08:01

Beitragvon ErnstVolker » 12. Mär 2019, 06:36 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Guten Morgen,

....Marks.Style:=smsLabel macht's schon möglich.

Code: Alles auswählen
if (AIndex = 200) then begin // Ende der Reaktionsphase (0,8 s)
     ADrawer.Ellipse(ACenter.X-rx, ACenter.Y-ry, ACenter.X+rx, ACenter.Y+ry);
     kurve.Marks.Style := smsLabel; //-->Das lässt den Textmarker erscheinen.
     kurve.ListSource.Item[AIndex]^.Text := 'Ein Wert';
     kurve.Marks.Visible := True;
  end;


Durch "OnCustomDrawPointer := @MeineKurvePointerHandler;" in "ErzeugeSerie" wird doch das Aussehen der Kurve schon beim Erzeugen beeinflusst dachte ich.

Vielen Dank für den Tipp!
ErnstVolker
 
Beiträge: 195
Registriert: 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon wp_xyz » 12. Mär 2019, 10:24 Re: TLineSeries zur Laufzeit mit UserDefinesChartSource erst

Ich halte diesen Code für riskant. OnCustomDrawPointer wird während der Paint-Routine aufgerufen und ist dafür gedacht, lediglich das Datenpunkt-Symbol in einer Art zu zeichnen, wie es der Benutzer will. Du änderst dort jedoch auch die anzuzeigenden Daten, indem du dem Datenpunkt einen Labeltext zuweist. Das kann eine erneute Layout-Berechnung triggern - und damit eine erneute Ausgabe. Wodurch OnCustomDrawPointer erneut aufgerufen wird. Das kann gut gehen, kann aber nach künftigen Änderungen an TAChart auch anders sein.

Was spricht dagegen, den LabelText außerhalb der Paint-Methode beim Zuweisen der Daten festzulegen, so wie oben beschrieben?

Hinweis:
Der Code "kurve.ListSource.Item[Aindex]^.AText := 'Ein Wert' allein sendet noch keine Nachricht an den Chart, weshalb der neue Text erst bei der nächsten Ausgabe (z.B. nach Zoomen, Größenveränderung des Chart usw.) berücksichtigt wird. Das ist im Gegensatz zu "kurve.ListSource.SetText(AIndex, 'Ein Wert')", dessen Code am Ende ein "Notify" aufruft und damit die erneute Layout-Berechnung triggern kann.
wp_xyz
 
Beiträge: 2832
Registriert: 8. Apr 2011, 08:01

• Themenende •
Vorherige

Zurück zu Einsteigerfragen



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

cron
porpoises-institution
accuracy-worried