TAChart Tutorial: Getting started/de
│
Deutsch (de) │
English (en) │
suomi (fi) │
français (fr) │
日本語 (ja) │
русский (ru) │
Einführung
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
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.
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.
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.
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 holtTUserDefinedChartSource
, 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.
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.
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).
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.
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.
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