How do I clear old text when printing text on ILI9341?

Mike5000

Well-known member
I need to display and update some numbers fast on my ILI9341. I try to set the backgound color with Display.setTextColor(C_LTYELLOW, C_BLACK).
However the text is overwritten but not cleared. It appears smeared out. I dont want to fill by using Display.Fillscreen(C_BLACK) because that slows down the loop and makes flicker as well.
Any fast tricks??
 
What library? What font?

In most cases the setTextColor as you showed should work. However if the numbers are of different length, like from: 100 to 2, then the 2 will only overwrite the first digit (assuming same size characters..)
But assuming that part works. You have a few options to overwrite the remaining space.

Quick and dirty: print a couple spaces after your number: tft.print(new_val, DEC); tft.print(" ");
This assumes you have room to the right...

remember how far out the text went on previous output and fillRect from the new end of text to the previous end of text. The actual calls depend on library.

If ili9341_t3n, you could use frame buffer, update the screen or region and do a updateScreen.

Which font and library also matters, if for example you use the Adafruit library. They did not used to support opaque text output with their fonts. My library I put in support. But with it you may need to
use clip rectangle as their font will extend to what logically would be start of next line of text in that font.
 
remember your numbers that are there and print them again in the background color before printing your new numbers. This will jsut update the pixels in your string.

Display.setTextColor(C_BLACK, C_BLACK);
Display.println(oldnumber);
Display.setTextColor(C_LTYELLOW, C_BLACK);
Display.println(number);
oldnumber = number;
 
remember your numbers that are there and print them again in the background color before printing your new numbers. This will jsut update the pixels in your string.

Display.setTextColor(C_BLACK, C_BLACK);
Display.println(oldnumber);
Display.setTextColor(C_LTYELLOW, C_BLACK);
Display.println(number);
oldnumber = number;

That is another possibility, Although, maybe no faster than doing a simple fillRect of the area of the field. And same issue of maybe flickering.
Note: with the pseudo code. You probably need to set the textCursor before each of those print, or println lines.
 
It will flicker somewhat, but only the number. if you're updating every 30ms it may be a problem, but if there's more like 300ms it shouldn't be bad. Note I use a slightly modified version of this to render an ellipse over a background pattern of noise, and it flickers but only a bit. There are 180 points in the ellipse in this demo and the screen refreshes at 30hz:

https://www.youtube.com/watch?v=sV_SWlSdgNY

I do this by creating an array of the xy coordinates of all 180 points (actually, 180 * 4) in the background, then filling the points with background color before drawing the ellipse again

Code:
// draw elliptical orbit
  void renderOrbit(int xSize, int ySize, double rotation){
   
    int centerX = xDisplay / 2;
    int centerY = yDisplay / 2;
  
    // Calculate the number of points to plot
    double increment = 2 * PI / displayPoints;
    double t = 0;
   
    // Iterate over each point on the ellipse outline
    for (int i = 0; i < displayPoints; i++) {
      // Calculate normalized coordinates (-1 to 1)
      double normalizedX = (xSize / 2) * cos(t);
      double normalizedY = (ySize / 2) * sin(t);
  
      // Apply rotation
      double angleInRadians = rotation * (PI / 180);
      double rotatedX = normalizedX * cos(angleInRadians) - normalizedY * sin(angleInRadians);
      double rotatedY = normalizedX * sin(angleInRadians) + normalizedY * cos(angleInRadians);
  
      // Calculate pixel coordinates
      uint8_t pixelX = centerX + round(rotatedX);
      uint8_t pixelY = centerY + round(rotatedY);
      currentOrbitX[i] = pixelX;
      currentOrbitY[i] = pixelY;
      currentOrbitX[2 * displayPoints + i] = pixelX;
      currentOrbitY[2 * displayPoints + i] = pixelY+1;
      currentOrbitX[3 * displayPoints + i] = pixelX+1;
      currentOrbitY[3 * displayPoints + i] = pixelY;
      currentOrbitX[4 * displayPoints + i] = pixelX+1;
      currentOrbitY[4 * displayPoints + i] = pixelY+1;
  
      // Plot the pixel on the display
      tft.drawPixel(currentOrbitX[i], currentOrbitY[i], ST77XX_RED);
      tft.drawPixel(currentOrbitX[2 * displayPoints + i], currentOrbitY[2 * displayPoints + i], ST77XX_RED);
      tft.drawPixel(currentOrbitX[3 * displayPoints + i], currentOrbitY[3 * displayPoints + i], ST77XX_RED);
      tft.drawPixel(currentOrbitX[4 * displayPoints + i], currentOrbitY[4 * displayPoints + i], ST77XX_RED);
  
      // Update angle
      t += increment;
    }
  }

  // undraw elliptical orbit
  void eraseOrbit(uint16_t* tableData){
   
    // Iterate over each point on the ellipse outline
    for (int i = 0; i < displayPoints; i++) {
  
      // Plot the pixel on the display
      uint16_t color1 = tableData[currentOrbitY[i] * xDisplay + currentOrbitX[i]];  // Get the value from the table
      uint16_t color2 = tableData[currentOrbitY[2 * displayPoints + i] * xDisplay + currentOrbitX[2 * displayPoints + i]];  // Get the value from the table
      uint16_t color3 = tableData[currentOrbitY[3 * displayPoints + i] * xDisplay + currentOrbitX[3 * displayPoints + i]];  // Get the value from the table
      uint16_t color4 = tableData[currentOrbitY[4 * displayPoints + i] * xDisplay + currentOrbitX[4 * displayPoints + i]];  // Get the value from the table
      
      // Set the pixel on the display with the calculated color
      tft.drawPixel(currentOrbitX[i], currentOrbitY[i], color1);
      tft.drawPixel(currentOrbitX[2 * displayPoints + i], currentOrbitY[2 * displayPoints + i], color2);
      tft.drawPixel(currentOrbitX[3 * displayPoints + i], currentOrbitY[3 * displayPoints + i], color3);
      tft.drawPixel(currentOrbitX[4 * displayPoints + i], currentOrbitY[4 * displayPoints + i], color4);
    }
  }
 
What library? What font?
If ili9341_t3n, you could use frame buffer, update the screen or region and do a updateScreen.

I use these libraries (linked to github in the platformio.ini file via the lib_deps =
paulstoffregen/ILI9341_t3@0.0.0-alpha+sha.ff4bba3e15
paulstoffregen/XPT2046_Touchscreen@0.0.0-alpha+sha.26b691b2c8

You mention a framebuffer possibility. This I remember from my old Amiga days. Writing to one part of the framebuffer and only on periodic interval switch from the current framebuffer to the one you were writing to. Is this possible with the ILI9341_t3 library?
 
To 'CLEAR' text on a graphics display, one should write the same text being cleared in the background color or just simply block fill the area. Then apply your new text in place.
 
To 'CLEAR' text on a graphics display, one should write the same text being cleared in the background color or just simply block fill the area. Then apply your new text in place.

Note: You will get some text flickering doing it this way.
I prefer to use the Opaque text color way, at least with our libraries.

Frame buffer code lets say in ILI9341_t3n - you can setup a clipRectangle to restrict where your drawing is going... And if the ciipRectangle is still set when you do updateScreen(), it will only update that area.
There is also an option in place that works some times where you can say only update the region of the screen that updated. Basically when on it computes a bounding rectangle of the different graphic primitives you called and only update the union of those.

However none of the partial frame updates works with the updateScreenAsyn() DMA... I think, I was experimenting with it, but only in the non-continuous updates mode.
 
I also used the trick of overwritting a text with a the same text with background color.

With anti aliased fonts this results in a ghostly halo around the erased characters.

This is because of the semi transparent anti aliasing pixels in the periphery of the characters... they only partially erase the previous pixels... which is logical.
 
Could you overwrite the Text but with BOLD characters. I am under the impression that when you use bold the characters are very slightly bigger, so this might handle the character boundary problem.
 
Back
Top