Tabview with buttons on left side are leaving artifacts from when switching to another tab

I have a tabview with 2 buttons on the left side. Sliding is turned off and the animation time is 0.
On the first tab I have labels and 2 more button the right side they are red so that you can see the artifacts. When I select the second tab I can see the 2 red buttons under the tabview buttons.

I have attached pictures to see.

It looks like the animation, which is off, is moving the page to the left but only the width of the tabview tab area and not the tabview button area too.


This is the ON tab on the left side. Look at the area between the ON and OFF buttons. Nice and clean. Also notice the red UP/DOWN buttons on the right side.

This is the OFF tab after I have changed from ON tab to OFF tab. You can see the red between the ON and OFF buttons. this is the red buttons from the ON tab that were on the right side of the screen.

Is this a tabview in the tab of another tabview?
Can this work? It looks like the red button gets stuck under the second tabview buttons.

Do you have the code to try this in the Simulator?

where is the simulator? is it on a webpage to use?

The simulator is linked very close to the top of the README: https://github.com/littlevgl/lvgl#website---live-demo--simulator--forum--docs-blog

Here is the code to reproduce. Fix please

tabviewOnOff = lv_tabview_create(lv_scr_act(), NULL);

// place the buttons on the left side
lv_tabview_set_btns_pos(tabviewOnOff, LV_TABVIEW_BTNS_POS_LEFT);

// Add 2 tabs (the tabs are page (lv_page) and can be scrolled
tabThermostatOn = lv_tabview_add_tab(tabviewOnOff, “On”);
tabThermostatOff = lv_tabview_add_tab(tabviewOnOff, “Off”);

// create the button
lv_obj_t * btnUp = lv_btn_create(tabThermostatOn, NULL);
lv_obj_set_size(btnUp, 370, 200);

// the thermostat tab to ON or OFF
lv_tabview_set_tab_act(tabviewOnOff, 1, LV_ANIM_OFF);

Did you test this in the simulator? Is the issue present there?

No I have not tested in simulator. I’m running on an Arduino. I have never setup the simulator. Its only 7 lines of code. Can you cut an paste in a simulator?

The simulator runs LittlevGL, so as long as you stick to touchscreen input, you should be able to make your code run there.

I don’t have the simulator.

I tested your code. I do not see any graphical glitches. This usually means that it’s an issue with your display driver, rather than a LittlevGL issue.

Thank you for testing.

I’m using lv_arduino https://github.com/littlevgl/lv_arduino.
Should I open a bug in that branch. I have not written a driver for this.

One thing I have noticed from looking at the tabview.c code is that for tabviews the memory for the buffer is appended to the previous tab and so on.

It appears that for the tabs the memory is like this"

| button | tab 1 | tab 2 | tab 3 | ….
There is only 1 copy for the buttons. and the tabs are only big enough for the content of the tab.

| button | tab 1 | tab 2 | tab 3 |
| button | tab 1 | this memory is accessed to write tab1
| display size | this is the size of the display. when witting tab 1 everything is Ok.
| tab2 | But when displaying tab 2 the display is actually bigger than the content and it is displaying the last button width of tab1 then the tab2 content.

thanks let me know what you think.

I was able to cludge a fix by setting the button on the first tab content area to hidden before showing the second tab.

Not sure how this would be a driver issue. When the driver knows nothing about a button or how to draw it.

Thanks for your help.
Good luck.

The driver deals with writing buffer areas to the screen. When weird graphics like this get drawn on one platform, but not another one, it usually means that there’s some issue with that specific platform. Maybe there is some sort of memory corruption?

One thing I note is that you only seem to have provided the child tabview code (“On/Off”), and not the parent tabview code (“Thermostat (ON)”/“Message”). That will probably affect the results I get. Can you send a complete code sample that lets me reproduce exactly what you are seeing on your display?

I sent only those seven lines of code because the issue happens with only those 7 lines of code. I removed all the other code and got it down to only those lines. It does not need to be tabview inside tab.

Maybe you can ask the person that wrote the tabview code and they will understand the tab buffers and manipulation they need to do for buttons on the left or right.

Thanks

Here is the code I still have it.

#include <lvgl.h>
#include <Ticker.h>
#include <TFT_eSPI.h>

#define LVGL_TICK_PERIOD 20
// GLOBAL LV objects
lv_obj_t * tabview;
lv_obj_t * tabThermostat;
lv_obj_t * tabMessage;

lv_obj_t * tabviewOnOff;
lv_obj_t * tabThermostatOn;
lv_obj_t * tabThermostatOff;
lv_obj_t * currentTemperatureOffBox;
lv_obj_t * targetTemperatureBox;
lv_obj_t * currentHumidityOnBox;
lv_obj_t * currentHumidityOffBox;
lv_obj_t * currentTemperatureOnBox;
lv_obj_t * messageLabel; // place to write the messages too.

Ticker tick; /* timer for interrupt handler /
TFT_eSPI tft = TFT_eSPI(); /
TFT instance */
static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];

#if USE_LV_LOG != 0
/* Serial debugging */
void my_print(lv_log_level_t level, const char * file, uint32_t line, const char * dsc)
{

Serial.printf("%s@%d->%s\r\n", file, line, dsc);
delay(100);
}
#endif

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint16_t c;

tft.startWrite(); /* Start new TFT transaction /
tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /
set the working window /
for (int y = area->y1; y <= area->y2; y++) {
for (int x = area->x1; x <= area->x2; x++) {
c = color_p->full;
tft.writeColor(c, 1);
color_p++;
}
}
tft.endWrite(); /
terminate TFT transaction /
lv_disp_flush_ready(disp); /
tell lvgl that flushing is done */
}

/* Interrupt driven periodic handler */
static void lv_tick_handler(void)
{

lv_tick_inc(LVGL_TICK_PERIOD);
}

/* Reading input device (simulated encoder here) /
bool read_encoder(lv_indev_drv_t * indev, lv_indev_data_t * data)
{
static int32_t last_diff = 0;
int32_t diff = 0; /
Dummy - no movement /
int btn_state = LV_INDEV_STATE_REL; /
Dummy - no press */

data->enc_diff = diff - last_diff;;
data->state = btn_state;

last_diff = diff;

return false;
}

bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
{
uint16_t touchX, touchY;
bool touched = tft.getTouch(&touchX, &touchY, 600);

if(!touched) {
  return false;
}

if(touchX > 480 || touchY > 320) {
  Serial.println("X or y outside of expected parameters..");
  Serial.print("y:");
  Serial.print(touchX);
  Serial.print(" x:");
  Serial.print(touchY);
} else {
  data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; 

  /*Save the state and save the pressed coordinate*/
  //if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
 
  /*Set the coordinates (if released use the last pressed coordinates)*/
  data->point.x = touchX;
  data->point.y = touchY;

  Serial.print("Data x");
  Serial.println(touchX);
  Serial.print("Data y");
  Serial.println(touchY);
}
return false; /*Return `false` because we are not buffering and no more data to read*/

}

void setup() {

Serial.begin(115200); /* prepare for possible serial debug */

lv_init();

#if USE_LV_LOG != 0
lv_log_register_print(my_print); /* register print function for debugging */
#endif

tft.begin(); /* TFT init /
tft.setRotation(1); /
Landscape orientation */

lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

/Initialize the display/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = 480;
disp_drv.ver_res = 320;
disp_drv.flush_cb = my_disp_flush;
disp_drv.buffer = &disp_buf;
lv_disp_drv_register(&disp_drv);

/Initialize the touch pad/
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv); /Descriptor of a input device driver/
indev_drv.type = LV_INDEV_TYPE_POINTER; /Touch pad is a pointer-like device/
indev_drv.read_cb = my_touchpad_read; /Set your driver function/
lv_indev_drv_register(&indev_drv); /Finally register the driver/

// Initialize the graphics library’s tick
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);

tabviewOnOff = lv_tabview_create(lv_scr_act(), NULL);

// place the buttons on the left side
lv_tabview_set_btns_pos(tabviewOnOff, LV_TABVIEW_BTNS_POS_LEFT);

// Add 2 tabs (the tabs are page (lv_page) and can be scrolled
tabThermostatOn = lv_tabview_add_tab(tabviewOnOff, “On”);
tabThermostatOff = lv_tabview_add_tab(tabviewOnOff, “Off”);

// create the button
lv_obj_t * btnUp = lv_btn_create(tabThermostatOn, NULL);
lv_obj_set_size(btnUp, 370, 200);

// the thermostat tab to ON or OFF
lv_tabview_set_tab_act(tabviewOnOff, 1, LV_ANIM_OFF);

}

void loop() {

lv_task_handler(); /* let the GUI do its work */
delay(5);
}

I think there is a misunderstanding here.

If you can reproduce the issue, and I can’t, it usually means that the problem is not within LittlevGL itself. It’s very difficult to fix an issue without a way to reliably reproduce it on another platform.

I’ll mention @Pablo2048; they are the maintainer of the lv_arduino repository.

lv_arduino repository is now very old actually. I want to made some update (at least to update to the latest lvgl), but I’m short of time right now. I’ll will try to do my best until end of this week to update the repository. @mikep then can try if the problem persists…

Hi,

I’m seeing the same problem too and it’s occurring on the Simulator.

I’ve also cross compiled onto my BeagleBone Linux target and it seems to be doing the same thing.

One interesting aspect on the BeagleBone (which is using the frame buffer device) is there seems to be a very noticeable redraw time. (I’ve a table on one of my tabs so maybe that’s possibly the cause for that).

Normally the redraw times are pretty swift. I’ll investigate further - just really wanted to confirm that I’m seeing the same behaviour.

Please send a code snippet that reproduces it in the simulator. If you can make it happen there then it very well may be a bug in LittlevGL.

Unfortunately it’s all a bit of a big collection of code rather than a snippet. As soon as I can I’ll try (in fact in doing so it highlight if it’s something I’m adding to the tabview that’s causing the issue. e.g. I have a mixure of tables and canvases on each tab )