Тестируем CGraphic - вопросы и предложения - страница 12

 

CGrafic::Destroy() - Не работает!


//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                                     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() - Не работает!

Как Вы определили? Какие симптомы?

 
Denis Kirichenko:

Как Вы определили? Какие симптомы?

Так ведь код для воспроизведения приложен :)

Да и на картинке видно, что после Destroy() добавляются графики 

с префиксом 

_exists
 
prostotrader:

Так ведь код для воспроизведения приложен :)

Да и на картинке видно, что после Destroy() добавляются графики 

с префиксом 

Ну вопрос был в частности про CGrafic::Destroy(). Он работает - в Отладчике проверил... Может что не так в коде у Вас?

 
Denis Kirichenko:

Ну вопрос был в частности про CGrafic::Destroy(). Он работает - в Отладчике проверил... Может что не так в коде у Вас?

Попадание в тело процедуры Destroy() совсем не означает что она (процедура) правильно работает.

После действительного разрушения  объекта мы не могли бы добавить в него новые графики, а они добавляются! 

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:

Попадание в тело процедуры Destroy() совсем не означает что она (процедура) правильно работает.

После действительного разрушения  объекта мы не могли бы добавить в него новые графики, а они добавляются! 

Насчёт попадания согласен. Но тем не менее... Ну, во-первых, void CGrafic::Destroy(). Т.е. метод нам как бы ничего не должен... А во-вторых может это дело программиста добавить проверку? Подо все задачи СБ не заточишь...

 
Denis Kirichenko:

Насчёт попадания согласен. Но тем не менее... Ну, во-первых, void CGrafic::Destroy(). Т.е. метод нам как бы ничего не должен... А во-вторых может это дело программиста добавить проверку? Подо все задачи СБ не заточишь...

Более того, я переделал 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!

И все-равно графики добавляются!

 
Как же сделать Resize в CGraphic ?
 

Строю графики и вывожу текс с помощью  CGraphic. Если запущен один экземпляр советника все отлично. А если запустить один и тоже же советник на разных графиках создается впечатление, что вывод информации всегда происходит на график, который сейчас на экране. А не на график, который указан в методе Create. Вот код советника для демонстрации проблемы:

#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;
  }

Если советник работает 1 все отлично

А вот если открыть второй советник на другом графике, то на первый график начинает приходить информация одновременно и с первого советника и со второго.

т.е начинает мелькание. т.к на один и тоже график пишту сразу несколько советников. Хотя в функции Init каждый советник получает Id графика на котором он запущен. Потом сразу же вызывается Create.

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);
  }

Помогите понять в чем проблема ?

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

Строю графики и вывожу текс с помощью  CGraphic. Если запущен один экземпляр советника все отлично. А если запустить один и тоже же советник на разных графиках создается впечатление, что вывод информации всегда происходит на график, который сейчас на экране. А не на график, который указан в методе Create. Вот код советника для демонстрации проблемы:

Если советник работает 1 все отлично

А вот если открыть второй советник на другом графике, то на первый график начинает приходить информация одновременно и с первого советника и со второго.

т.е начинает мелькание. т.к на один и тоже график пишту сразу несколько советников. Хотя в функции Init каждый советник получает Id графика на котором он запущен. Потом сразу же вызывается Create.

Помогите понять в чем проблема ?

В имя объекта не нужно добавить ChartId? Я не помню, добавляется ли оно внутри функции.

Причина обращения: