Teste CGraphic - perguntas e sugestões - página 12

 

CGrafic::Destroy() - Não funciona!


//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                                     F_Spread.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, prostotrader"
#property link      "https://www.mql5.com"
#property version   "1.000"
#property indicator_separate_window
#property indicator_plots   1
#property indicator_buffers 1
//---
#define  IND_RESIZE 1
#define  RESULT_OR_NAN(x,expression) ((x==0)?(double)"nan":expression)
//--- Functions
double BlueFunction(double x)   { return(RESULT_OR_NAN(x,10*x*sin(1/x)));      }
double RedFunction(double x)    { return(RESULT_OR_NAN(x,sin(100*x)/sqrt(x))); }
double OrangeFunction(double x) { return(RESULT_OR_NAN(x,sin(100*x)/sqrt(-x)));}
//---
#include <Graphics\Graphic.mqh>
CGraphic Chart;
CColorGenerator generator;
bool is_create;
int sub_window;
int cur_height, cur_width;
//double a_array[];
double v_max, v_min, i_step;
int cnt = 0;
uint blue, red, orange;
double a_from, a_to, a_step;
//+------------------------------------------------------------------+
//| inputs                                                           |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Custom indicator Fill data function                              |
//+------------------------------------------------------------------+
void FillData()
{
  Chart.CurveAdd(RedFunction,a_from,a_to,a_step,red,CURVE_LINES,"Red");
  Chart.CurveAdd(OrangeFunction,a_from,a_to,a_step,orange,CURVE_LINES,"Orange");
  Chart.CurveAdd(BlueFunction,a_from,a_to,a_step,blue,CURVE_LINES,"Blue");
  Chart.CurvePlotAll();
  Chart.Update();
}
//+------------------------------------------------------------------+
//| Custom indicator ChartResize function                            |
//+------------------------------------------------------------------+
void ChartResize()
{
  cnt++;
  if(cnt > 2) return;
  if(is_create == true)
  {
    Chart.Destroy();
    
    
    Chart.CurveAdd(RedFunction,a_from,a_to,a_step,red,CURVE_LINES,"Red_exists");
    Chart.CurveAdd(OrangeFunction,a_from,a_to,a_step,orange,CURVE_LINES,"Orange_exists");
    Chart.CurveAdd(BlueFunction,a_from,a_to,a_step,blue,CURVE_LINES,"Blue_exists");
    Chart.CurvePlotAll();
    Chart.Update();
    is_create = false;
  }  
  cur_height =  int(ChartGetInteger(ChartID(),CHART_HEIGHT_IN_PIXELS, sub_window));
  cur_width =  int(ChartGetInteger(ChartID(),CHART_WIDTH_IN_PIXELS, sub_window));
  is_create = Chart.Create(ChartID(), "Spread", sub_window, 0, 0, cur_width, cur_height);
  if(is_create == true)
  {
    Chart.BackgroundColor(clrWhite);
    
    FillData();
  }
}
//+------------------------------------------------------------------+
//| Custom indicator OnInit function                                 |
//+------------------------------------------------------------------+
int OnInit()
{
  IndicatorSetInteger(INDICATOR_DIGITS, 0);
  IndicatorSetString(INDICATOR_SHORTNAME, "F_Spread");
  sub_window = ChartWindowFind(ChartID(),"F_Spread");
  v_max = SymbolInfoDouble(Symbol(), SYMBOL_SESSION_PRICE_LIMIT_MAX);
  v_min = -SymbolInfoDouble(Symbol(), SYMBOL_SESSION_PRICE_LIMIT_MIN);  
  i_step = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_SIZE);
  is_create = false;
//===
  a_from=-1.2;
  a_to=1.2;
  a_step=0.005;
  blue= generator.Next();
  red = generator.Next();
  orange=generator.Next();
//---  
  return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator OnDeinit function                               |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  if(is_create == true)
  {
    Chart.Destroy();
  }
}
//+------------------------------------------------------------------+
//| Custom indicator ChartEvent function                             |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
  if(id == CHARTEVENT_CHART_CHANGE)
  {
    int i_heigth =  int(ChartGetInteger(ChartID(),CHART_HEIGHT_IN_PIXELS, sub_window));
    int i_width =  int(ChartGetInteger(ChartID(),CHART_WIDTH_IN_PIXELS, sub_window));
    if((i_heigth != cur_height) || (i_width != cur_width))
    {
      EventChartCustom(ChartID(), CHARTEVENT_CUSTOM + IND_RESIZE, 1, 1, "resize");
    }
  }
  else
  if((id > CHARTEVENT_CUSTOM) && (sparam == "resize"))
  {
    PlaySound("");
    ChartResize();
  }   
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
{
  
  return(rates_total);
}
//+------------------------------------------------------------------+
 
prostotrader:

CGrafic::Destroy() - Não funciona!

Como você o detectou? Quais são os sintomas?

 
Denis Kirichenko:

Como você o identificou? Quais são os sintomas?

Bem, o código é anexado para reprodução :)

E na foto você pode ver que depois de Destroy() são adicionados os gráficos

com prefixo

_exists
 
prostotrader:

Mas o código para reprodução está anexado :)

E na foto você pode ver que depois de Destroy() são adicionados os gráficos

com prefixo

Bem, minha pergunta era sobreCGrafic::Destroy(). Funciona - eu verifiquei com o depurador. Talvez algo esteja errado em seu código?

 
Denis Kirichenko:

Bem, a pergunta era especificamente sobreCGrafic::Destroy(). Funciona - eu verifiquei no depurador. Talvez algo esteja errado em seu código?

Entrar no corpo do procedimento Destroy() não significa que ele (o procedimento) funcione corretamente.

Após a destruiçãoreal de um objeto, não foi possível adicionar novos gráficos a ele, e eles são adicionados!

Chart.Destroy();
    
    
    Chart.CurveAdd(RedFunction,a_from,a_to,a_step,red,CURVE_LINES,"Red_exists");
    Chart.CurveAdd(OrangeFunction,a_from,a_to,a_step,orange,CURVE_LINES,"Orange_exists");
    Chart.CurveAdd(BlueFunction,a_from,a_to,a_step,blue,CURVE_LINES,"Blue_exists");
 
prostotrader:

Entrar no corpo do procedimento Destroy() não significa de forma alguma que ele (o procedimento) esteja funcionando corretamente.

Após a destruição real de um objeto, não foi possível acrescentar novos gráficos a ele, e eles sim!

Sobre o acerto, eu concordo. Mas, no entanto... Bem, primeiro,CGraficvazio::Destroy(). Ou seja, o método não nos deve nada. E em segundo lugar, talvez caiba ao programador acrescentar cheques? Você não pode configurar a SB para todas as tarefas...

 
Denis Kirichenko:

Sobre o acerto, eu concordo. Mas, no entanto... Bem, antes de mais nada,CGraficvazio::Destroy(). Ou seja, o método não nos deve nada. E em segundo lugar, talvez caiba ao programador acrescentar cheques? Você não pode configurar a SB para todas as tarefas.

Além disso, eu alterei o método Destroy.

//+------------------------------------------------------------------+
//| Remove graphic from chart                                        |
//+------------------------------------------------------------------+
void CGraphic::Destroy(const long chart,const string name)
  {
    if(ObjectFind(chart,name)>=0)
    {
      SetDefaultParameters();
      m_generator.Reset();
      m_canvas.Destroy();
      bool res = ObjectDelete(chart,name);
      if(res == true)
      {
        Print("Object destroyed!"); 
      }
     }  
   }
2020.11.02 17:16:45.408 F_Spread (Si-12.20,M1)  Object destroyed!

E ainda acrescenta gráficos!

 
Como você faz Resize em CGraphic?
 

Eu traço os gráficos e produzo o texto usando o CGraphic. Se uma instância da EA estiver funcionando, tudo está bem. Se eu executar a mesma EA em gráficos diferentes, tenho a impressão de que a saída está sempre no gráfico que está atualmente na tela. E não na tabela que está especificada no método Criar. Aqui está o código da EA para demonstrar o problema:

#include <Graphics\Graphic.mqh>

CGraphic          Graphic;     // Для вывода графика.
long ChartId;
int OnInit()
  {
   ChartId= ID_Grafika_S_Expertom(); // Узнаем Id графика на котором запущен советник.
   Graphic.Create(ChartId,"CPrecieIdealnayFast ", 0, 10, 30, 500, 500);   
   Print("OnInit ",Symbol()," ChartId=",ChartId);
   EventSetMillisecondTimer(1000);
   return(INIT_SUCCEEDED);
  }

void OnTimer()
  {  
   string Str;
   StringConcatenate(Str,ChartId," ",Symbol()," ",TimeLocal());
   Graphic.FontSet("Arial",20);
   Graphic.TextAdd(20,30, Str, ColorToARGB(clrRed), TA_LEFT|TA_TOP);
   Graphic.Update();
   Graphic.Redraw(true);     
  }
void OnDeinit( const int Reanson )
  {
  Graphic.Destroy();
  }
  
  long ID_Grafika_S_Expertom()
  {
   string MaskaNameExpert=              MQLInfoString(MQL_PROGRAM_NAME);
   int SekyndNaGrafikeSTekygemExpertom= PeriodSeconds();
   string SimvolExpert=                 Symbol();
//--- 1. Настраиваемся на первый график. Если не получилось возращаем советник не найден. 

//--- В цикле.
//--- 2. Получаем Имя эксперта.
//--- --- 2.1 Если не удалось получить имя эксперта смотрим следующий график.
//--- --- --- 2.2 Если не удалось получить слеюущий график выходим из цикла.
//--- 3.A Если на графике есть эксперт И в его названии есть маска: Запоминаем Id и выходим из цикла.
//--- 3.B Если Нет эксперта или НЕ нашли смотрим следующий график.  
//--- --- 3.B.A Если не удалось получить слеюущий график выходим из цикла.   
//--- --- 3.B.B Если  Удалось получить слеюущий график ищем в начало цикла.  

   long ID_Chart= -1;
   string NameExpert="";   
   long   IskomoeIdChart= -1;
   int    LimitChatr= 1000;            // Наверняка ведь не 1000 графиков.
   int    i=0;                         // Cчетчик графиков
   
//--- 1. Настраиваемся на первый график. Если не получилось возращаем советник не найден. 
   ID_Chart= ChartFirst();
   if( ID_Chart < 0 ) return -1;
   
   string Simvol;
   int    KolichestvoSekynd;
   while( i < LimitChatr )
     {
//--- 2. Получаем Имя эксперта.     
      NameExpert=             ChartGetString( ID_Chart, CHART_EXPERT_NAME );
      Simvol=                 ChartSymbol(ID_Chart);
      KolichestvoSekynd=      PeriodSeconds( ChartPeriod(ID_Chart) );
    //  Print("На графике ",ChartSymbol(ID_Chart)," Period=",ChartPeriod(ID_Chart)," Расположен советник (",NameExpert,")");
      
//--- 3.A Если на графике есть эксперт И в его названии есть маска: Запоминаем Id и выходим из цикла.  
      if( NameExpert != ""  && 
         StringFind(NameExpert,MaskaNameExpert) > -1 &&
          Simvol            == SimvolExpert &&
          KolichestvoSekynd == SekyndNaGrafikeSTekygemExpertom )
        {
     //    Print("НАШЛИ На графике ",ChartSymbol(ID_Chart)," Period=",ChartPeriod(ID_Chart)," Расположен советник (",NameExpert,")");
         IskomoeIdChart= ID_Chart; break; 
        }
//--- 3.B Если Нет эксперта или НЕ нашли смотрим следующий график.      
      else
        {
       //  Print("Не удалось найти маску (",MaskaNameExpert," в названии эксперта (",NameExpert,") ",ChartSymbol(ID_Chart)," Period=",ChartPeriod(ID_Chart)," ID=",ID_Chart);
         ID_Chart= ChartNext(ID_Chart);
         i++;
//--- --- 3.B.A Если не удалось получить слеюущий график выходим из цикла.         
         if( ID_Chart < 0 ) {/*Print("Закончились графики.");*/break;}
//--- --- 3.B.B Если  Удалось получить слеюущий график ищем в начало цикла.       
         else               {/* Print("Получили новое Id графика ",ChartSymbol(ID_Chart)," Period=",ChartPeriod(ID_Chart)," ID=",ID_Chart);*/continue;}
        }        
     }   
    return IskomoeIdChart;
  }

Se o Expert Advisor 1 funcionar, tudo está bem

Mas se você abrir a segunda EA em outro gráfico, o primeiro gráfico começa a receber informações da primeira EA e o segundo ao mesmo tempo.

Isso significa que ela começa a cintilar, porque vários Expert Advisors trabalham em um mesmo gráfico. No entanto, na função Init, cada consultor especializado recebe a identificação do gráfico em que foi lançado. Depois recebo uma chamada para Criar.

int OnInit()
  {
   ChartId= ID_Grafika_S_Expertom(); // Узнаем Id графика на котором запущен советник.
   Graphic.Create(ChartId,"CPrecieIdealnayFast ", 0, 10, 30, 500, 500);   
   Print("OnInit ",Symbol()," ChartId=",ChartId);
   EventSetMillisecondTimer(1000);
   return(INIT_SUCCEEDED);
  }

Por favor, ajude-me a entender qual é o problema.

Визуализируй это! Графическая библиотека в MQL5 как аналог plot из R
Визуализируй это! Графическая библиотека в MQL5 как аналог plot из R
  • www.mql5.com
При исследовании и изучении закономерностей важную роль играет визуальное отображение с помощью графиков. В популярных среди научного сообщества языках программирования, таких как R и Python, для визуализации предназначена специальная функция plot. С её помощью можно рисовать линии, точечные распределения и гистограммы для наглядного представления закономерностей. В MQL5 вы можете делать всё то же самое с помощью класса CGraphics.
 
pivomoe:

Eu traço os gráficos e produzo o texto usando o CGraphic. Se uma instância da EA estiver funcionando, tudo está bem. Se eu executar a mesma EA em gráficos diferentes, tenho a impressão de que a saída está sempre no gráfico que está atualmente na tela. E não na tabela que está especificada no método Criar. Aqui está o código da EA para demonstrar o problema:

Se o Expert Advisor 1 funcionar, tudo está bem

Mas se você abrir a segunda EA em outro gráfico, o primeiro gráfico começa a receber informações da primeira EA e o segundo ao mesmo tempo.

Isso significa que ela começa a cintilar, porque vários Expert Advisors trabalham em um mesmo gráfico. No entanto, na função Init, cada consultor especializado recebe a identificação do gráfico em que foi lançado. Depois recebo uma chamada para Criar.

Por favor, ajude-me a entender qual é o problema?

Em nome do objeto, não é necessário adicionar ChartId? Não me lembro se ele é adicionado dentro da função.