TAChart Tutorial: Getting started/de

From Free Pascal wiki
Jump to navigationJump to search

Deutsch (de) English (en) suomi (fi) français (fr) 日本語 (ja)

Einführung

tachart getting started step6.png

Wenn du einen Plot oder Chart in einem Lazarus-Formular benötigst, solltest du einmal einen Blick auf TAChart werfen. Das ist das von Lazarus standardmäßig dafür zur Verfügung gestellte Package.

In diesem Tutorial werden wir einige elementare mathematische Funktionen mit TAChart zeichnen. Wir werden ein Diagramm mit drei Liniendatenreihen ("Series") erzeugen für die Funktionen

  • y=cos(x),
  • y=sin(x), und
  • y=cos(x)*sin(x).

Vielleicht sollte ich noch die hier immer wieder auftauchenden Begriffe "Series" und "Chart" erläutern: das gesamte Diagramm wird auch als "Chart" bezeichnet (- ist "Chart" im Deutschen ein männliches oder sächliches Substantiv? Ich werde lt. Duden immer von "das Chart" reden). Jede Funktion wird als Kurve dargestellt, und diese wird als "Series", oder eingedeutscht als "Datenreihe" bezeichnet. Die Datenpunkte der Kurve werden durch Linienabschnitte verbunden, deshalb spricht man auch von "Line series" bzw. Liniendatenreihe. Mit TAChart kann man natürlich auch andere Arten von Datenreihen erzeugen, z.b. Balkendatenreihen (Bar series), Flächendatenreihen (Area series) oder aber auch fortgeschrittene Datenreihen für Fit- oder Spline-Kurven.

Was brauchen wir?

Diese Anleitung wird sehr elementar gehalten sein. Natürlich benötigst du grundlegende Kenntnisse der Programmiersprache Object Pascal und musst mit der Lazarus-Entwicklungsumgebung umgehen können.

TAChart ist in Lazarus enthalten. Daher musst du dieses Package nicht irgendwo im Internet suchen und musst auch nichts separat installieren. Allerdings, achte darauf, dass deine Lazarus-Version nicht zu alt ist, denn TAChart wird aktiv weiterentwickelt und kann sich von Version zu Version ändern.

Am besten folgst du diesem Tutorial Schritt für Schritt. Du kannst aber auch den Quellcode des fertigen Projekts am Ende dieses Artikels verwenden.

Ein neues Projekt

TAChart component palette.png

Zu Beginn erzeugen wir in Lazarus ein neues Projekt und wählen dann in der Komponentenpalette den Reiter "Chart". Klicke auf das Icon ganz links, die "TChart"-Komponente, und füge diese dem Formular hinzu. Als Ergebnis siehst du ein leeres Diagramm mit standardisierten x- und y-Achsen.

TAChart GettingStarted Step1.png

Datenreihen hinzufügen

Nun fügen wir Datenreihen hinzu. Zu diesem Zweck, musst du auf das Chart doppel-klicken (oder rechts-klicken und im Kontext-Menü den obersten Eintrag "Datenreihen bearbeiten" auswählen). Nun erscheint der Datenreihen-Editor von TAChart. Es ist noch alles leer, aber wenn du auf "Hinzuf." klickst, klappt ein Menü auf mit allen Arten von Datenreihen, die TAChart zur Verfügung stellt. Wähle "Linien-Diagramm". Wiederhole dies noch zweimal, um ingesamt drei Datenreihen zu erzeugen, die dem Chart zugeordnet werden. Sie sind im Chart noch nicht sichtbar weil sie ja noch keine Daten enthalten. Keine Daten - keine Anzeige. Aber wir werden uns darum gleich kümmern.

TAChart GettingStarted Step1a.png

Aber vorher solltest du dir den Objektbaum über dem Objekt-Inspektor ansehen. TAChart benutzt eine ziemlich komplexe Architektur von Klassen und Containern, daher ist es ganz wesentlich, dass du den Objektbaum verstehst. Im aktuellen Zustand unseres Projekts sehen wir die TChart-Komponente und ihre untergeordneten "Kind"-Komponenten: die drei Liniendatenreihen sowie die Achsenliste ("AxisList"), die ihrerseits wiederum die x und y-Achsen als Kinder enthält (als "Bottom" und "Left" bezeichnet). Die Namen der Datenreihen werden nach dem Schema Chartname<Zahl><Datenreihentyp><Zahl> erzeugt.

tachart getting started object tree.png

Aber warum geben wird den Datenreihen nicht aussagekräftigere Namen, wie SinSeries, CosSeries, und SinCosSeries? Zu diesem Zweck klicken wir auf jede Datenreihe im Objektbaum und ändern ihren Namen im entsprechenden Feld im Objektinspektor darunter.

Daten hinzufügen

Nun wird es Zeit, Daten hinzuzufügen. Die einfachste Methode ist, die Daten zusammen mit dem Formular zu erzeugen. Das heißt, wir schreiben einen Handler für das Ereignis OnCreate des Formulars und weisen dort, wie gleich gezeigt wird, der Datenreihe die entsprechenden Daten zu. In einem "echten" Projekt wird man natürlich die Daten bei anderen Gelegenheiten den Datenreihen zuweisen, z.B. nach einem Button-Click, der eine Berechnung oder das Einlesen der Daten von Datei bewirkt hat.

procedure TForm1.FormCreate(Sender: TObject);
const
  N = 100;
  MIN = -10;
  MAX = 10;
var
  i: Integer;
  x: Double;
begin
  for i:=0 to N-1 do begin
    x := MIN + (MAX - MIN) * i /(N - 1);
    SinSeries.AddXY(x, sin(x));
    CosSeries.AddXY(x, cos(x));
    SinCosSeries.AddXY(x, sin(x)*cos(x));
  end;
end;

Diese Prozedur erzeugt für jede Datenreihe N = 100 Datenpunkte. Die x-Werte werden äquidistant zwischen einem Anfangswert Minimum MIN = -10 und einem Endwert MAX = +10 berechnet, und die y-Werte ergeben sich aus der betreffenden mathematischen Funktion. Die wichtigen Zeilen sind die Aufrufe der AddXY-Methode jeder Datenreihe. Diese Methode erhält die x- und y-Koordinaten jedes Datenpunktes als Parameter und fügt sie einer internen Liste hinzu. Es gibt auch überladene Versionen, bei denen man zusätzlich für jeden Datenpunkt einen Beschriftungstext sowie eine individuelle Farbe angeben kann. Aber dieses Feature brauchen wir hier nicht.

Die erwähnte Liste ist eine sogenannte ChartSource (übersetzt: "Chart-Datenquelle") - das ist eine Klasse, die die zu plottenden Daten zur Verfügung stellt. Man kann - wie oben - die eingebaute Datenquelle verwenden, oder eine separate mit der Datenreihe verbinden. Es gibt in der Komponenten-Palette eine Vielzahl von Chart-Datenquellen, wie

  • TListChartSource, die die Daten in einer Array-ähnlichen Liste speichert (dieser Typ wird von unserer Datenreihe intern verwendet)
  • TDBChartSource, die die Daten aus den Feldern und Records einer Datenbank holt
  • TUserDefinedChartSource, die einen sehr allgemeinen Zugriff auf Daten in allen möglichen Strukturen außerhalb des TAChart-Package ermöglicht, z.B. in einem allgemeinen Array benutzer-definierter Records.
  • TCalculatedChartSource, die die Ergebnisse einer Berechnung der Daten aus einer anderen Chart-Datenquelle zur Verfügung stellt.

Aber genug über Chart-Datenquellen - die eingebaute Quelle ist für dieses einführende Projekt völlig ausreichend.

tachart getting started step2.png

Ok, kompilieren wir das Programm... Wir sehen die drei Kurven, und die x-Achse erstreckt sich automatisch über den Bereich der x-Werte zwischen -10 und +10. Nicht schlecht für den Anfang, aber noch verbesserungswürdig: Das Diagramm ist sehr verwirrend, wir können nicht zwischen den einzelnen Linien unterscheiden, man kann nicht sagen, welche Datenreihe zu welcher Funktion gehört.

Datenreihen formatieren

Warum ändern wir nicht die Farbe jeder einzelnen Datenreihe? Dafür muss man nur im Objekt-Baum jede Datenreihe auswählen und dann im darunterligenden Objekt-Inspektor die Eigenschaft SeriesColor ("Datenreihen-Farbe") so ändern, wie wir wollen. SeriesColor bezeichnet die Farbe der Verbindungslinien zwischen den einzelnen Datenpunkten.

Wenn du jetzt neu kompilierst, siehst du die Datenreihen in Farbe. Aber man kann immer noch nicht unterscheiden, welche Datenreihe sich auf welche Funktion bezieht. Wir brauche eine Legende!

Eine Legende hinzufügen

Wähle das Chart an. Scrolle im Objektinspektor nach unten zur Eigenschaft Legend, öffne die untergeordneten Eigenschaften. Am Ende der Liste findest du die Eigenschaft Visible ("sichtbar"), die standardmäßig auf false steht. OK - stelle sie auf true und kompiliere neu.

tachart getting started step3.png

Es wird besser. Was noch fehlt, ist ein erklärender Text für jede Datenreihe, etwas wie y = sin(x). Kein Problem! Für diesen Zweck hat jede Datenreihe eine Eigenschaft Title - das ist der Text, der stellvertretend für die Datenreihe in der Legende erscheint, zusammen mit einem Symbol für das Aussehen der Datenreihe. Also: gehe nochmals alle Datenreihen durch und gib im Objektinspektor jeweils für Title die folgenden Texte ein: y=sin(x), y=cos(x), and y=sin(x)*cos(x).

tachart getting started step4.png tachart getting started step4a.png

Wenn du jetzt neu kompiliert, ist das Chart fast perfekt. Fast - weil die Legende relativ groß ist und das Diagramm im verfügbaren Platz zusammenquetscht. Natürlich könnte man das Formular mit dem Diagramm vergrößern. Aber könnte man stattdessen nicht die Legende unterhalb des Charts anordnen? Kein Problem: Gehe zurück zur Chart-Eigenschaft Legend und setzte die Eigenschaft Alignment ("Ausrichtung") auf laBottomCenter ("unten Mitte"). Du solltest auch ColumnCount ("Spaltenanzahl") auf 3 setzen, damit die drei Einträge nebeneinander, als 3 Spalten, dargestellt werden.

tachart getting started step5.png

Ah! -- der dritte Legendeneintrag wird abgeschnitten, weil das Fenster nicht breit genug ist. Setze die Eigenschaft Align ("Ausrichten") des Chart auf alClient und vergrößere die Fensterbreite ein bisschen.

Feinabstimmung

Ein paar wenige Dinge kann man noch verbessern: Die Achsen sollten einen Titel haben, etwa "x-Achse" and "y-Achse", und über dem Chart sollte auch ein Titel stehen.

Um den Titel der x-Achse festzulegen, wähle im Objekt-Baum den Eintrag Bottom of the AxisList-Kindkomponente des Chart, oder gehe im Objektinspektor zum Eintrag Bottom axis. Klappe die Untereigenschaften auf, wo das Feld Title zu finden ist. Diese Eigenschaft hat ihrerseits weitere untergeordnete Eigenschaften. Der Text im Feld Caption ("Beschriftung") ist das, was wir suchen - dieser Text wird als Beschriftung an der Achse angezeigt. Vergiss nicht, Visible auf true zu setzen, damit die Beschriftung auch wirklich angezeigt wird. Natürlich kannst du auch die Schriftart z.b. auf fett umstellen: die zugehörige Eigenschaft findest du etwas weiter oben unter LabelFont und Style.

Wiederhole dieses Vorgehen mit der Titel der y-Achse (Left axis). Und im wesentlichen dieselbe Prozedur gilt auch für den Chart-Titel: Scrolle zur Chart-Eigenschaft Title ("Titel"), und tippe den Titel ins Feld Text ein (wo auch mehrzeiliger Text möglich ist). Nicht vergessen: Visible auf true setzen.

Und zum Schluss: Wie wär's mit einem weißen Hintergrund für die durch die Achsen aufgespannte Chart-Fläche? Dafür ist die Eigenschaft BackColor des Chart zuständigt. Und vielleicht sollte das Gitternetz der Achsen weniger deutlich hervortreten? Stelle dazu die Eigenschaft Grid.Color jeder Achse auf die Farbe clSilver um.

Fertig!

Zum Schluss sieht unser Chart so aus. Toll, nicht? Und es war eigentlich gar nicht schwierig...

Wenn du mehr über TAChart lernen willst, solltest du dir die offizielle Dokumentation ansehen und mit einigen der vielen Demos spielen, die zu TAChart gehören. Du findest sie im Ordner components\tachart\demo deiner Lazarus-Installation.

tachart getting started step6.png

Quellcode

Der Quellcode dieses Tutorials steht auch im Ordner tutorials/getting_started neuerer TAChart-Installationen.

Projekt-Datei (.lpr)

program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, Unit1, tachartlazaruspkg
  { you can add units after this };

{$R *.res}

begin
  RequireDerivedFormResource := True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Unit1.pas

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, TAGraph, TASeries, Forms, Controls, Graphics,
  Dialogs;

type

  { TForm1 }

  TForm1 = class(TForm)
    Chart1: TChart;
    SinSeries: TLineSeries;
    CosSeries: TLineSeries;
    SinCosSeries: TLineSeries;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
const
  N = 100;
  MIN = -10;
  MAX = 10;
var
  i: Integer;
  x: Double;
begin
  for i:=0 to N - 1 do begin
    x := MIN + (MAX - MIN) * i / (N - 1);
    SinSeries.AddXY(x, sin(x));
    CosSeries.AddXY(x, cos(x));
    SinCosSeries.AddXY(x, sin(x)*cos(x));
  end;

end;

end.

Unit.lfm

object Form1: TForm1
  Left = 14
  Height = 244
  Top = 137
  Width = 347
  Caption = 'Form1'
  ClientHeight = 244
  ClientWidth = 347
  OnCreate = FormCreate
  LCLVersion = '1.1'
  object Chart1: TChart
    Left = 0
    Height = 244
    Top = 0
    Width = 347
    AxisList = <    
      item
        Grid.Color = clSilver
        Minors = <>
        Title.LabelFont.Orientation = 900
        Title.LabelFont.Style = [fsBold]
        Title.Visible = True
        Title.Caption = 'y axis'
      end    
      item
        Grid.Color = clSilver
        Alignment = calBottom
        Minors = <>
        Title.LabelFont.Style = [fsBold]
        Title.Visible = True
        Title.Caption = 'x axis'
      end>
    BackColor = clWhite
    Foot.Brush.Color = clBtnFace
    Foot.Font.Color = clBlue
    Legend.Alignment = laBottomCenter
    Legend.ColumnCount = 3
    Legend.Visible = True
    Title.Brush.Color = clBtnFace
    Title.Font.Color = clBlue
    Title.Font.Style = [fsBold]
    Title.Text.Strings = (
      'My first chart'
    )
    Title.Visible = True
    Align = alClient
    ParentColor = False
    object SinSeries: TLineSeries
      Title = 'y=sin(x)'
      LinePen.Color = clRed
    end
    object CosSeries: TLineSeries
      Title = 'y=cos(x)'
      LinePen.Color = clBlue
    end
    object SinCosSeries: TLineSeries
      Title = 'y=sin(x)*cos(x)'
      LinePen.Color = clGreen
    end
  end
end