How to fix flickering bitmap when updating its size accordingly? - page 3

 
Nikolai Semko #:

I couldn't run your code because of an error (array out of range in 'Ex.mq5' (143,31)). When I bypassed this error, nothing is displayed.

That's totally weird.

Somehow index 0 in the array doesn't contain the name of the object when performing ChartObjectName().

The first index 0 should have a name "144_97"

Clearly I added 2 objects into the array, somehow only the 2nd object that has name.

Files:
pie.mq5  81 kb
 
Nikolai Semko #:

I couldn't run your code because of an error (array out of range in 'Ex.mq5' (143,31)). When I bypassed this error, nothing is displayed.

Yes, are the _X() and _Y() functions correct

         int x=(int)_X(startIndex);
         int y=(int)_Y(startIndex);

         int x1=(int)_X(endIndex);
         int y1=(int)_Y(endIndex);
 
Nikolai Semko #:

Alain, I was not lazy and checked.
The check showed that the reason is ChartTimePriceToXY.
Your code is running with flickering due to frequent use of ChartTimePriceToXY. My code doesn't flicker.


No !

As your video shows perfectly there is NO flickering with the red rectangle which is the one I fixed.

I never said that ChartTimePriceToX() is not a costly operation, I said it was not the reason for the flickering in this case and you perfectly proved it.

P.S: Sorry for posting code that doesn't compile, it was late.

 
Alain Verleyen #:

No !

As your video shows perfectly there is NO flickering with the red rectangle which is the one I fixed.

I never said that ChartTimePriceToX() is not a costly operation, I said it was not the reason for the flickering in this case and you perfectly proved it.

P.S: Sorry for posting code that doesn't compile, it was late.

What does the red rectangle have to do with it when your blue one is flickering?

 
Agustinus Biotamalo Lumbantoruan #:

Yes, are the _X() and _Y() functions correct

No!


And why did you insert my library into your code?

What didn't you like about one line of code:

#include <Canvas\iCanvas_CB.mqh> 

 instead of 900 lines of code?


#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/abiotamalo"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1


#include <Canvas\iCanvas_CB.mqh> //https://www.mql5.com/ru/code/22164

CCanvas *canvasObjects[];
int Counter=0;
void OnDeinit(const int r){
   for(int i=0;i<ArraySize(canvasObjects);i++) delete canvasObjects[i];
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create canvas
   int x=0;
   int y=0;
   ChartTimePriceToXY(0,0,iTime(Symbol(),PERIOD_CURRENT,144),iHigh(Symbol(),PERIOD_CURRENT,144),x,y);
   int x1=0;
   int y1=0;
   ChartTimePriceToXY(0,0,iTime(Symbol(),PERIOD_CURRENT,97),iLow(Symbol(),PERIOD_CURRENT,97),x1,y1);
   double priceWidth=x1-x;
   double priceHeight=y1-y;
   bool objCreated=false;
   /*
      First canvas object
   */
   if(true)
     {
      int size = ArraySize(canvasObjects);
      ArrayResize(canvasObjects,size+1);
      canvasObjects[size] = new CCanvas;
      string name="144_97";
      datetime startTime=iTime(Symbol(),PERIOD_CURRENT,50);
      double startignPoint=iHigh(Symbol(),PERIOD_CURRENT,50);        
      objCreated=canvasObjects[size].CreateBitmap(name,startTime,startignPoint,x1-x,y1-y,COLOR_FORMAT_ARGB_NORMALIZE);
      canvasObjects[size].Erase(ColorToARGB(clrRed, 0));      
      canvasObjects[size].Update(); 
      //Print(canvas.ChartObjectName());   
     }
   ChartTimePriceToXY(0,0,iTime(Symbol(),PERIOD_CURRENT,50),iHigh(Symbol(),PERIOD_CURRENT,50),x,y);
   x1=0;
   y1=0;
   ChartTimePriceToXY(0,0,iTime(Symbol(),PERIOD_CURRENT,8),iLow(Symbol(),PERIOD_CURRENT,8),x1,y1);
   priceWidth=x1-x;
   priceHeight=y1-y;
   objCreated=false;
   /*
      Second Canvas Object
   */
   if(true)
     {
      int size = ArraySize(canvasObjects);
      ArrayResize(canvasObjects,size+1);
      canvasObjects[size] = new CCanvas;
      string name="50_8";
      datetime startTime=iTime(Symbol(),PERIOD_CURRENT,50);
      double startignPoint=iHigh(Symbol(),PERIOD_CURRENT,50);        
      objCreated=canvasObjects[size].CreateBitmap(name,startTime,startignPoint,x1-x,y1-y,COLOR_FORMAT_ARGB_NORMALIZE);
      canvasObjects[size].Erase(ColorToARGB(clrRed, 0));      
      canvasObjects[size].Update();
      
     }    
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   return rates_total;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id==CHARTEVENT_CHART_CHANGE)
     {
      for(int i=0;i<ArraySize(canvasObjects);i++){
         string name=canvasObjects[i].ChartObjectName();
         string split[];
         StringSplit(name,StringGetCharacter("_",0),split);
         if(name==NULL){
            return;
         }
         int startIndex=split[0];
         int endIndex=split[1];
         int x=(int)_X((double)startIndex);
         int y=(int)_Y(iHigh(_Symbol,0,startIndex));
         datetime startTime=iTime(Symbol(),PERIOD_CURRENT,startIndex);
         double startignPoint=iHigh(Symbol(),PERIOD_CURRENT,startIndex);         
         //if(!ChartTimePriceToXY(0,0,iTime(Symbol(),PERIOD_CURRENT,startIndex),iHigh(Symbol(),PERIOD_CURRENT,startIndex),x,y)){
         //   Print(GetLastError());
         //}
         int x1=(int)_X((double)endIndex);
         int y1=(int)_Y(iLow(_Symbol,0,endIndex));
         //if(!ChartTimePriceToXY(0,0,iTime(Symbol(),PERIOD_CURRENT,endIndex),iLow(Symbol(),PERIOD_CURRENT,endIndex),x1,y1)){
         //   Print(GetLastError());
         //}
         double priceWidth=x1-x;
         double priceHeight=y1-y;  
         double fillRectangleSize=priceHeight/3;
         bool objCreated=canvasObjects[i].CreateBitmap(name,startTime,startignPoint,x1-x,y1-y,COLOR_FORMAT_ARGB_NORMALIZE);
         if(i==0)
            canvasObjects[i].FillRectangle(0,0,priceWidth,fillRectangleSize,ColorToARGB(clrRed, 50));
         if(i==1)
            canvasObjects[i].FillRectangle(0,0,priceWidth*0.33,fillRectangleSize,ColorToARGB(clrRed, 50));
         if(i==0)//Just width variation
            canvasObjects[i].FillRectangle(0,fillRectangleSize,priceWidth*0.5,fillRectangleSize*2,ColorToARGB(clrGreen, 50));
         else
            canvasObjects[i].FillRectangle(0,fillRectangleSize,priceWidth*0.2,fillRectangleSize*2,ColorToARGB(clrGreen, 50));
         canvasObjects[i].FillRectangle(0,fillRectangleSize*2,priceWidth,fillRectangleSize*3,ColorToARGB(clrBlue, 50));
         //c.Resize(priceWidth*0.1,fillRectangleSize*0.1);
         canvasObjects[i].Update();     
      }
      //ArrayFree(canvasObjects);      
     }
  }  
  


But I must say that your logic and code are very far from perfect. I would never do that. Study, study and study again. I advise you to forget about operations with strings, if this is not done directly to generate a string for output (for Print or Comment)

 
Nikolai Semko #:

What does the red rectangle have to do with it when your blue one is flickering?

You still don't understand !

The flickering is NOT due to ChartTimePriceToXY() but to bad coding, I fixed the bad coding for the red rectangle and it doesn't flicker.

Proof by code. Run the attached code and see...no flickering for both rectangles, but it's still using ChartTimePriceToXY.

Files:
455324.mq5  5 kb
 
Alain Verleyen #:

You still don't understand !

The flickering is NOT due to ChartTimePriceToXY() but to bad coding, I fixed the bad coding for the red rectangle and it doesn't flicker.

Your code doesn't flicker at all because you coded it properly, not because you don't use ChartTimePriceToXY.

Proof by code. Run the attached code and see...no flickering for both rectangles, but it's still using ChartTimePriceToXY.

It doesn't matter that there are errors. Anyway, when you fix all the errors, you will run into incredible lags in your code due to the use of ..XY..  ChartGet.. functions.
I showed you that in your code the blue rectangle flickers, but in mine it doesn't. These are only two rectangles, and if there are 100 of them, the system will lag terribly.

 
Nikolai Semko #:

It doesn't matter that there are errors. Anyway, when you fix all the errors, you will run into incredible lags in your code due to the use of ..XY..  ChartGet.. functions.
I showed you that in your code the blue rectangle flickers, but in mine it doesn't. These are only two rectangles, and if there are 100 of them, the system will lag terribly.

Of course it matters. Anyway that's enough, if you want to be right, ok you are right.

I am more interested by this flickering, do you see it (it's a GIF, click on it) ? Do you know how to fix it ? 


 
Nikolai Semko #:

The reason for the flickering in your example is the use of the ChartTimePriceToXY function.

This is a very slow function (in MQL5). Why it's slow is a very long story. I consider this to be a semantic MQ bug, but I'm tired of fighting with MQ on this issue.

You can use my library iCanvas_CB.mqh, which does not use this function to convert coordinates (time, price) to pixel coordinates. In this library you can see how you can do without these (..XY.. ChartGet.. ChartSet..) very slow functions in order to implement these functions yourself and not use my library.

Alternatively, you can use one canvas stretched over the entire chart window and form all the objects in it (I attach an example TestCanvas2Rect.mq5), but in this case the redrawing will lag behind the chart when scrolling, since the canvas is not tied to time and price.

There is an issue with your code. It's not always precise and reliable ! The top left corner is supposed to be at the high of candle 50 right ? But it is not, there is a small shift almost always present :

And sometimes a big shift :


 
Alain Verleyen #:

There is an issue with your code. It's not always precise and reliable ! The top left corner is supposed to be at the high of candle 50 right ? But it is not, there is a small shift almost always present :

And sometimes a big shift :


And also issue on the X axis :

Same rectangle, I just moved the chart horizontally.

Reason: