Interfaces gráficas XI: Integración de la librería gráfica estándar (build 16)
Contenido
- Introducción
- Cambios en el esquema de la librería
- Aplicación para la prueba de las propiedades del gráfico
- Aplicación para probar las propiedades de las curvas del gráfico
- Aplicación con gráfico animado de hipocicloide
- Nueva versión de la aplicación de prueba desde las actualizaciones anteriores
- Conclusión
Introducción
El primer artículo de la serie nos cuenta con más detalles para qué sirve esta librería: Interfaces gráficas I: Preparación de la estructura de la librería (Capítulo 1). Al final de los artículos de cada parte se puede encontrar la lista de los capítulos con los enlaces, así como descargar la versión completa de la librería en la fase actual del desarrollo del proyecto. Es necesario colocar los ficheros en los mismos directorios, tal como están ubicados en el archivo.
En el segundo capítulo de la novena parte de la serie Interfaces gráficas IX: Controles «Indicador de progreso» y «Gráfico lineal» (Capítulo 2), fue demostrado cómo se podía integrar la clase para crear los gráficos lineales en la librería. Fue una solución temporal porque las posibilidades de esta parte de la librería estándar no eran suficientes. Desde hace poco tiempo, fue presentada la nueva versión de la librería gráfica para el diseño de los gráficos científicos (clase CGraphic). La descripción de algunas funciones de esta clase fue presentada en el artículo ¡Visualice esto! la biblioteca gráfica en MQL5 como un análogo de plot en el lenguaje R. En esta actualización de la librería para la creación de las interfaces gráficas será presentada la versión con nuevo control para crear los gráficos. Ahora, será aún más fácil visualizar los datos de diferentes tipos.
Cambios en el esquema de la librería
Antes, en esta librería se usaba la copia de la clase CCanvas destinada para el dibujado. Debido a la refactorización global del código de la librería realizada hace poco, ahora esta copia no es necesaria y se puede eliminarla, sustituyendo por la versión original desde la librería original. Eso redujo el volumen de la librería aproximadamente en un 10%, y casi en un 40% respecto a la versión que había presentada antes de la refactorización en los artículos Interfaces gráficas XI: Refactorización del código de la librería (build 14.1) e Interfaces gráficas XI: Controles dibujados (build 14.2)
Ahora, para crear los gráficos, va a usarse la clase CGraphic, por eso incluiremos el archivo Graphic.mqh en el archivo Objects.mqh. Puesto que el archivo con la clase CCanvas está incluido en uno de los archivos que están incluidos en el archivo Graphic.mqh, él también estará disponible para toda la librería.
//+------------------------------------------------------------------+ //| 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> ...
La clase CLineChart fue renombrado en CGraph. Su contenido también fue cambiado. Ahora, en esta clase hay sólo los métodos para gestionar las propiedades generales y los estados del control.
class CGraph : public CElement { public: //--- Manejador de eventos del gráfico virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); //--- Desplazamiento del control virtual void Moving(const bool only_visible=true); //--- Gestión virtual void Show(void); virtual void Hide(void); virtual void Reset(void); virtual void Delete(void); //--- Aplicación de últimos cambios virtual void Update(const bool redraw=false); //--- private: //--- Cambio de tamaños void Resize(const int width,const int height); //--- Cambiar el ancho por el lado derecho de la ventana virtual void ChangeWidthByRightWindowSide(void); //--- Cambiar el alto por el borde inferior de la ventana virtual void ChangeHeightByBottomWindowSide(void); };
Se puede gestionar las propiedades del gráfico si obtenemos el puntero a la instancia de la clase CGraphic a través el método CGraphic::GetGraphicPointer() :
class CGraph : public CElement { private: //--- Objetos para crear el control CGraphic m_graph; //--- public: //--- Devuelve el puntero al gráfico CGraphic *GetGraphicPointer(void) { return(::GetPointer(m_graph)); } };
Las clases adicionales están incluidos en la clase CGraphic, sirven para gestionar las propiedades de los ejes (CAxis) y curvas (CCurve) del gráfico. La clase CColorGenerator sirve para generar el color de las curvas. Todas estas clases se encuentran en unos archivos separados que están incluidos en el archivo Graphic.mqh:
//+------------------------------------------------------------------+ //| 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" ...
El archivo con la clase CCanvas está incluido en el archivo Curve.mqh, y desde aquí estará disponible para toda la librería.
//+------------------------------------------------------------------+ //| Curve.mqh | //| Copyright 2016-2017, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include <Object.mqh> #include <Canvas\Canvas.mqh> ...
En la imagen de abajo se muestran todas las conexiones mencionadas entre los archivos y las clases:
Fig. 1. Conexiones entre las clases de la librería estándar y librería en desarrollo.
De esta manera, para la librería y los archivos de la aplicación donde se utiliza, automáticamente se hacen disponibles las clases de la librería estándar para el trabajo con los arrays y los archivos. Luego, en este artículo serán demostradas varias aplicaciones MQL de prueba para comprender mejor qué posibilidades están disponibles ahora.
Aplicación para la prueba de las propiedades del gráfico
En la primera aplicación de prueba, implementamos la interfaz gráfica con los controles para manejar algunas propiedades del gráfico tipo CGraphic. Colocaremos el control tipo CTabs en la parte superior del formulario. En este caso, es el grupo de cuatro pestañas. Debajo del área de trabajo de las pestañas, estará ubicado el gráfico con dos curvas cuyos valores serán generados de forma aleatoria.
En la primera pestaña (Background), vamos a crear los controles que permitirán manejar las siguientes propiedades del gráfico:
- Color del fondo.
- Texto principal del gráfico (se muestra en la parte superior).
- Texto auxiliar del gráfico (se muestra en la parte inferior).
- Color del texto principal.
- Color del texto auxiliar.
- Tamaño de la fuente del texto principal.
- Tamaño de la fuente del texto auxiliar.
Para establecer y obtener estas propiedades, la clase CGraphic contiene los métodos públicos correspondientes:
//+------------------------------------------------------------------+ //| Structure CBackground | //| Usage: background on a two-dimensional graphics | //+------------------------------------------------------------------+ struct CBackground { uint clr; uint clr_main; uint clr_sub; string main; string sub; int size_main; int size_sub; }; //+------------------------------------------------------------------+ //| Class CGraphic | //| Usage: class for drawing two-dimensional graphics | //+------------------------------------------------------------------+ class CGraphic { protected: //--- element of graphic CBackground m_background; // background //--- public: //--- gets the background properties 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); } //--- sets the background properties 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; } };
A continuación, se puede observar como es:
Fig. 2. Los controles de la primera pestaña (Background) de la aplicación MQL de prueba.
En la segunda pestaña (Indents & history), ubicaremos los controles para establecer las siguientes propiedades:
- Márgenes (izquierda, derecha, arriba, abajo).
- Ancho de la leyenda.
- Tamaño de la fuente de la leyenda.
- Tamaño de los marcadores de la leyenda.
- Márgenes generales entre todos los controles del gráfico.
- Tamaño de las marcas en las escalas de los ejes del gráfico.
Para obtener y establecer estas propiedades, se puede usar los métodos CGraphic que se muestran en el listado del código de abajo:
//+------------------------------------------------------------------+ //| Structure CCurveHistory | //| Usage: history of curves on a two-dimensional graphics | //+------------------------------------------------------------------+ 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 | //| Usage: class for drawing two-dimensional graphics | //+------------------------------------------------------------------+ class CGraphic { protected: //--- element of graphic CCurveHistory m_history; // history //--- public: //--- gets or sets indents 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; } //--- gets or sets gap int GapSize(void) const { return(m_gap); } void GapSize(const int size) { m_gap=size; } //--- gets or sets major mark size int MajorMarkSize(void) const { return(m_mark_size); } void MajorMarkSize(const int size) { m_mark_size=size; } //--- gets the curve history properties 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); } //--- sets the curve history properties 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; } };
Abajo se muestra cómo se ve eso en la interfaz gráfica de una aplicación MQL:
Fig. 3. Controles de la segunda pestaña (Indents & history) de la aplicación MQL de prueba.
En la tercera pestaña (Grid), se encuentran los controles para establecer las propiedades de la cuadrícula que se listan a continuación:
- Color de las líneas de la cuadrícula.
- Color de línea cero de los ejes.
- Color del fondo de la cuadrícula.
- Dibujado de los puntos en los nodos de la cuedrícula.
- Radio de los puntos.
- Color de los puntos.
Para obtener y establecer estas propiedades, en la clase CGraphic hay métodos correspondientes (véase el código de abajo):
//+------------------------------------------------------------------+ //| Structure CGrid | //| Usage: grid on a two-dimensional graphics | //+------------------------------------------------------------------+ 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 | //| Usage: class for drawing two-dimensional graphics | //+------------------------------------------------------------------+ class CGraphic { protected: //--- element of graphic CGrid m_grid; // grid //--- public: //--- gets the grid properties 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); } //--- sets the grid properties 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; } };
Pues, es lo que veremos al final:
Fig. 4. Controles de la tercera pestaña (Grid) de la aplicación MQL.
En la cuarta pestaña (Axes), se ubicarán los controles a través de los cuales se puede cambiar las propiedades de los ejes del gráfico. Para cambiar entre los ejes, se usarán los botones de opción en la parte izquierda del área de trabajo de las pestañas, que se encuentra separada de los demás controles de la pestaña Axes con una línea separadora.
Las propiedades que estarán disponibles para el ajuste son las siguientes:
- Redimensionamiento automático.
- Valor mínimo del eje.
- Valor máximo del eje.
- Valor del suplemento para el mínimo del eje.
- Valor del suplemento para el máximo del eje.
- Tamaño de los números en el eje.
- Longitud máxima de los números a mostrar en el eje.
- Tamaño de la fuente para el nombre del eje.
- Valor inicial del paso en el eje.
- Cantidad máximo de los números en el eje.
- Nombre del eje.
- Color del texto del nombre del eje.
Abajo se muestran los nombres de los métodos de la clase CAxis para obtener y modificar las propiedades descritas:
//+------------------------------------------------------------------+ //| Class CAxis | //| Usage: class for create axes on a two-dimensional graphics | //+------------------------------------------------------------------+ 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; // length of the default step double m_max_labels; // the maximum number of marks double m_min_grace; // "grace" value applied to the minimum data range double m_max_grace; // "grace" value applied to the maximum data range //--- public: CAxis(void); ~CAxis(void); //--- properties 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; } //--- default properties 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; } };
Abajo se muestra lo que hemos obtenido al final:
Fig. 5. Controles de la cuarta pestaña (Axes) de la aplicación MQL de prueba.
Puede descargar esta aplicación de prueba al final del artículo para estudiarla más detalladamente.
Aplicación para probar las propiedades de las curvas del gráfico
Para las pruebas de algunas propiedades de las curvas del gráfico tipo CGraphic, fue escrita una aplicación MQL especial. En la parte superior del formulario de esta aplicación, se encuentran los controles para manejar las propiedades de las curvas del gráfico, y debajo de ellos se ubican dos gráficos tipo CGraphic (control CGraph). En el primer gráfico, veremos las series con datos aleatorios, en el segundo, van a construirse sus derivados, que serán calculados (como ejemplo) según la fórmula del indicador Momentum.
Éstos son los controles para manejar las propiedades de las curvas del gráfico:
- Checkbox Animate – sirve para iniciar la llegada automática de los datos al gráfico.
- Campo de edición Array size – número actual de controles en el array de los datos mostrados en el gráfico.
- Botón Random – genera las consecuencias aleatorias de los datos en las series en el gráfico.
- Camos de edición Period – valor de la variable para calcular el indu¡icador Momentum.
- Combobox Curve type – selección del tipo de las curvas en el gráfico.
- Combobox Point type – selección del tipo de los puntos de datos a base de los cuales se construyen las curvas en el gráfico.
En la clase personalizada de la aplicación (CProgram), han sido implementados los métodos que están vinculados con los controles arriba mencionados y ejecutan las siguientes tareas:
- Establecimiento del tamaño para los arrays para mostrar los datos en el gráfico.
- Inicialización de arrays usando los datos.
- Actualización de los gráficos para mostrar los últimos cambios.
- Adición de un control al final de los arrays.
- Eliminación de un control al final de los arrays.
- Actualización de los gráficos por el temporizador.
- Animación de los gráficos con la llegada automática de nuevos datos.
Los métodos donde todo eso está implementado se muestran a continuación. Puede estudiar al detalle el código de estos métodos en los archivos adjuntos al artículo.
class CProgram : public CWndEvents { protected: //--- Arrays de los datos para mostrar en los gráficos double data1[]; double data2[]; //--- double data3[]; double data4[]; //--- private: //--- Establecer el tamaño nuevo de los arrays void ResizeGraph1Arrays(void); void ResizeGraph2Arrays(void); void ResizeGraph1Arrays(const int new_size); void ResizeGraph2Arrays(const int new_size); //--- Inicialización de arrays void InitGraph1Arrays(void); void InitGraph2Arrays(void); //--- Puesta a cero de arrays void ZeroGraph1Arrays(void); void ZeroGraph2Arrays(void); //--- Establece el valor aleatorio según el índice especificado void SetGraph1Value(const int index); void SetGraph2Value(const int index); //--- Actualizar las series en el gráfico void UpdateGraph(void); void UpdateGraph1(void); void UpdateGraph2(void); //--- Recálculo de las series en el gráfico void RecalculatingSeries(void); //--- Añade un valor al final de los arrays void AddValue(void); //--- Elimina un valor al final de los arrays void DeleteValue(void); //--- Actualización del gráfico por el temporizador void UpdateGraphByTimer(void); //--- Animación de las series del gráfico void AnimateGraphSeries(void); };
Abajo se muestra el resultado:
Fig. 6. Interfaz gráfica de la aplicación para testear las propiedades de las curvas del gráfico.
Puede descargar esta aplicación de prueba al final del artículo para estudiarla más detalladamente.
Aplicación con gráfico animado de hipocicloide
En uno de sus libros de programación en VBA en el ambiente del programa Microsoft Excel, su autor, John Walkenbach, proporciona un CD con archivos para las pruebas a sus lectores. En uno de los archivos, fue implementado el diagrama en la que se generaba una cantidad infinita de hipocicloides.
Nota: La wikipedia ofrece la siguiente definición:
Hipocicloide (en base de las palabras griegas ὑπό — abajo, debajo y κύκλος — círculo, circunferencia) es una curva plana formada por un punto situado sobre la circunferencia que rueda por el interior de otra circunferencia sin deslizamiento .
John Walkenbach define este concepto manera en sus libro de la siguiente:
Vamos a implementar la misma aplicación en MQL, y añadiremos la interfaz gráfica para manejar los parámetros. Vamos a ver en detalle cómo están organizados todo eso.
Para generar una nueva curva hipocicloide, se usan tres parámetros según los cuales se inicializan las secuencias numéricas con paso indicado. Luego, a base de estos valores en estas secuencias, se realizan los cálculos para obtener las coordenadas de los puntos en el gráfico. Después de eso, los resultados obtenidos se normalizan.
En la clase personalizada, declaramos varios arrays para calcular las secuencias y los campos para el cálculo de la desviación media y estándar:
//+------------------------------------------------------------------+ //| Program.mqh | //| Copyright 2017, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include <Math\Stat\Stat.mqh> #include <EasyAndFastGUI\WndEvents.mqh> #include <EasyAndFastGUI\TimeCounter.mqh> //+------------------------------------------------------------------+ //| Clase para crear la aplicación | //+------------------------------------------------------------------+ class CProgram : public CWndEvents { protected: ... //--- Arrays de los datos para los cálculos double a_inc[]; double b_inc[]; double t_inc[]; double x_source[]; double y_source[]; //--- Arrays de los datos para mostrar en el gráfico double x_norm[]; double y_norm[]; //--- Para el cálculo de la desviación media y estándar 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) { ... }
El cálculo de los valores va a realizarse en el método CProgram::InitArrays(). Aquí, los datos iniciales se calculan en el primer ciclo. Luego, se obtiene la desviación media y estándar, y los datos se normalizan en el segundo ciclo. El tamaño para los arrays se establece a través del método CProgram::ResizeArrays(). El valor para el tamaño de los arrays se coge del control «Campo de edición» (CTextEdit) de la interfaz gráfica de la aplicación.
class CProgram : public CWndEvents { private: //--- Establecemos nuevo tamaño para los arrays void ResizeArrays(void); //--- Inicialización de los arrays auxiliares para los cálculos void InitArrays(void); }; //+------------------------------------------------------------------+ //| Cambia el tamaño de los arrays | //+------------------------------------------------------------------+ void CProgram::ResizeArrays(void) { int array_size =::ArraySize(x_norm); int new_size =(int)m_array_size.GetValue(); //--- Salir si el tamaño no ha cambiado if(array_size==new_size) return; //--- Establecer nuevo tamaño ::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); } //+------------------------------------------------------------------+ //| Inicialización de arrays | //+------------------------------------------------------------------+ void CProgram::InitArrays(void) { //--- Cambiar los tamaños de los arrays ResizeArrays(); //--- Calculamos los valores usando las fórmulas 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); } //--- Calculamos la media x_mean=MathMean(x_source); y_mean=MathMean(y_source); //--- Calculamos la desviación estándar x_sdev=MathStandardDeviation(x_source); y_sdev=MathStandardDeviation(y_source); //--- Corrección para evitar la división por cero x_sdev =(x_sdev==0)? 1 : x_sdev; y_sdev =(y_sdev==0)? 1 : y_sdev; //--- Normalizamos los datos 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; } }
En la clase CGraphic hay métodos que permiten añadir las marcas adicionales para las escalas de los ejes, líneas y el texto en el área de trabajo del gráfico.
En caso de nuestro ejemplo, usaremos el método CProgram::TextAdd() para mostrar las diagramas de los valores de la desviación media y estándar para las secuencias X y Y colocándolas en la esquina superior izquierda. Para obtener las coordenadas del punto extremo (esquina superior izquierda) del diagrama, se usan los métodos CGraphic::ScaleX() y CGraphic::ScaleY(), que sirven para el redimensionamiento de los valores reales del gráfico en las coordenadas de los píxeles. Aquí, como valores reales, se usa el mínimo por el eje X y el máximo por el eje Y.
class CProgram : public CWndEvents { private: //--- Añade el texto en el gráfico void TextAdd(void); }; //+------------------------------------------------------------------+ //| Añade el texto en el gráfico | //+------------------------------------------------------------------+ void CProgram::TextAdd(void) { //--- Obtenemos el puntero del gráfico 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); //--- Calculamos las coordenadas y mostramos el texto en el gráfico 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); } }
Una vez establecidos todos los datos necesarios en el gráfico, hay que redibujarlo para mostrar los últimos cambios. Para eso se utiliza el método CProgram::UpdateSeries(). Aquí, primero, comprobamos si hay series en el gráfico. Si es así, establecemos los datos calculados últimamente. Aparte de eso, establecemos las propiedades para la curva usando los controles de la interfaz gráfica de la aplicación. Aquí es (1) el suavizado de la curva, (2) tipo de los puntos y (3) tipo de la curva. Cabe mencionar que la colocación del texto en el gráfico debe realizarse después de que hayan sido establecidas y dibujadas todas las demás propiedades y datos. Al final del todo, hay que actualizar el gráfico para ver el resultado.
class CProgram : public CWndEvents { private: //--- Coloca y actualiza las series en el gráfico void UpdateSeries(void); }; //+------------------------------------------------------------------+ //| Coloca y actualiza las series en el gráfico | //+------------------------------------------------------------------+ void CProgram::UpdateSeries(void) { //--- Obtenemos el puntero del gráfico CGraphic *graph=m_graph1.GetGraphicPointer(); //--- Actualizamos todas las series del gráfico con nuevos datos int total=graph.CurvesTotal(); if(total>0) { //--- Obtenemos el puntero de la curva CCurve *curve=graph.CurveGetByIndex(0); //--- Establecer el array de los datos curve.Update(x_norm,y_norm); //--- Obtenemos los valores de las propiedades de la curva 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(); //--- Establecer las propiedades curve.LinesSmooth(m_line_smooth.IsPressed()); curve.PointsType(point_type); curve.Type(curve_type); } //--- Aplicar graph.Redraw(true); //--- Mostrar el texto TextAdd(); //--- Actualizar el gráfico graph.Update(); }
Para el cálculo y aplicación de los resultados obtenidos con una llamada, se usa el método CProgram::RecalculatingSeries():
class CProgram : public CWndEvents { private: //--- Recálculo de las series en el gráfico void RecalculatingSeries(void); }; //+------------------------------------------------------------------+ //| Recálculo de las series en el gráfico | //+------------------------------------------------------------------+ void CProgram::RecalculatingSeries(void) { //--- Calculamos los valores e inicializamos los arrays InitArrays(); //--- Actualizamos las series UpdateSeries(); }
El diagrama construido a base de estas fórmulas tendrá un aspecto más interesante si estará animado. Para hacer moverse las secuencias calculadas, hay que modificar el valor inicial de estas secuencias. Se puede conseguir eso, introduciendo los valores en los campos de edición o iniciando el proceso en modo automático. En modo automático, el incremento o reducción de los valores en este campo, se realiza en el método CProgram::AnimateGraphSeries(). Este método se invoca dentro del método CProgram::UpdateGraphByTimer(), cuya llamada, a su vez, se realiza en el temporizador de la aplicación.
class CProgram : public CWndEvents { private: //--- Actualización del gráfico por el temporizador void UpdateGraphByTimer(void); //--- Animación de las series del gráfico void AnimateGraphSeries(void); }; //+------------------------------------------------------------------+ //| Temporizador | //+------------------------------------------------------------------+ void CProgram::OnTimerEvent(void) { CWndEvents::OnTimerEvent(); //--- Actualización del gráfico por el temporizador if(m_counter1.CheckTimeCounter()) { UpdateGraphByTimer(); } ... } //+------------------------------------------------------------------+ //| Actualización del gráfico por el temporizador | //+------------------------------------------------------------------+ void CProgram::UpdateGraphByTimer(void) { //--- Salir si (1) el formulario está minimizado o (2) la animación está desactivada if(m_window.IsMinimized() || !m_animate.IsPressed()) return; //--- Animación de las series del gráfico AnimateGraphSeries(); //--- Actualizar los arrays y las series en el gráfico RecalculatingSeries(); } //+------------------------------------------------------------------+ //| Animación de las series del gráfico | //+------------------------------------------------------------------+ void CProgram::AnimateGraphSeries(void) { //--- Para indicar la dirección del cambio del tamaño de los arrays static bool counter_direction=false; //--- Si llegamos al mínimo, cambiamos de dirección if((double)m_animate.GetValue()<=(double)m_animate.MinValue()) counter_direction=false; //--- Si llegamos al máximo, cambiamos de dirección if((double)m_animate.GetValue()>=(double)m_animate.MaxValue()) counter_direction=true; //--- Cambiamos el tamaño del array según la dirección string value=""; if(!counter_direction) value=string((double)m_animate.GetValue()+m_animate.StepValue()); else value=string((double)m_animate.GetValue()-m_animate.StepValue()); //--- Establecer el valor nuevo y actualizar el campo de edición m_animate.SetValue(value,false); m_animate.GetTextBoxPointer().Update(true); }
Al final, obtenemos el siguiente resultado:
Fig. 7. Demostración del hipocicloide animado.
Puede descargar esta aplicación de prueba al final del artículo para estudiarla más detalladamente.
Nueva versión de la aplicación de prueba desde las actualizaciones anteriores
La aplicación de prueba que había sido presentada en el artículo Interfaces gráficas IX: Controles «Indicador de progreso» y «Gráfico lineal» (Capítulo 2) fue actualizada de acuerdo con los cambios realizados en esta actualización.
A continuación, se muestra la nueva versión de esta aplicación MQL con la interfaz gráfica actualizada:
Fig. 8. Nueva versión de la aplicación de prueba desde las actualizaciones anteriores.
Puede descargar esta aplicación de prueba al final del artículo para estudiarla más detalladamente.
Conclusión
En este artículo, la parte de la librería estándar para la construcción de los gráficos científicos ha sido integrada en nuestra librería para la creación de las interfaces gráficas. Puede descargar todos los ejemplos demostrados al final del artículo para estudiarlos más detalladamente.
En esta fase del desarrollo de la librería, su esquema general tiene el siguiente aspecto:
Fig. 9. Estructura de la librería en la fase actual del desarrollo.
Este código de la librería se ofrece de forma gratuita. Usted puede utilizarlo en sus proyectos, inclusive de negocio, escribir los artículos y realizar los trabajos de encargo.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/3527
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso