
Grafische Interfaces XI: Integration der graphischen Standardbibliothek (build 16)
Inhalt
- Einführung
- Veränderungen im Schema der Bibliothek
- Testanwendung für die Eigenschaften von Diagrammen
- Testanwendung für die Eigenschaften der Darstellung von Kurven
- Testanwendung für die Eigenschaften der Darstellung animierter Hypozykloide
- Neue Version der Testanwendung aus den vorherigen Aktualisierungen
- Schlussfolgerung
Einführung
Der erste Artikel Grafische Interfaces I: Vorbereitung der Bibliotheksstruktur (Kapitel 1) erklärt detailliert, wofür die Bibliothek gedacht ist. Sie finden eine Liste von Artikeln mit Verweisen am Ende jeden Kapitels. Dort können Sie auch die komplette, aktuelle Version der Bibliothek zum derzeitigen Entwicklungsstand herunterladen. Die Dateien müssen in die gleichen Verzeichnisse wie im beigefügten Archiv kopiert werden.
Das zweite Kapitel des neunten Teils der Serie, Grafische Interfaces IX: Die Fortschrittsanzeige und das Linienchart-Control (Kapitel 2), zeigte an einem Beispiel, wie eine Klasse zur Erstellung von Liniendiagrammen in die Bibliothek integriert werden kann. Das war eine vorübergehende Lösung, da die Fähigkeiten dieses Teils der Bibliothek sehr mangelhaft waren. Eine neue Version der Grafikbibliothek zur Erstellung wissenschaftlicher Diagramme (die Klasse CGraphic) wurde kürzlich vorgestellt. Einige Funktionen dieser Klasse wurden in Visualisierung! Eine grafische MQL5 Bibliothek ähnlich 'plot' der Sprache R beschrieben. Mit dieser Aktualisierung der weiterentwickelten Bibliothek, um grafische Interfaces zu erstellen, wird eine Version mit neuem Steuerelemente zur Erstellung von Diagrammen eingeführt. Jetzt ist es noch einfacher, Daten verschiedener Typen zu visualisieren.
Veränderungen im Schema der Bibliothek
Früher verwendete die entwickelte Bibliothek zum Zeichnen eine Kopie der Klasse CCanvas. Aufgrund der kürzlich erfolgten globalen Überarbeitung des Bibliothekscodes wird diese Kopie nicht mehr benötigt und kann durch die Originalversion aus der Standardbibliothek ersetzt werden. Dies reduzierte den Umfang der Bibliothek um etwa 10% und um fast 40% gegenüber der vor der Überarbeitungen in den Artikeln Graphische Interfaces XI: Überarbeitung des Bibliothekscodes (build 14.1) und Graphisches Interface XI: Gezeichnete Steuerelemente (build 14.2).
Die Klasse CGraphic wird nun zum Erstellen von Diagrammen verwendet, daher sollte die Datei Graphic.mqh in die Datei Objects.mqh geladen werden. Da die Datei mit der Klasse CCanvas bereits in einer der in der Datei Graphic.mqh enthaltenen Dateien enthalten ist, steht sie somit der gesamten Bibliothek zur Verfügung.
//+------------------------------------------------------------------+ //| Objects.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "Enums.mqh" #include "Defines.mqh" #include "Fonts.mqh" #include "Colors.mqh" #include <Graphics\Graphic.mqh> #include <ChartObjects\ChartObjectSubChart.mqh> ...
Die Klasse CLineChart wurde in CGraph umbenannt, deren Inhalt auch überarbeitet wurde. Diese Klasse enthält nun nur noch die Methoden zur Verwaltung der allgemeinen Eigenschaften und Zustände des Steuerelements.
class CGraph : public CElement { public: //--- Handler der Chartereignisse virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); //--- Verschieben des Steuerelementes virtual void Moving(const bool only_visible=true); //--- Management virtual void Show(void); virtual void Hide(void); virtual void Reset(void); virtual void Delete(void); //--- Anwenden der letzten Änderungen virtual void Update(const bool redraw=false); //--- private: //--- Größenänderung void Resize(const int width,const int height); //--- Ändern der Breite mit dem rechten Rand des Fensters virtual void ChangeWidthByRightWindowSide(void); //--- Ändern der Höhe mit dem unteren Rand des Fensters virtual void ChangeHeightByBottomWindowSide(void); };
Die Eigenschaften des Diagramms können mit der Methode CGraphic::GetGraphicPointer() verwaltet werden, um den Pointer auf eine Instanz der Klasse CGraphic zu erhalten:
class CGraph : public CElement { private: //--- Objekte zum Erstellen des Steuerelementes CGraphic m_graph; //--- public: //--- Rückgabe des Pointers zum Chart CGraphic *GetGraphicPointer(void) { return(::GetPointer(m_graph)); } };
Zusätzliche Klassen wurden in die Klasse CGraphic geladen, um die Eigenschaften der Achsen (CAxis) und Kurven (CCurve) des Diagramms zu handhaben. Die Klasse CColorGenerator dient zur Erzeugung der Kurvenfarben. Alle diese Klassen sind in separaten Dateien, die von der Datei Graphic.mqh geladen werden:
//+------------------------------------------------------------------+ //| Graphic.mqh | //| Copyright 2016-2017, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include <Arrays\ArrayObj.mqh> #include "Curve.mqh" #include "Axis.mqh" #include "ColorGenerator.mqh" ...
Die Datei mit der Klasse CCanvas wird in der Datei Curve.mqh geladen, und steht daher danach der ganzen Bibliothek zur Verfügung.
//+------------------------------------------------------------------+ //| Curve.mqh | //| Copyright 2016-2017, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include <Object.mqh> #include <Canvas\Canvas.mqh> ...
Alle oben erwähnten Beziehung zwischen den Dateien und den Klassen zeigt das Bild unten:
Abb. 1. Die Beziehungen zwischen der standardmäßigen und der weiterentwickelten Bibliothek der Klassen.
Damit stehen die Klassen der Standardbibliothek für das Arbeiten mit Arrays und Dateien automatisch für die Bibliothek und Dateien der Anwendung, in der sie verwendet werden, zur Verfügung. Einige Testanwendungen in MQL werden in dem Artikel weiter unten vorgestellt, um zu verstehen, welche neuen Funktionen nun verfügbar sind.
Testanwendung für die Eigenschaften von Diagrammen
Die erste Testanwendung in MQL wird eine grafische Benutzeroberfläche mit Steuerelementen für die Verwaltung bestimmter Eigenschaften eines Diagramms des Typs CGraphic implementieren. Am oberen Rand des Formulars befindet sich eine Steuerung vom Typ CTabs. In diesem Fall handelt es sich um eine Gruppe von vier Karteireiter. Im Arbeitsbereich der Karteireiter befindet sich ein Diagramm mit zwei Kurven mit zufällig generierten Werten.
Hinter der ersten Karteireiter (Hintergrund) befinden sich die Steuerelemente zur Verwaltung der folgenden Diagrammeigenschaften:
- Hintergrundfarbe.
- Haupttext des Diagramms (oben).
- Hilfstext des Diagramms (unten).
- Farbe des Haupttextes.
- Farbe des Hilfstextes.
- Schriftgröße des Haupttextes.
- Schriftgröße des Hilfstextes.
Um diese Eigenschaften festzulegen und abzurufen, stellt die Klasse CGraphic die entsprechenden 'public' Methoden zur Verfügung:
//+------------------------------------------------------------------+ //| Structure CBackground | //| Verwendung: Hintergrund der zweidimensionalen Grafik | //+------------------------------------------------------------------+ struct CBackground { uint clr; uint clr_main; uint clr_sub; string main; string sub; int size_main; int size_sub; }; //+------------------------------------------------------------------+ //| Class CGraphic | //| Verwendung: Klasse für zweidimensionale Grafiken | //+------------------------------------------------------------------+ class CGraphic { protected: //--- Elemente der Grafik CBackground m_background; // background //--- public: //--- Abfragen der Eigenschaften des Hintergrundes uint BackgroundColor(void) const { return(m_background.clr); } uint BackgroundMainColor(void) const { return(m_background.clr_main); } uint BackgroundSubColor(void) const { return(m_background.clr_sub); } string BackgroundMain(void) const { return(m_background.main); } string BackgroundSub(void) const { return(m_background.sub); } int BackgroundMainSize(void) const { return(m_background.size_main); } int BackgroundSubSize(void) const { return(m_background.size_sub); } //--- Festlegen der Eigenschaften des Hintergrund void BackgroundColor(const uint clr) { m_background.clr=clr; } void BackgroundMainColor(const uint clr) { m_background.clr_main=clr; } void BackgroundSubColor(const uint clr) { m_background.clr_sub=clr; } void BackgroundMain(const string main) { m_background.main=main; } void BackgroundSub(const string sub) { m_background.sub=sub; } void BackgroundMainSize(const int size) { m_background.size_main=size; } void BackgroundSubSize(const int size) { m_background.size_sub=size; } };
Und so sieht das Ganze aus:
Abb. 2. Steuerelemente des ersten Karteireiters (Background) der Testanwendung in MQL.
Die zweite Karteireiter (Indents & history) enthält die Steuerelemente zur Einstellung der folgenden Eigenschaften:
- Einzüge (links, rechts, oben, unten).
- Breite der Legende.
- Schriftgröße der Legende.
- Größe des Markers der Legende.
- Allgemeine Einzüge für alle Elemente des Diagramms.
- Größe des Markers des Skalierung der Achsen.
Die in der folgenden Auflistung aufgeführten Methoden von CGraphic können für die Ermittlung und Einstellung dieser Eigenschaften verwendet werden:
//+------------------------------------------------------------------+ //| Structure CCurveHistory | //| Verwendung: Historie der Kurven einer zweidimensionalen Grafik | //+------------------------------------------------------------------+ struct CCurveHistory { int name_width; int name_size; int symbol_size; int count_total; int count_points; int count_lines; int count_histogram; int count_custom; }; //+------------------------------------------------------------------+ //| Class CGraphic | //| Verwendung: Klasse zum Zeichen zweidimensionaler Grafiken | //+------------------------------------------------------------------+ class CGraphic { protected: //--- Elemente der Grafik CCurveHistory m_history; // Historie //--- public: //--- Abfragen oder Festlegen der Einzüge int IndentUp(void) const { return(m_up0); } void IndentUp(const int up) { m_up0=up; } int IndentDown(void) const { return(m_down0); } void IndentDown(const int down) { m_down0=down; } int IndentLeft(void) const { return(m_left0); } void IndentLeft(const int left) { m_left0=left; } int IndentRight(void) const { return(m_right0); } void IndentRight(const int right) { m_right0=right; } //--- Abfragen oder Festlegen des Abstands int GapSize(void) const { return(m_gap); } void GapSize(const int size) { m_gap=size; } //--- Abfragen oder Festlegen der Größe des Hauptmarkers int MajorMarkSize(void) const { return(m_mark_size); } void MajorMarkSize(const int size) { m_mark_size=size; } //--- Abfragen der Eigenschaften der Historie der Kurve int HistoryNameWidth(void) const { return(m_history.name_width); } int HistoryNameSize(void) const { return(m_history.name_size); } int HistorySymbolSize(void) const { return(m_history.symbol_size); } //--- Festlegen der Eigenschaften der Historie der Kurve void HistoryNameWidth(const int width) { m_history.name_width=width; } void HistoryNameSize(const int size) { m_history.name_size=size; } void HistorySymbolSize(const int size) { m_history.symbol_size=size; } };
Und so schaut jetzt das Grafische Interface der Testanwendung für MQL aus:
Abb. 3. Steuerelement des zweiten Karteireiters (Indents & history) der Testanwendung in MQL.
Der dritte Karteireiter (Grid) verfügt über die Steuerelemente der unten aufgeführten Eigenschaften des Rasters:
- Farbe der Rasterlinien.
- Farbe der Nulllinie.
- Farbe des Hintergrunds des Rasters.
- Zeichnung von Punkten in den Rasterknoten
- Radius der Punkte.
- Farbe der Punkte.
Die entsprechenden Methoden sind in der Klasse CGraphic vorhanden, um diese Eigenschaften abzufragen und festzulegen (siehe den Code unten):
//+------------------------------------------------------------------+ //| Structure CGrid | //| Verwendung: Raster einer zweidimensionalen Grafik | //+------------------------------------------------------------------+ struct CGrid { uint clr_line; uint clr_background; uint clr_circle; uint clr_axis_line; uint clr_frame; int r_circle; bool has_circle; }; //+------------------------------------------------------------------+ //| Class CGraphic | //| Verwendung: Klasse zum Zeichnen einer zweidimensionalen Grafik | //+------------------------------------------------------------------+ class CGraphic { protected: //--- Elemente der Grafik CGrid m_grid; // grid //--- public: //--- Abfrage der Eigenschaften des Rasters uint GridLineColor(void) const { return(m_grid.clr_line); } uint GridAxisLineColor(void) const { return(m_grid.clr_axis_line); } uint GridBackgroundColor(void) const { return(m_grid.clr_background); } int GridCircleRadius(void) const { return(m_grid.r_circle); } uint GridCircleColor(void) const { return(m_grid.clr_circle); } bool GridHasCircle(void) const { return(m_grid.has_circle); } //--- Festlegen der Eigenschaften des Rasters void GridLineColor(const uint clr) { m_grid.clr_line=clr; } void GridAxisLineColor(const uint clr) { m_grid.clr_axis_line=clr; } void GridBackgroundColor(const uint clr) { m_grid.clr_background=clr; } void GridCircleRadius(const int r) { m_grid.r_circle=r; } void GridCircleColor(const uint clr) { m_grid.clr_circle=clr; } void GridHasCircle(const bool has) { m_grid.has_circle=has; } };
Und so schaut es dann aus:
Abb. 4. Steuerelemente des dritten Karteireiters (Grid) der Testanwendung in MQL.
Die Steuerelemente zur Verwaltung der Eigenschaften von Diagrammachsen sind über den vierten Karteireiter (Axes) erreichbar. Die Optionstasten im linken Teil des Arbeitsbereichs der Karteireiter ermöglichen das Umschalten zwischen den Konfiguration einer bestimmten Achse. Diese Tasten sind durch eine Trennlinie von den anderen Elementen des Karteireiter Axes getrennt.
Hier sind die veränderbaren Eigenschaften:
- Automatische Skalierung.
- Minimaler Achsenwert.
- Maximaler Achsenwert.
- Toleranzwert für das Achsenminimum.
- Toleranzwert für das Achsenmaximum.
- Größe der Zahlen der Achsen.
- Maximal angezeigte Länge der Zahlen der Achsen.
- Schriftgröße der Achsennamen.
- Anfangsschrittweite für die Achse.
- Maximale Anzahl von Zahlen auf der Achse.
- Achsenname.
- Textfarbe des Achsennamnes.
Die folgende Auflistung zeigt die Namen der Methoden der Klasse CAxis zur Abfrage und Festlegen der oben genannten Eigenschaften:
//+------------------------------------------------------------------+ //| Class CAxis | //| Verwendung: Klasse zum Erstellen der Achsen einer zweidim. Grafik| //+------------------------------------------------------------------+ class CAxis { private: double m_min; double m_max; uint m_clr; string m_name; int m_name_size; int m_values_size; int m_values_width; bool m_auto_scale; double m_default_step; // Standardschrittweite double m_max_labels; // Maximalzahl der Marker double m_min_grace; // "grace" Wert für den die minimalen Datenbereich double m_max_grace; // "grace" Wert für den die maximalen Datenbereich //--- public: CAxis(void); ~CAxis(void); //--- Eigenschaften double Min(void) const { return(m_min); } void Min(const double min) { m_min=min; } double Max(void) const { return(m_max); } void Max(const double max) { m_max=max; } string Name(void) const { return(m_name); } void Name(const string name) { m_name=name; } //--- Standardeigenschaften uint Color(void) const { return(m_clr); } void Color(const uint clr) { m_clr=clr; } bool AutoScale(void) const { return(m_auto_scale); } void AutoScale(const bool auto) { m_auto_scale=auto; } int ValuesSize(void) const { return(m_values_size); } void ValuesSize(const int size) { m_values_size=size; } int ValuesWidth(void) const { return(m_values_width); } void ValuesWidth(const int width) { m_values_width=width; } int NameSize(void) const { return(m_name_size); } void NameSize(const int size) { m_name_size=size; } double DefaultStep(void) const { return(m_default_step); } void DefaultStep(const double value) { m_default_step=value; } double MaxLabels(void) const { return(m_max_labels); } void MaxLabels(const double value) { m_max_labels=value; } double MinGrace(void) const { return(m_min_grace); } void MinGrace(const double value) { m_min_grace=value; } double MaxGrace(void) const { return(m_max_grace); } void MaxGrace(const double value) { m_max_grace=value; } };
Das Ergebnis ist unten dargestellt:
Abb. 5. Steuerelemente des vierten Karteireiters (Axes) der Testanwendung in MQL.
Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.
Testanwendung für die Eigenschaften der Darstellung von Kurven
Eine eigene MQL-Anwendung wurde geschrieben, um bestimmte Eigenschaften von Kurven auf einem Diagramm des Typs CGraphic zu testen. Steuerelemente für die Verwaltung der Eigenschaften für das Zeichnen von Kurven befinden sich am oberen Rand des Formulars dieser Anwendung, darunter befinden sich zwei Diagramme des Typs CGraphic (das Steuerelement CGraph). Das erste Diagramm zeigt eine Reihe zufälliger Daten, das zweite die Ableitungen, die anhand der Formel des Momentum-Indikators berechnet werden.
Hier sind die Steuerelemente zum Verwalten der Eigenschaften um Kurven zu zeichnen:
- Animate Ankreuzkästchen - Starten der automatische Dateneingabe in das Diagramm.
- Array size Spin-Bearbeitungsfeld – Die aktuelle Anzahl der Elemente im Datenarray, die auf dem Chart angezeigt werden.
- Random Taste – Erzeugen einer zufällige Datenabfolge auf dem Chart.
- Period Spin-Bearbeitungsfeld – Wert der Variablen für die Berechnung des Indikators Momentum.
- Curve type Kombinationsfeld – Kurventyp auf dem Diagramm.
- Point type Kombinationsfeld – Typ der Datenpunkte zum Zeichnen der Kurve.
Die nutzerdefinierte Klasse der Anwendung (CProgram) implementiert Methoden, die sich auf die oben genannten Steuerelemente beziehen und die folgenden Aufgaben ausführen:
- Festlegen der darzustellenden Arraygröße.
- Initialisieren des Arrays mit Daten.
- Aktualisieren des Diagramms mit den letzten Änderungen.
- Hinzufügen einen Elementes am Ende des Arrays.
- Löschen eines Elements vom Ende des Arrays.
- Zeit gesteuertes aktualisieren des Diagramms.
- Animierte Diagramme mit automatischem Eingang neuer Daten.
Nachfolgend ist der Code für alle Methoden angeführt, die diese Funktionen implementieren. Laden Sie die Dateien am Ende des Artikels herunter, wenn Sie mehr Details über den Code dieser Methoden wissen wollen.
class CProgram : public CWndEvents { protected: //--- Array der Daten zur Ausgabe auf den Chart double data1[]; double data2[]; //--- double data3[]; double data4[]; //--- private: //--- Größenänderung des Arrays void ResizeGraph1Arrays(void); void ResizeGraph2Arrays(void); void ResizeGraph1Arrays(const int new_size); void ResizeGraph2Arrays(const int new_size); //--- Initialisierung des Arrays void InitGraph1Arrays(void); void InitGraph2Arrays(void); //--- Arrays auf Null setzten void ZeroGraph1Arrays(void); void ZeroGraph2Arrays(void); //--- Setzen von Zufallswerte am angegebenen Index void SetGraph1Value(const int index); void SetGraph2Value(const int index); //--- Aktualisieren der Werte auf dem Chart void UpdateGraph(void); void UpdateGraph1(void); void UpdateGraph2(void); //--- Neuberechnen der Werte für den Chart void RecalculatingSeries(void); //--- Hinzufügen eines neuen Wertes am Ende des Arrays void AddValue(void); //--- Entfernen des Wertes am Ende des Arrays void DeleteValue(void); //--- Aktualisieren des Charts durch den Timer void UpdateGraphByTimer(void); //--- Animieren der Werte des Charts void AnimateGraphSeries(void); };
Hier ist, wie es aussieht:
Abb. 6. Grafisches Interface der Testanwendung zum Zeichnen von Kurven.
Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.
Testanwendung für die Eigenschaften der Darstellung animierter Hypozykloide
In einem seiner Bücher über VBA-Programmierung in Microsoft Excel stellt John Walkenbach dem Leser eine CD mit Testdateien zur Verfügung. Eine der Dateien implementiert ein Diagramm, in dem eine unendliche Anzahl von Hypozykloiden erzeugt wird.
Als Referenz: Wikipedia gibt folgende Definition an
Ein Hypozykloid (griechisch ὑπό — unten, unter und κύκλος — Kreis, Kreisumfang) ist eine spezielle, ebene Kurve, die durch die Bewegung eines Mittelpunktes eines kleinen Kreis, der auf größeren Kreises rollt, erzeugt wird.
Die Definition von John Walkenbach aus seinem Buch:
Wir implementieren eine ähnliche Anwendung in MQL und fügen ein grafisches Interface der Verwaltung der Parameter hinzu. Lassen Sie uns im Detail sehen, wie es funktioniert.
Aus drei Parametern wird ein neues Hypozykloid erzeugt, mit dem die numerischen Sequenzen mit dem angegebenen Schritt initialisiert werden. Dann werden Berechnungen auf der Grundlage der Werte in diesen Sequenzen durchgeführt, um die Koordinaten der Punkte auf dem Diagramm zu erhalten. Danach werden die erhaltenen Ergebnisse normalisiert.
In der nutzerdefinierten Klasse deklarieren wir mehrere Arrays, um die Sequenzen und Felder zur Berechnung des Mittelwerts und der Standardabweichung zu berechnen.
//+------------------------------------------------------------------+ //| Program.mqh | //| Copyright 2017, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include <Math\Stat\Stat.mqh> #include <EasyAndFastGUI\WndEvents.mqh> #include <EasyAndFastGUI\TimeCounter.mqh> //+------------------------------------------------------------------+ //| Klassen zum Erstellen der Anwendung | //+------------------------------------------------------------------+ class CProgram : public CWndEvents { protected: ... //--- Array der Daten der Berechnung double a_inc[]; double b_inc[]; double t_inc[]; double x_source[]; double y_source[]; //--- Array der Daten zur Ausgabe auf dem Chart double x_norm[]; double y_norm[]; //--- Berechnen von Mittelwert und Standardabweichung double x_mean; double y_mean; double x_sdev; double y_sdev; ... }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CProgram::CProgram(void) : x_mean(0), y_mean(0), x_sdev(0), y_sdev(0) { ... }
Die Werte werden in der Methode CProgram::InitArrays() berechnet. Der erste Zyklus berechnet hier die Ausgangsdaten. Danach werden Mittelwert und Standardabweichung ermittelt und der zweite Zyklus normalisiert die Daten. Die Größen der Arrays werden mit der Methode CProgram::ResizeArrays() festgelegt. Die Werte für die Größen des Arrays werden aus dem Textfeld des Steuerelementes (CTextEdit) des grafischen Interfaces der Anwendung übernommen.
class CProgram : public CWndEvents { private: //--- Größenänderung des Arrays void ResizeArrays(void); //--- Initialisieren des Hilfsarrays zur Berechnung void InitArrays(void); }; //+------------------------------------------------------------------+ //| Größenänderung des Arrays | //+------------------------------------------------------------------+ void CProgram::ResizeArrays(void) { int array_size =::ArraySize(x_norm); int new_size =(int)m_array_size.GetValue(); //--- Verlassen, wenn keine Größenänderung if(array_size==new_size) return; //--- Festlegen der neuen Größe ::ArrayResize(a_inc,new_size); ::ArrayResize(b_inc,new_size); ::ArrayResize(t_inc,new_size); ::ArrayResize(x_source,new_size); ::ArrayResize(y_source,new_size); ::ArrayResize(x_norm,new_size); ::ArrayResize(y_norm,new_size); } //+------------------------------------------------------------------+ //| Initialisierung der Arrays | //+------------------------------------------------------------------+ void CProgram::InitArrays(void) { //--- Größenänderung der Arrays ResizeArrays(); //--- Berechnen der Werte mit der Formel int total=(int)m_array_size.GetValue(); for(int i=0; i<total; i++) { if(i<1) { a_inc[i] =1+(double)m_animate.GetValue(); b_inc[i] =1+(double)m_animate.GetValue(); t_inc[i] =1+(double)m_animate.GetValue(); } else { a_inc[i] =a_inc[i-1]+(double)m_a_inc.GetValue(); b_inc[i] =b_inc[i-1]+(double)m_b_inc.GetValue(); t_inc[i] =t_inc[i-1]+(double)m_t_inc.GetValue(); } //--- double a=a_inc[i]; double b=b_inc[i]; double t=t_inc[i]; //--- x_source[i] =(a-b)*cos(t)+b*cos((a/b-1)*t); y_source[i] =(a-b)*sin(t)+b*sin((a/b-1)*t); } //--- Berechnen des Mittelwertes x_mean=MathMean(x_source); y_mean=MathMean(y_source); //--- Berechnen der Standardabweichung x_sdev=MathStandardDeviation(x_source); y_sdev=MathStandardDeviation(y_source); //--- Abfangen einer Division durch Null x_sdev =(x_sdev==0)? 1 : x_sdev; y_sdev =(y_sdev==0)? 1 : y_sdev; //--- Normalisieren der Daten for(int i=0; i<total; i++) { x_norm[i] =(x_source[i]-x_mean)/x_sdev; y_norm[i] =(y_source[i]-y_mean)/y_sdev; } }
Die Klasse CGraphic enthält Methoden, die es erlauben, innerhalb des Arbeitsbereiches des erstellten Diagramms zusätzliche Ausschnitte, Linien und Texte zu den Achsenskalen hinzuzufügen.
In unserem Fall wird die Methode CProgram::TextAdd() verwendet, um die Werte des Mittelwerts und der Standardabweichung für X- und Y-Sequenzen in der linken oberen Ecke des Diagramms auszugeben. Die Methoden CGraphic::ScaleX() und CGraphic::ScaleY() werden verwendet, um die Koordinaten des äußersten linken Punktes (obere linke Ecke) des Diagramms zu erhalten. Sie dienen zur Skalierung der tatsächlichen Werte des Diagramms in Pixelkoordinaten. Hier werden das Minimum auf der X-Achse und das Minimum auf der Y-Achse als reale Werte angegeben.
class CProgram : public CWndEvents { private: //--- Schreiben von Text auf dem Chart void TextAdd(void); }; //+------------------------------------------------------------------+ //| Schreiben von Text auf dem Chart | //+------------------------------------------------------------------+ void CProgram::TextAdd(void) { //--- Abfragen des Pointers zum Chart CGraphic *graph=m_graph1.GetGraphicPointer(); //--- int x =graph.ScaleX(graph.XAxis().Min())+50; int y =graph.ScaleY(graph.YAxis().Max())+10; int y2 =y+20; uint clr =::ColorToARGB(clrBlack); uint align =TA_RIGHT; //--- string str[8]; str[0] ="x mean:"; str[1] ="y mean:"; str[2] =::DoubleToString(x_mean,2); str[3] =::DoubleToString(y_mean,2); str[4] ="x sdev:"; str[5] ="y sdev:"; str[6] =::DoubleToString(x_sdev,2); str[7] =::DoubleToString(y_sdev,2); //--- Berechnen der Koordinaten und Ausgabe des Textes auf den Chart int l_x=0,l_y=0; for(int i=0; i<8; i++) { if(i<2) l_x=x; else if(i<6) l_x=(i%2==0)? l_x+50 : l_x; else l_x=(i%2==0)? l_x+60 : l_x; //--- l_y=(i%2==0)? y : y2; //--- graph.TextAdd(l_x,l_y,str[i],clr,align); } }
Nachdem alle erforderlichen Daten auf dem Diagramm festgelegt sind, muss es neu gezeichnet werden, um die letzten Änderungen darzustellen. Das geschieht durch die Methode CProgram::UpdateSeries(). Hier wird zunächst geprüft, ob sich Serien auf dem Diagramm befinden. Wenn ja, werden die zuletzt berechneten Daten verwendet. Zusätzlich werden die Eigenschaften der Kurve über die Steuerelemente des grafischen Interface eingestellt. Hier sind dies (1) die Linienglättung, (2) die Art der Punkte und (3) die Art der Kurve. Es ist zu beachten, dass es notwendig ist, den Text in der Grafik zu implementieren, nachdem alle anderen Eigenschaften und Daten installiert und gezeichnet wurden. Am Ende ist es notwendig, das Diagramm zu aktualisieren, um das Ergebnis zu sehen.
class CProgram : public CWndEvents { private: //--- Festlegen und Aktualisieren der Werte auf dem Chart void UpdateSeries(void); }; //+------------------------------------------------------------------+ //| Festlegen und Aktualisieren der Werte auf dem Chart | //+------------------------------------------------------------------+ void CProgram::UpdateSeries(void) { //--- Abfragen des Pointers auf den Chart CGraphic *graph=m_graph1.GetGraphicPointer(); //--- Aktualisieren aller Werte auf dem Chart int total=graph.CurvesTotal(); if(total>0) { //--- Abfrage des Pointers auf die Kurve CCurve *curve=graph.CurveGetByIndex(0); //--- Festlegen der Datenarrays curve.Update(x_norm,y_norm); //--- Abfrage der Eigenschaften der Kurve ENUM_CURVE_TYPE curve_type =(ENUM_CURVE_TYPE)m_curve_type.GetListViewPointer().SelectedItemIndex(); ENUM_POINT_TYPE point_type =(ENUM_POINT_TYPE)m_point_type.GetListViewPointer().SelectedItemIndex(); //--- Festlegen der Eigenschaften curve.LinesSmooth(m_line_smooth.IsPressed()); curve.PointsType(point_type); curve.Type(curve_type); } //--- Anwenden graph.Redraw(true); //--- Textausgabe TextAdd(); //--- Aktualisieren des Charts graph.Update(); }
Die Methode CProgram::RecalculatingSeries() wird zur Berechnung und Anwendung der erhaltenen Ergebnisse in einem einzigen Aufruf verwendet:
class CProgram : public CWndEvents { private: //--- Neuberechnen der Werte des Charts void RecalculatingSeries(void); }; //+------------------------------------------------------------------+ //| Neuberechnen der Werte des Charts | //+------------------------------------------------------------------+ void CProgram::RecalculatingSeries(void) { //--- Berechnen der Werte und Initialisierung der Arrays InitArrays(); //--- Aktualisieren der Werte UpdateSeries(); }
Das Diagramm basiert auf diesen Formeln wird interessanter aussehen, wenn es animiert wird. Um die berechneten Sequenzen in Bewegung zu setzen, ist es notwendig, den Anfangswert dieser Sequenzen zu ändern. Dies kann durch Eingabe von Werten über das Spin-Bearbeitungsfeld oder durch die automatische Ausführen des Prozesses erreicht werden. Im automatischen Modus wird der Wert in diesem Eingabefeld in der Methode CProgram::AnimateGraphSeries() erhöht oder erniedrigt. Diese Methode wird in der Methode CProgram::UpdateGraphByTimer() aufgerufen, die ihrerseits im Timer der Anwendung aufgerufen wird.
class CProgram : public CWndEvents { private: //--- Aktualisieren des Charts durch den Timer void UpdateGraphByTimer(void); //--- Animieren der Werte des Charts void AnimateGraphSeries(void); }; //+------------------------------------------------------------------+ //| Timer | //+------------------------------------------------------------------+ void CProgram::OnTimerEvent(void) { CWndEvents::OnTimerEvent(); //--- Aktualisieren des Charts durch den Timer if(m_counter1.CheckTimeCounter()) { UpdateGraphByTimer(); } ... } //+------------------------------------------------------------------+ //| Aktualisieren des Charts durch den Timer | //+------------------------------------------------------------------+ void CProgram::UpdateGraphByTimer(void) { //--- Verlassen, wenn (1) Anzeige ist minimiert oder (2) Animation ist deaktiviert if(m_window.IsMinimized() || !m_animate.IsPressed()) return; //--- Animieren der Werte des Charts AnimateGraphSeries(); //--- Aktualisieren der Arrays und der Werte des Charts RecalculatingSeries(); } //+------------------------------------------------------------------+ //| Animieren der Werte des Charts | //+------------------------------------------------------------------+ void CProgram::AnimateGraphSeries(void) { //--- Zur Richtungsangabe und Größenänderung der Arrays static bool counter_direction=false; //--- Richtungswechsel, wenn das Minimum erreicht wurde if((double)m_animate.GetValue()<=(double)m_animate.MinValue()) counter_direction=false; //--- Richtungswechsel, wenn das Maximum erreiccht ist if((double)m_animate.GetValue()>=(double)m_animate.MaxValue()) counter_direction=true; //--- Größenänderung des Arrays in der angegebenen Richtung string value=""; if(!counter_direction) value=string((double)m_animate.GetValue()+m_animate.StepValue()); else value=string((double)m_animate.GetValue()-m_animate.StepValue()); //--- Fetslegen der neuen Werte und aktualisieren des Eingabefeldes m_animate.SetValue(value,false); m_animate.GetTextBoxPointer().Update(true); }
Das erhaltene Ergebnis ist unten dargestellt:
Abb. 7. Demonstration eines animierten Hypozykloids.
Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.
Neue Version der Testanwendung aus den vorherigen Aktualisierungen
Die im Artikel Grafische Interfaces IX: Die Fortschrittsanzeige und das Linienchart-Control (Kapitel 2) vorgestellte Testanwendung wurde entsprechend den Änderungen in diesem Update aktualisiert.
Die neue Version dieser MQL-Anwendung mit dem aktualisierten grafischen Interface ist unten dargestellt:
Abb. 8. Neue Version der Testanwendung der vorhergehenden Aktualisierungen.
Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.
Schlussfolgerung
In diesem Artikel wurde ein Teil der Standardbibliothek zum Zeichnen von wissenschaftlichen Diagrammen in die entwickelte Bibliothek zur Erstellung von grafischen Interfaces integriert. Alle Beispiele können von den Dateien heruntergeladen werden, die diesem Artikel beigefügt sind, um den Quellcode genauer zu studieren.
Das Schema der Bibliothek im aktuellen Entwicklungsstadium sieht wie folgt aus:
Abb. 9. Die Struktur der Bibliothek im aktuellen Zustand der Entwicklung
Der vorgestellte Code ist kostenfrei. Sie können ihn in Ihren, auch kommerziellen, Projekten verwenden, damit Artikel schreiben und ihn für eigene Aufträge verwenden.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/3527





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
"Wenn Sie Fragen zur Verwendung des Materials aus dem Artikel haben, können Sie diese im Kommentarteil stellen."
Heisst es am Ende des Artikels.
JA UND WAS HABE ICH DAVON WENN NIEMAND ANTWORTET ?
Der Autor meint er hat keine Zeit. Dieses .................
"Wenn Sie Fragen zur Verwendung des Materials aus dem Artikel haben, können Sie diese im Kommentarteil stellen."
Heisst es am Ende des Artikels.
JA UND WAS HABE ICH DAVON WENN NIEMAND ANTWORTET ?
Der Autor meint er hat keine Zeit. Dieses .................
Ich habe bisher weder mit mt5 noch gar mit dieser Bibliothek gearbeitet, aber:
- Ich würde aber denken, dass die letzte Version alle bisherigen ersetzt oder ersetzen soll - so wäre es jedenfalls meiner Meinung nach korrekt!
- Wenn Du hier keine Antwort kriegst schreibe auf der Kommentarseite des Originals (https://www.mql5.com/ru/forum/212721) mit Deinem Text in Deutsch, in Englisch und Russisch. Zur Übersetzung verwendest Du ganz einfach google-translate.
(Kleiner Trick, ich habe mal gelesen google-translate übersetzt deutsch-russisch anscheinend immer über Englisch, also erst ins Englische, das eventuell korrigieren und dann ins Russische!)Hallo Otto,
hat sich der Programmierer inzwischen dazu geäußert bzw. die Fehler korrigiert.
Das Dilemma beginnt bereits mit dem 1. Kapitel des Grafischen Interfaces I.
Das ist alles sehr schade, da sich der Programmierer mit den vielen Artikeln hier eine Menge Arbeit gemacht hat.
Nur wenn permant der Compiler Fehlermeldungen auswirft, dann verliert man schnell die Lust das nachzuproggen
und der Lerneffekt ist dann natürlich auch nicht gegeben.
VG
Steffen
Ich würde nur die letzte Version verwenden.
Eine Übersicht ist hier: https://www.mql5.com/en/code/19703
Ich hab das Thema auch aufgegeben.
Kenne das was Otto bemängelt.
Ich habe es aber fast immer wieder hinbekommen.Viel umprogrammiert aber danach lief es immer. Nur die Zeit geht verloren.
Der Ersteller müsste mal riesengroß BETA reinschreiben.
Denn nichts anderes ist das.