TAChart Tutorial: BarSeries/de

From Free Pascal wiki
Jump to navigationJump to search

Deutsch (de) English (en) suomi (fi) русский (ru)

Einführung

BarSeries finished.png

Die TAChart-Bibliothek kann eine Vielzahl von Diagrammen in Lazarus erstellen. Aber im Vergleich zu anderen Serientypen scheinen Balken-Plots schwieriger zu sein, vor allem, weil es eine Vielzahl von Möglichkeiten gibt:

  • Nebeneinander angeordnete Balken
  • Gestapelte Balken
  • Gestapelte Balken, auf 100 % normiert
  • Vertikale Balken
  • Horizontale Balken

In diesem Tutorial möchten wir dir die Grundidee zeigen, wie du ein Diagramm mit mehreren nebeneinander angeordneten Balkenreihen erstellen kannst. In einem Nachfolge-Tutorial lernst du, wie man die Balken übereinander stapeln kann.

Neben Balkenserien stellt dieses Tutorial auch TRandomChartSource vor, eine praktische Datenquelle zum Entwerfen und Testen eines Diagramms, ohne die Anwendung kompilieren zu müssen.

Du benötigst Grundkenntnisse in Pascal und Lazarus. Wirf einen Blick auf das TAChart Tutorial: Getting started, um einige grundlegende Fähigkeiten für die Arbeit mit TAChart zu erlernen, wenn diese Bibliothek neu für dich ist. Wir empfehlen auch, die TAChart-Dokumentation zu studieren.

Vorbereitung

Einrichten des Diagramms

Erstelle ein neues Projekt und speichere es. Platziere eine TChart-Komponente aus der Lazarus-Komponentenpalette auf dem Formular Form1 und ziehe ihre Größe soweit auf, dass sie den gewünschten Bereich des Formulars ausfüllt.

Daten zum Plotten

Bevor wir fortfahren, müssen wir uns überlegen, welche Daten wir darstellen wollen. Vielleicht könntest du das Guthaben deiner Giro- und Sparkonten verwenden, oder die Geschäftsergebnisse großer Unternehmen, die irgendwo im Internet zu finden sind, oder etwas ganz anderes ...

Gehen wir dieses Mal einen anderen Weg: Warum zeichnen wir nicht einfach zufällige Daten? Natürlich haben diese keine Bedeutung, aber sie sind einfach und sehr bequem zum Üben. Insbesondere enthält TAChart die Komponente TRandomChartSource, die Zufallsdaten bereitstellt, die zur Entwurfszeit nahtlos in einer Datenreihe eingefügt werden können. Das bedeutet, dass du diesem Tutorial folgen kannst, ohne eine Codezeile schreiben zu müssen und ohne die Demo-Anwendung kompilieren zu müssen. Später, wenn die Layoutarbeiten abgeschlossen sind, kannst du die RandomChartSources entfernen und durch ChartSources mit "echten" Daten ersetzen.

Wie wir gleich sehen werden, gibt es im Chart drei Serien, jede davon mit – sagen wir – vier Balken. Für jede Serie benötigst du eine Datenquelle. Wiegesagt, wir nehmen eine TRandomChartSource. Um diese verfügbar zu machen, wirf einen Blick auf die "Chart"-Komponentenpalette - es ist das vierte Symbol in der Palette und im folgenden Screenshot rot hervorgehoben:

TChart Palette RandomChartSource.png

Füge dem Formular drei RandomChartSources hinzu – eine pro Serie. Benenne sie um in RedChartSource, BlueChartSource und YellowChartSource um, da sie mit "roten", "blauen" und "gelben" Balkenreihen verknüpft werden sollen (man sollte immer lieber "sprechende" Variablennamen verwenden.)

Zuvor müssen wir die RandomChartSources einrichten, da sie standardmäßig keine Daten liefern. Wir wollen vier Balken pro Serie haben. Setze daher die Eigenschaft PointsNumber auf 4. Damit die Achsenbeschriftungen mit den Balken synchron sind, muss die x-Achse zwischen 1 und 4 liegen (oder zwischen 0 und 3, oder zwischen 0 und 39, was auch immer du möchtest - wir werden später genauer auf die Achsenbeschriftungen eingehen): XMin = 1, XMax = 4. Und schließlich müssen wir auch den y-Achsenbereich angeben, vielleicht wählst du YMin = 0 und YMax = 100.

Balkenserie

Serie hinzufügen

Nachdem alle Vorbereitungen abgeschlossen sind, können wir die Balkenserie zum Diagramm hinzufügen. Klicke doppelt auf dem Diagramm, um den Reiheneditor zu öffnen, dann auf „Hinzufügen“ und wähle aus der Liste den Eintrag „Balkenserie“ aus. Dasselbe zweimal wiederholen, so dass wir am Ende drei Balkenserien im Chart haben. Wir sehen sie im Diagramm noch nicht, weil sie noch nicht mit unseren Daten verknüpft sind. Im Objektbaum des Objektinspektors erscheinen die Serien jedoch als Unterknoten des "Chart"-Knotens.

Klicke auf die erste Reihe im Objektbaum und gehe im Objektinspektor zur Eigenschaft Source; wähle den Eintrag RedChartSource aus der Liste aus. Jetzt wird die Reihe im Diagramm sichtbar. Um sie "rot" zu machen, gehe Sie zur Eigenschaft SeriesColor und wählen die Farbe clRed. Benenne Sie die Datenreihe um nach „RedBarSeries“ und ändere ihren Titel zu „red“. Letzteres ist für die Legende, die wir aktivieren, indem wir Legend.Visible des Chart auf true setzen.

Wiederhole das mit den anderen beiden Serien entsprechend.

AllBarSeries.png

Jetzt zeigt der Chart die Balkenserien an. Die Balken befinden sich jedoch jeweils auf demselben Wert der x-Achse, die gelben Balken werden teilweise von den anderen Balken verdeckt. Das wollen wir jetzt beheben.

Nebeneinander angeordnete Balken

Um die Balken jeder Gruppe (d. h. Balken, die demselben x-Wert zugeordnet sind) nebeneinander anzuordnen, müssen wir sie horizontal verschieben. TBarSeries bietet zu diesem Zweck zwei Eigenschaften:

  • BarWidthPercent
  • BarOffsetPercent

Beide Zahlen werden in Prozent des Abstands zur nächsten Balkengruppe ausgedrückt. (In manchen Diagrammen sind die Balken nicht äquidistant und erhalten daher unterschiedliche Balkenbreiten. Um in einem solchen Fall eine konstante Balkendicke zu erreichen, setze die Eigenschaft BarWidthStyle auf bwPercentMin.)

Die Grundidee ist, dass der Raum zwischen den Balkengruppen (100%) durch die Balken und etwas Leerraum zur nächsten Gruppe geteilt wird. Wenn wir zwischen den Gruppen eine Lücke von beispielsweise einer Balkenbreite lassen wollen, müssen wir 100 % durch 4 teilen (3 Balken plus Lücke), d. h. jeder Balken kann eine Breite von 25 % einnehmen.

Setzen wir also BarWidthPercent auf 25 und sehen, was passiert. Oh - nicht ganz das, was wir wollten: Die Balken sind zwar schmaler geworden, aber sie überlappen sich immer noch. Dies geschieht natürlich, weil wir den Parameter BarOffsetPercent nicht geändert haben.

Derzeit ist BarOffsetPercent null, was bedeutet, dass sich die Mitte jedes Balkens genau an der Position des Achsenstrichs befindet. Wir müssen die roten Balken nach links und die gelben Balken nach rechts so verschieben, dass sie die in der Mitte verbleibenden blauen Balken berühren. Die Verschiebungsdifferenz beträgt eine Balkenbreite, also 25 %. Um die roten Balken nach links zu verschieben, muss ihr BarOffsetPercent negativ sein.

Zusammenfassend verwenden wir die folgenden Werte:

  • RedBarSeries: BarOffsetPercent = -25, BarWidthPercent = 25
  • BlueBarSeries: BarOffsetPercent = 0, BarWidthPercent = 25
  • YellowBarSeries: BarOffsetPercent = 25, BarWidthPercent = 25

AllBarSeries-side-by-side.png

Achse

Achsenbeschriftung

Das nächste zu behandelnde Problem ist die x-Achse. Normalerweise stellen Balkendiagramme die Kategorien von Datensätzen dar, was häufig Textbeschriftungen unter jeder Balkengruppe erfordert. Aber bisher haben wir hier nur numerische Bezeichnungen. Außerdem sind die Zwischenbeschriftungen bei halben Zahlen unschön.

Der beste Weg, dies richtig zu machen, ist, eine zusätzliche ChartSource für die Zuordnung der Zeichenketten zu den Achsenwerten zu verwenden. Es ist diesmal eine TListChartSource, die als zweites Symbol in der Palette der Diagrammkomponenten zu finden ist. Klicke sie auf das Formular und nenne sie in LabelsChartSource.

Die ListChartSource hat einen eingebauten Datenpunkt-Editor, der es ermöglicht, Daten zur Entwurfszeit einzugeben. Wählen die LabelsChartSource an und gehe im Objekt-Inspektor zur Eigenschaft DataPoints. Klicke rechts auf "...", um den Datenpunkt-Editor zu öffnen, und gib folgende Daten ein:

LabelsSource DataPoints Editor.png

In der Spalte "X" tragen wir die Werte der x-Koordinaten jeder Balkengruppe ein. Wir könnten die "Y"-Spalte weglassen, aber wie wir später bei dem horizontalen Balkendiagramm sehen werden, ist es praktisch, die gleichen Daten auch in dieser Spalte zu haben, damit die Beschriftungen nach dem Drehen der Balken erhalten bleiben. In der Spalte „Text“ legen wir die Texte fest, die für jede Balkengruppe entlang der Achse als Achsenmarkierungen erscheinen sollen. Nehmen wir an, dass unsere Daten saisonale Werte darstellen und verwenden die Abkürzungen „Q1“, „Q2“, „Q3“ und „Q4“ für „Quartal 1“ usw. Die Spalte „Farbe“ kann leer bleiben.

Um diese Beschriftungen zu aktivieren, müssen wir diese ChartSource der Eigenschaft Source der Marks der unteren Achse zuweisen. Weiterhin muss die Eigenschaft Style von Marks auf smsLabel geschaltet werden, denn das wählt für die Beschriftungen den oben unter „Text“ eingegebenen Daten aus.

Voila - und unser Chart sieht nun so aus:

BarSeries with Axis Marks.png

Rasterlinien und Unterteilungsstriche zwischen den Gruppen anzeigen

Ein kleines Problem kann verbessert werden: Das Diagramm wäre verständlicher, wenn sich die Achsenmarkierungen und Gitterlinien nicht in der Mitte der Balkengruppen, sondern direkt zwischen ihnen befinden würden.

Zuerst schalten wir das Raster der unteren Achse aus: BottomAxis.Grid.Visible = false. Um die Unterteilungsstriche ("Ticks") zu entfernen, können wir TickLength und TickInnerLength auf 0 setzen.

Aber wie erzeugt man die Gitterlinien zwischen den Diagrammgruppen? Dies kann durch Erstellen einer "Sekundär-Achse" zur unteren Achse erfolgen. Dies ist ein weiterer Satz von Ticks und Gitterlinien zusätzlich zur "Haupt"-Achse. Gehe zur unteren Achse und klicke auf Minors, um den entsprechenden Editor zu öffnen. Klicke nun auf "Hinzufügen" und wähle den Eintrag 0 - M in der Liste aus. Zurück im normalen Objektinspektor, aktiviere Visible, erhöhe TickLength auf 4 und setze schließlich Intervals.Count auf 1 - Wir wollen nur 1 kleinen Tick zwischen den großen Ticks. Überprüfe Sie die Grid-Einstellungen der Sekundär-Achse - Visible sollte auf true eingestellt sein.

Dies führt zum Endergebnis. Fertig? Nicht ganz! Unter den Balken ist ein störender kleiner Spalt. Dies rührt von der Eigenschaft Margins des Diagramms her, die einen gewissen Abstand zwischen der Reihe und den Achsen lässt. Setze einfach Chart.Margins.Bottom auf 0, um die Lücke zu entfernen.

BarSeries no bottom margins.png

Horizontale Balkenserie

Bevor wir diese Lektion schließen, möchten wir dieses Projekt schnell ändern und ein Diagramm mit horizontalen Balken erstellen. Diese Art von Diagramm wird häufig bevorzugt, wenn die Achsenbeschriftungen aus langen Texten bestehen und das Diagramm im Querformat ausgerichtet ist.

TAChart bietet keine spezielle "THorizontalBarSeries", aber die standardmäßige TBarSeries kann leicht modifiziert werden, um horizontale Balken zu bekommen. Wie bei jedem andere Nachfahren von TChartSeries gibt es auch hier die Eigenschaften AxisIndexX und AxisIndexY, um anzugeben, welche Achse für die x und y Koordinaten verantwortlich ist. Setze einfach AxisIndexX auf den Index der LeftAxis (normalerweise 0) und AxisIndexY auf den Index der BottomAxis; das vertauscht die x- und y-Achsen, und die Balkenrichtung wird gedreht.

Und natürlich muss diesmal die LabelsChartSource mit der Marks.Source der LeftAxis verknüpft werden. Und die Sekundärachse muss entsprechend gehandhabt werden.

Im Grunde ist das alles, was du brauchst, um ein Diagramm mit horizontalen Balken zu erstellen.

Horizontal BarSeries.png

Zusammenfassung

Schritte zum Erstellen eines Balkendiagramms mit nebeneinander angeordneten Balken:

  • Für jeden Balken ist eine eigene BarSeries-Komponente erforderlich.
  • Verwende die BarSeries-Eigenschaften BarWidthPercent und BarOffsetPercent, um die Balken nebeneinander mit oder ohne Überlappung anzuordnen. Die Prozentangaben beziehen sich auf den Abstand zwischen den Mittelpunkten der Balkengruppen.
  • Setze für horizontale Balkenreihen den AxisIndexX der Reihe auf den Index der LeftAxis des Diagramms (normalerweise 0) und AxisIndexY code> auf den Index der BottomAxis (normalerweise 1).

Quellcode

Der Quellcode dieses Tutorials ist im Ordner components/tachart/tutorials/bar_series deiner TAChart-Installation neuerer Lazarus-Versionen verfügbar.

Projektdatei

program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, tachartlazaruspkg, Unit1
  { 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, Forms, Controls, Graphics, Dialogs, TAGraph,
  TASeries, TASources;

type

  { TForm1 }

  TForm1 = class(TForm)
    Chart1: TChart;
    LabelsChartSource: TListChartSource;
    RedBarSeries: TBarSeries;
    BlueBarSeries: TBarSeries;
    YellowBarSeries: TBarSeries;
    RedChartSource: TRandomChartSource;
    BlueChartSource: TRandomChartSource;
    YellowChartSource: TRandomChartSource;
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

end.

Unit1.lfm (vertikale Balken)

object Form1: TForm1
  Left = 381
  Height = 272
  Top = 444
  Width = 429
  Caption = 'Form1'
  ClientHeight = 272
  ClientWidth = 429
  LCLVersion = '1.3'
  object Chart1: TChart
    Left = 0
    Height = 272
    Top = 0
    Width = 384
    AxisList = <    
      item
        Minors = <>
        Title.LabelFont.Orientation = 900
      end    
      item
        Grid.Visible = False
        TickLength = 0
        Alignment = calBottom
        Marks.Format = '%2:s'
        Marks.Source = LabelsChartSource
        Marks.Style = smsLabel
        Minors = <        
          item
            Intervals.Count = 1
            Intervals.MinLength = 5
            Intervals.Options = [aipUseCount, aipUseMinLength]
            TickLength = 4
          end>
      end>
    Foot.Brush.Color = clBtnFace
    Foot.Font.Color = clBlue
    Legend.Visible = True
    Margins.Bottom = 0
    Title.Brush.Color = clBtnFace
    Title.Font.Color = clBlue
    Title.Text.Strings = (
      'TAChart'
    )
    ParentColor = False
    object RedBarSeries: TBarSeries
      Title = 'red'
      BarBrush.Color = clRed
      BarOffsetPercent = -25
      BarWidthPercent = 25
      Source = RedChartSource
    end
    object BlueBarSeries: TBarSeries
      Title = 'blue'
      BarBrush.Color = clBlue
      BarWidthPercent = 25
      Source = BlueChartSource
    end
    object YellowBarSeries: TBarSeries
      Title = 'yellow'
      BarBrush.Color = clYellow
      BarOffsetPercent = 25
      BarWidthPercent = 25
      Source = YellowChartSource
    end
  end
  object RedChartSource: TRandomChartSource
    PointsNumber = 4
    RandSeed = 1
    XMax = 4
    XMin = 1
    YMax = 100
    YMin = 0
    left = 360
    top = 72
  end
  object BlueChartSource: TRandomChartSource
    PointsNumber = 4
    RandSeed = 2
    XMax = 4
    XMin = 1
    YMax = 100
    YMin = 0
    left = 360
    top = 120
  end
  object YellowChartSource: TRandomChartSource
    PointsNumber = 4
    RandSeed = 3
    XMax = 4
    XMin = 1
    YMax = 100
    YMin = 0
    left = 360
    top = 168
  end
  object LabelsChartSource: TListChartSource
    DataPoints.Strings = (
      '1|1|?|Q1'
      '2|2|?|Q2'
      '3|3|?|Q3'
      '4|4|?|Q4'
    )
    left = 361
    top = 220
  end
end

Unit1.lfm (horizontale Balken)

object Form1: TForm1
  Left = 381
  Height = 272
  Top = 444
  Width = 429
  Caption = 'Form1'
  ClientHeight = 272
  ClientWidth = 429
  LCLVersion = '1.3'
  object Chart1: TChart
    Left = 0
    Height = 272
    Top = 0
    Width = 384
    AxisList = <    
      item
        Grid.Visible = False
        TickLength = 0
        Marks.Format = '%2:s'
        Marks.Source = LabelsChartSource
        Marks.Style = smsLabel
        Minors = <        
          item
            Intervals.Count = 1
            Intervals.MinLength = 5
            Intervals.Options = [aipUseCount, aipUseMinLength]
            TickLength = 4
          end>
        Title.LabelFont.Orientation = 900
      end    
      item
        Alignment = calBottom
        Minors = <>
      end>
    Foot.Brush.Color = clBtnFace
    Foot.Font.Color = clBlue
    Legend.Visible = True
    Margins.Bottom = 0
    Title.Brush.Color = clBtnFace
    Title.Font.Color = clBlue
    Title.Text.Strings = (
      'TAChart'
    )
    ParentColor = False
    object RedBarSeries: TBarSeries
      Title = 'red'
      AxisIndexX = 0
      AxisIndexY = 1
      BarBrush.Color = clRed
      BarOffsetPercent = -25
      BarWidthPercent = 25
      Source = RedChartSource
    end
    object BlueBarSeries: TBarSeries
      Title = 'blue'
      AxisIndexX = 0
      AxisIndexY = 1
      BarBrush.Color = clBlue
      BarWidthPercent = 25
      Source = BlueChartSource
    end
    object YellowBarSeries: TBarSeries
      Title = 'yellow'
      AxisIndexX = 0
      AxisIndexY = 1
      BarBrush.Color = clYellow
      BarOffsetPercent = 25
      BarWidthPercent = 25
      Source = YellowChartSource
    end
  end
  object RedChartSource: TRandomChartSource
    PointsNumber = 4
    RandSeed = 1
    XMax = 4
    XMin = 1
    YMax = 100
    YMin = 0
    left = 360
    top = 72
  end
  object BlueChartSource: TRandomChartSource
    PointsNumber = 4
    RandSeed = 2
    XMax = 4
    XMin = 1
    YMax = 100
    YMin = 0
    left = 360
    top = 120
  end
  object YellowChartSource: TRandomChartSource
    PointsNumber = 4
    RandSeed = 3
    XMax = 4
    XMin = 1
    YMax = 100
    YMin = 0
    left = 360
    top = 168
  end
  object LabelsChartSource: TListChartSource
    DataPoints.Strings = (
      '1|1|?|Q1'
      '2|2|?|Q2'
      '3|3|?|Q3'
      '4|4|?|Q4'
    )
    left = 361
    top = 220
  end
end