More than one roller widgets in one tabview,their events can influence each other

Important: posts that do not use this template will be ignored or closed.

Before posting

  • Get familiar with Markdown to format and structure your post
  • Be sure to update lvgl from the latest version from the master branch.
  • Be sure you have checked the relevant part of the documentation. We will not respond in detail to posts where you haven’t read the relevant documentation.
  • If applicable use the Simulator to eliminate hardware related issues.

Delete this section if you read and applied the mentioned points.

Description

What MCU/Processor/Board and compiler are you using?

visual studio 2017

What LVGL version are you using?

v7

What do you want to achieve?

how to overcome roller events influence each other

What have you tried so far?

Change the roller style and some other property

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

/*You code here*/
/******************************roller_test.h*******************/
#pragma once
#ifndef ROLLER_TEST_H
#define ROLLER_TEST_H

#include "lvgl/lvgl.h"

#ifdef  __cplusplus
extern "C" {
#endif //  __cplusplus

void SetupScreen(lv_obj_t *obj);

#ifdef __cplusplus
}
#endif // __cplusplus

#endif // ! UI_MORE_TIMER_H
/******************************roller_test.c*******************/
#include "lvgl/lvgl.h"
#include "roller_test.h"

static lv_obj_t *tabview = NULL;
static lv_obj_t *tab1 = NULL;
static lv_style_t rollerBgStyle, rollerSelStyle;
static char hourStrBuf[3] = { 0 };
static char minuteStrBuf[3] = { 0 };
static char secondStrBuf[3] = { 0 };
static lv_obj_t *hourRoller = NULL;
static lv_obj_t *minuteRoller = NULL;
static lv_obj_t *secondRoller = NULL;
static uint32_t timerTmp = 60;
static const char *HourBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23";
static const char *MinuteBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";
static const char *SecondBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";

static void InitTableview(lv_obj_t *obj)
{
	static lv_style_t bgStyle;
	static lv_style_t scrlStyle;
	tabview = lv_tabview_create(obj, NULL);
	lv_obj_set_size(tabview, LV_HOR_RES, LV_VER_RES);
	lv_obj_add_style(tabview, LV_OBJ_PART_MAIN, &bgStyle);
	lv_tabview_set_btns_pos(tabview, LV_TABVIEW_TAB_POS_NONE);
	lv_obj_align(tabview, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);

	tab1 = lv_tabview_add_tab(tabview, "Tab1");
	lv_page_set_scrlbar_mode(tab1, LV_SCRLBAR_MODE_OFF);
	lv_obj_add_style(tab1, LV_PAGE_PART_SCROLLABLE, &scrlStyle);
	lv_tabview_set_tab_act(tabview, 1, LV_ANIM_OFF);
}

static void RollerSetting(lv_obj_t *roller, const char *opt, lv_coord_t xpos, uint16_t index, lv_event_cb_t event)
{
	roller = lv_roller_create(tab1, NULL);
	lv_roller_set_options(roller, opt, LV_ROLLER_MODE_INIFINITE);
	lv_obj_set_size(roller, 36, 150);
	lv_obj_add_style(roller, LV_ROLLER_PART_BG, &rollerBgStyle);
	lv_obj_add_style(roller, LV_ROLLER_PART_SELECTED, &rollerSelStyle);
	lv_roller_set_auto_fit(roller, false);
	lv_roller_set_visible_row_count(roller, 3);
	lv_roller_set_selected(roller, index, LV_ANIM_OFF);
	if (&event == NULL) {
		lv_obj_set_event_cb(roller, event);
	}
	lv_obj_align(roller, NULL, LV_ALIGN_IN_TOP_LEFT, xpos, 40);
}

static void TimerHourRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
	if (event == LV_EVENT_VALUE_CHANGED) {
		memset(hourStrBuf, 0, sizeof(hourStrBuf));
		lv_roller_get_selected_str(obj, hourStrBuf, sizeof(hourStrBuf));
	}
}

static void TimerMinuteRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
	if (event == LV_EVENT_VALUE_CHANGED) {
		memset(minuteStrBuf, 0, sizeof(minuteStrBuf));
		lv_roller_get_selected_str(obj, minuteStrBuf, sizeof(minuteStrBuf));
	}
}

static void TimerSecondRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
	if (event == LV_EVENT_VALUE_CHANGED) {
		memset(secondStrBuf, 0, sizeof(secondStrBuf));
		lv_roller_get_selected_str(obj, secondStrBuf, sizeof(secondStrBuf));
	}
}

static void SettingTimerUI(void)
{
	uint16_t hourIndex = timerTmp / 3600 + 2;
	if (hourRoller == NULL) {
		RollerSetting(hourRoller, HourBuf, 30, hourIndex, TimerHourRollerEventHandler);
	}

	uint16_t minuteIndex = timerTmp % 3600 / 60 + 5;
	if (minuteRoller == NULL) {
		RollerSetting(minuteRoller, MinuteBuf, 133, minuteIndex, TimerMinuteRollerEventHandler);
	}

	uint16_t secondIndex = timerTmp % 60 + 5;
	if (secondRoller == NULL) {
		RollerSetting(secondRoller, SecondBuf, 234, secondIndex, TimerSecondRollerEventHandler);
	}


}

static void InitRollerStyle(void)
{
	lv_style_reset(&rollerBgStyle);
	lv_style_init(&rollerBgStyle);
	lv_style_set_bg_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_bg_grad_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_bg_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
	lv_style_set_radius(&rollerBgStyle, LV_STATE_DEFAULT, 0);
	lv_style_set_border_width(&rollerBgStyle, LV_STATE_DEFAULT, 0);
	lv_style_set_text_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
	lv_style_set_text_line_space(&rollerBgStyle, LV_STATE_DEFAULT, 32);
	lv_style_set_text_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_GRAY);
	lv_style_reset(&rollerSelStyle);
	lv_style_init(&rollerSelStyle);
	lv_style_set_bg_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_bg_grad_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_text_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x00, 0xd8, 0xff));
}

void SetupScreen(lv_obj_t *obj)
{
	InitTableview(obj);
	InitRollerStyle();
	SettingTimerUI();
}
## Screenshot and/or video

If possible, add screenshots and/or videos about the current state.
I build three roller and each of them has an event,but 
when I rolling one of them with no stop exactly on an option and at this time rolling another,the previous even move.

Hi @zhuxiya,

There are a few things in your code which could be causing memory corruption please address these first:

  1. You do not need to call lv_style_reset() before lv_style_init(), lv_style_reset() should be called when you are finished with a style to free its’ memory.

  2. You need to initialise the styles in your function static void InitTableview(lv_obj_t *obj).

I have made changes to your posted code below:

	static lv_obj_t *tabview = NULL;
	static lv_obj_t *tab1 = NULL;
	static lv_style_t rollerBgStyle, rollerSelStyle;
	static char hourStrBuf[3] = { 0 };
	static char minuteStrBuf[3] = { 0 };
	static char secondStrBuf[3] = { 0 };
	static lv_obj_t *hourRoller = NULL;
	static lv_obj_t *minuteRoller = NULL;
	static lv_obj_t *secondRoller = NULL;
	static uint32_t timerTmp = 60;
	static const char *HourBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23";
	static const char *MinuteBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
	"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";
	static const char *SecondBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
	"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";

	static void InitTableview(lv_obj_t *obj)
	{
		static lv_style_t bgStyle;
		static lv_style_t scrlStyle;
		tabview = lv_tabview_create(obj, NULL);
		lv_obj_set_size(tabview, LV_HOR_RES, LV_VER_RES);
		lv_style_init( &bgStyle ); // Added this line
		lv_obj_add_style(tabview, LV_OBJ_PART_MAIN, &bgStyle);
		lv_tabview_set_btns_pos(tabview, LV_TABVIEW_TAB_POS_NONE);
		lv_obj_align(tabview, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);

		tab1 = lv_tabview_add_tab(tabview, "Tab1");
		lv_page_set_scrlbar_mode(tab1, LV_SCRLBAR_MODE_OFF);
		lv_style_init( &scrlStyle ); // Added this line
		lv_obj_add_style(tab1, LV_PAGE_PART_SCROLLABLE, &scrlStyle);
		lv_tabview_set_tab_act(tabview, 1, LV_ANIM_OFF);
	}

	static void RollerSetting(lv_obj_t *roller, const char *opt, lv_coord_t xpos, uint16_t index, lv_event_cb_t event)
	{
		roller = lv_roller_create(tab1, NULL);
		lv_roller_set_options(roller, opt, LV_ROLLER_MODE_INIFINITE);
		lv_obj_set_size(roller, 36, 150);
		lv_obj_add_style(roller, LV_ROLLER_PART_BG, &rollerBgStyle);
		lv_obj_add_style(roller, LV_ROLLER_PART_SELECTED, &rollerSelStyle);
		lv_roller_set_auto_fit(roller, false);
		lv_roller_set_visible_row_count(roller, 3);
		lv_roller_set_selected(roller, index, LV_ANIM_OFF);
		if (&event == NULL) {
			lv_obj_set_event_cb(roller, event);
		}
		lv_obj_align(roller, NULL, LV_ALIGN_IN_TOP_LEFT, xpos, 40);
	}

	static void TimerHourRollerEventHandler(lv_obj_t *obj, lv_event_t event)
	{
		if (event == LV_EVENT_VALUE_CHANGED) {
			memset(hourStrBuf, 0, sizeof(hourStrBuf));
			lv_roller_get_selected_str(obj, hourStrBuf, sizeof(hourStrBuf));
		}
	}

	static void TimerMinuteRollerEventHandler(lv_obj_t *obj, lv_event_t event)
	{
		if (event == LV_EVENT_VALUE_CHANGED) {
			memset(minuteStrBuf, 0, sizeof(minuteStrBuf));
			lv_roller_get_selected_str(obj, minuteStrBuf, sizeof(minuteStrBuf));
		}
	}

	static void TimerSecondRollerEventHandler(lv_obj_t *obj, lv_event_t event)
	{
		if (event == LV_EVENT_VALUE_CHANGED) {
			memset(secondStrBuf, 0, sizeof(secondStrBuf));
			lv_roller_get_selected_str(obj, secondStrBuf, sizeof(secondStrBuf));
		}
	}

	static void SettingTimerUI(void)
	{
		uint16_t hourIndex = timerTmp / 3600 + 2;
		if (hourRoller == NULL) {
			RollerSetting(hourRoller, HourBuf, 30, hourIndex, TimerHourRollerEventHandler);
		}

		uint16_t minuteIndex = timerTmp % 3600 / 60 + 5;
		if (minuteRoller == NULL) {
			RollerSetting(minuteRoller, MinuteBuf, 133, minuteIndex, TimerMinuteRollerEventHandler);
		}

		uint16_t secondIndex = timerTmp % 60 + 5;
		if (secondRoller == NULL) {
			RollerSetting(secondRoller, SecondBuf, 234, secondIndex, TimerSecondRollerEventHandler);
		}


	}

	static void InitRollerStyle(void)
	{
//		lv_style_reset(&rollerBgStyle);  NOT REQUIRED
		lv_style_init(&rollerBgStyle);
		lv_style_set_bg_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_bg_grad_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_bg_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
		lv_style_set_radius(&rollerBgStyle, LV_STATE_DEFAULT, 0);
		lv_style_set_border_width(&rollerBgStyle, LV_STATE_DEFAULT, 0);
		lv_style_set_text_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
		lv_style_set_text_line_space(&rollerBgStyle, LV_STATE_DEFAULT, 32);
		lv_style_set_text_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_GRAY);
//		lv_style_reset(&rollerSelStyle);   NOT REQUIRED
		lv_style_init(&rollerSelStyle);
		lv_style_set_bg_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_bg_grad_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_text_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x00, 0xd8, 0xff));
	}

	void SetupScreen(lv_obj_t *obj)
	{
		InitRollerStyle();
		InitTableview(obj);
		SettingTimerUI();
	}

I hope this helps,

Kind Regards,

Pete

Thank you for you can give me some suggestions,I did as your method but rollers’s event could also affect each other.

Hi @zhuxiya,

Also I forgot to mention I changed the order of your function calls in your function void SetupScreen(lv_obj_t *obj)

void SetupScreen(lv_obj_t *obj)
	{
		InitRollerStyle();
		InitTableview(obj);
		SettingTimerUI();
	}

Did you try this also?

Kind Regards,

Pete

Thank you for you can give me some suggestions,I did as your method but rollers’s event could also affect each other.

The first question:
When I rolling the first roller and dose’t stop exactly on an option,then I rolling the second
roller but the first roller following rolling.
The second question
I set the roller with LV_ROLLER_MODE_INFINITE,when I short click the first roller’s
upper nearest option,the roller rolling pass many numbers but does’t stop on the
clicked nesrest option.
But when I set the roller with LV_ROLLER_MODE_NORMAL,I short click the first
roller’s upper nearest option,the roller can only rolling pass one number and just stop on
my clicked option.
The third question:
The roller’s index can not match the numbers of option,when the option numbers
increase,the roller’s index also change.
example:the first roller’s 0 option’s index is not 0 and not 1,but 2;the second roller’s 0
option’s index is not 0 and 1 and 2 and 3 and 4 but 5.IMG_5433

Hi @zhuxiya,

I have spotted another issue with your RollerSetting() function I have modified it below, I have changed the event parameter to a void pointer for the call back function and altered the logic on the event parameter to assign the callback function if event is not equal to NULL.

I think your intention was probably something like this?

	static void RollerSetting(lv_obj_t *roller, const char *opt, lv_coord_t xpos, uint16_t index, void *event )
	{
		roller = lv_roller_create(tab1, NULL);
		lv_roller_set_options(roller, opt, LV_ROLLER_MODE_INIFINITE);
		lv_obj_set_size(roller, 36, 150);
		lv_obj_add_style(roller, LV_ROLLER_PART_BG, &rollerBgStyle);
		lv_obj_add_style(roller, LV_ROLLER_PART_SELECTED, &rollerSelStyle);
		lv_roller_set_auto_fit(roller, false);
		lv_roller_set_visible_row_count(roller, 3);
		lv_roller_set_selected(roller, index, LV_ANIM_OFF);
		if (event != NULL) {
			lv_obj_set_event_cb(roller, event);
		}
		lv_obj_align(roller, NULL, LV_ALIGN_IN_TOP_LEFT, xpos, 40);
	}

I have tested this in the simulator and your hour, minute, second string buffers are all being set correctly with this latest change.

Here is a complete copy and paste of the your code with all the modifications as I using in the simulator:

	static lv_obj_t *tabview = NULL;
	static lv_obj_t *tab1 = NULL;
	static lv_style_t rollerBgStyle, rollerSelStyle;
	static char hourStrBuf[3] = { 0 };
	static char minuteStrBuf[3] = { 0 };
	static char secondStrBuf[3] = { 0 };
	static lv_obj_t *hourRoller = NULL;
	static lv_obj_t *minuteRoller = NULL;
	static lv_obj_t *secondRoller = NULL;
	static uint32_t timerTmp = 60;
	static const char *HourBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23";
	static const char *MinuteBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
	"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";
	static const char *SecondBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
	"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";

	static void InitTableview(lv_obj_t *obj)
	{
		static lv_style_t bgStyle;
		static lv_style_t scrlStyle;
		tabview = lv_tabview_create(obj, NULL);
		lv_obj_set_size(tabview, LV_HOR_RES, LV_VER_RES);
		lv_style_init( &bgStyle );
		lv_obj_add_style(tabview, LV_OBJ_PART_MAIN, &bgStyle);
		lv_tabview_set_btns_pos(tabview, LV_TABVIEW_TAB_POS_NONE);
		lv_obj_align(tabview, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);

		tab1 = lv_tabview_add_tab(tabview, "Tab1");
		lv_page_set_scrlbar_mode(tab1, LV_SCRLBAR_MODE_OFF);
		lv_style_init( &scrlStyle );
		lv_obj_add_style(tab1, LV_PAGE_PART_SCROLLABLE, &scrlStyle);
		lv_tabview_set_tab_act(tabview, 1, LV_ANIM_OFF);
	}

	static void RollerSetting(lv_obj_t *roller, const char *opt, lv_coord_t xpos, uint16_t index, void *event)
	{
		roller = lv_roller_create(tab1, NULL);
		lv_roller_set_options(roller, opt, LV_ROLLER_MODE_INIFINITE);
		lv_obj_set_size(roller, 36, 150);
		lv_obj_add_style(roller, LV_ROLLER_PART_BG, &rollerBgStyle);
		lv_obj_add_style(roller, LV_ROLLER_PART_SELECTED, &rollerSelStyle);
		lv_roller_set_auto_fit(roller, false);
		lv_roller_set_visible_row_count(roller, 3);
		lv_roller_set_selected(roller, index, LV_ANIM_OFF);
		if (event != NULL) {
			lv_obj_set_event_cb(roller, event);
		}
		lv_obj_align(roller, NULL, LV_ALIGN_IN_TOP_LEFT, xpos, 40);
	}

	static void TimerHourRollerEventHandler(lv_obj_t *obj, lv_event_t event)
	{
		if (event == LV_EVENT_VALUE_CHANGED) {
			memset(hourStrBuf, 0, sizeof(hourStrBuf));
			lv_roller_get_selected_str(obj, hourStrBuf, sizeof(hourStrBuf));
		}
	}

	static void TimerMinuteRollerEventHandler(lv_obj_t *obj, lv_event_t event)
	{
		if (event == LV_EVENT_VALUE_CHANGED) {
			memset(minuteStrBuf, 0, sizeof(minuteStrBuf));
			lv_roller_get_selected_str(obj, minuteStrBuf, sizeof(minuteStrBuf));
		}
	}

	static void TimerSecondRollerEventHandler(lv_obj_t *obj, lv_event_t event)
	{
		if (event == LV_EVENT_VALUE_CHANGED) {
			memset(secondStrBuf, 0, sizeof(secondStrBuf));
			lv_roller_get_selected_str(obj, secondStrBuf, sizeof(secondStrBuf));
		}
	}

	static void SettingTimerUI(void)
	{
		uint16_t hourIndex = timerTmp / 3600 + 2;
		if (hourRoller == NULL) {
			RollerSetting(hourRoller, HourBuf, 30, hourIndex, TimerHourRollerEventHandler);
		}

		uint16_t minuteIndex = timerTmp % 3600 / 60 + 5;
		if (minuteRoller == NULL) {
			RollerSetting(minuteRoller, MinuteBuf, 133, minuteIndex, TimerMinuteRollerEventHandler);
		}

		uint16_t secondIndex = timerTmp % 60 + 5;
		if (secondRoller == NULL) {
			RollerSetting(secondRoller, SecondBuf, 234, secondIndex, TimerSecondRollerEventHandler);
		}


	}

	static void InitRollerStyle(void)
	{
//		lv_style_reset(&rollerBgStyle);
		lv_style_init(&rollerBgStyle);
		lv_style_set_bg_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_bg_grad_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_bg_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
		lv_style_set_radius(&rollerBgStyle, LV_STATE_DEFAULT, 0);
		lv_style_set_border_width(&rollerBgStyle, LV_STATE_DEFAULT, 0);
		lv_style_set_text_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
		lv_style_set_text_line_space(&rollerBgStyle, LV_STATE_DEFAULT, 32);
		lv_style_set_text_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_GRAY);
//		lv_style_reset(&rollerSelStyle);
		lv_style_init(&rollerSelStyle);
		lv_style_set_bg_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_bg_grad_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_style_set_text_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x00, 0xd8, 0xff));
	}

	void SetupScreen(lv_obj_t *obj)
	{
		InitRollerStyle();
		InitTableview(obj);
		SettingTimerUI();
	}

I am not seeing the scrolling problems you describe with the simulator. What platform are you using for your tests? Also are you using the latest master branch, if not which version?

Kind Regards,

Pete

Thank you very much for You spend time to test my code.I do as your method,change the evrnt type to vod *,but I delete the “event == NULL” judge.I think it dost not wether has the judege.my function as following
/***/
static void RollerSetting(lv_obj_t *roller, const char *opt, lv_coord_t xpos, uint16_t index, void *event)
{
roller = lv_roller_create(tab1, NULL);
lv_roller_set_options(roller, opt, LV_ROLLER_MODE_INIFINITE);
lv_obj_set_size(roller, 36, 150);
lv_obj_add_style(roller, LV_ROLLER_PART_BG, &rollerBgStyle);
lv_obj_add_style(roller, LV_ROLLER_PART_SELECTED, &rollerSelStyle);
lv_roller_set_auto_fit(roller, false);
lv_roller_set_visible_row_count(roller, 3);
lv_roller_set_selected(roller, index, LV_ANIM_OFF);
lv_obj_set_event_cb(roller, event);
lv_obj_align(roller, NULL, LV_ALIGN_IN_TOP_LEFT, xpos, 40);
}
/
/
I the rollers rooling can affect each other,and I can not seleced the latest opthion.
I use the visual studio 2017 and v7 lvglTFT Simulator 2020-07-16 16-01-32

Thank you I tried,it still have zhe problems,I want to show you video,but the plat does not support

Hi @zhuxiya,

I can see your video just fine thank you. I am not sure why you are seeing these problems.

I have now setup the Visual Studio 2017(Version 15.0) simulator project on my system and cloned the repository with git as follows:
E:\TestArea\vs17_git>git clone --recurse-submodules https://github.com/lvgl/lv_sim_visual_studio_sdl.git

I then opened the project solution file in VS2017…
I then modified the standard main.c file to be this:

/**
* @file main
*
*/

/*********************
*      INCLUDES
*********************/
#include <stdlib.h>
#include <Windows.h>
#include <SDL.h>
#include "lvgl/lvgl.h"
#include "lv_drivers/display/monitor.h"
#include "lv_drivers/indev/mouse.h"
#include "lv_drivers/indev/keyboard.h"
#include "lv_examples/lv_examples.h"

/*********************
*      DEFINES
*********************/

/**********************
*      TYPEDEFS
**********************/

/**********************
*  STATIC PROTOTYPES
**********************/
static void hal_init(void);
static int tick_thread(void *data);

/**********************
*  STATIC VARIABLES
**********************/
static lv_indev_t * kb_indev;

/**********************
*      MACROS
**********************/

/**********************
*   GLOBAL FUNCTIONS
**********************/
static lv_obj_t *tabview = NULL;
static lv_obj_t *tab1 = NULL;
static lv_style_t rollerBgStyle, rollerSelStyle;
static char hourStrBuf[3] = { 0 };
static char minuteStrBuf[3] = { 0 };
static char secondStrBuf[3] = { 0 };
static lv_obj_t *hourRoller = NULL;
static lv_obj_t *minuteRoller = NULL;
static lv_obj_t *secondRoller = NULL;
static uint32_t timerTmp = 60;
static const char *HourBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23";
static const char *MinuteBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";
static const char *SecondBuf = "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29"
"\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";

static lv_obj_t *selected_label = NULL;

static void update_label( void ) {

	lv_label_set_text_fmt(selected_label, "%s:%s:%s", hourStrBuf, minuteStrBuf, secondStrBuf);
}

static void InitTableview(lv_obj_t *obj)
{
	static lv_style_t bgStyle;
	static lv_style_t scrlStyle;
	tabview = lv_tabview_create(obj, NULL);
	lv_obj_set_size(tabview, LV_HOR_RES, LV_VER_RES);
	lv_style_init(&bgStyle);
	lv_obj_add_style(tabview, LV_OBJ_PART_MAIN, &bgStyle);
	lv_tabview_set_btns_pos(tabview, LV_TABVIEW_TAB_POS_NONE);
	lv_obj_align(tabview, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);

	tab1 = lv_tabview_add_tab(tabview, "Tab1");
	lv_page_set_scrlbar_mode(tab1, LV_SCRLBAR_MODE_OFF);
	lv_style_init(&scrlStyle);
	lv_obj_add_style(tab1, LV_PAGE_PART_SCROLLABLE, &scrlStyle);
	lv_tabview_set_tab_act(tabview, 1, LV_ANIM_OFF);

	selected_label = lv_label_create(tabview, NULL);
	lv_obj_set_pos(selected_label, 400, 40);

}

static void RollerSetting(lv_obj_t *roller, const char *opt, lv_coord_t xpos, uint16_t index, void *event)
{
	roller = lv_roller_create(tab1, NULL);
	lv_roller_set_options(roller, opt, LV_ROLLER_MODE_INIFINITE);
	lv_obj_set_size(roller, 36, 150);
	lv_obj_add_style(roller, LV_ROLLER_PART_BG, &rollerBgStyle);
	lv_obj_add_style(roller, LV_ROLLER_PART_SELECTED, &rollerSelStyle);
	lv_roller_set_auto_fit(roller, false);
	lv_roller_set_visible_row_count(roller, 3);
	lv_roller_set_selected(roller, index, LV_ANIM_OFF);
	lv_obj_set_event_cb(roller, event);
	lv_obj_align(roller, NULL, LV_ALIGN_IN_TOP_LEFT, xpos, 40);
}

static void TimerHourRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
	if (event == LV_EVENT_VALUE_CHANGED) {
		memset(hourStrBuf, 0, sizeof(hourStrBuf));
		lv_roller_get_selected_str(obj, hourStrBuf, sizeof(hourStrBuf));
		update_label();
	}
}

static void TimerMinuteRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
	if (event == LV_EVENT_VALUE_CHANGED) {
		memset(minuteStrBuf, 0, sizeof(minuteStrBuf));
		lv_roller_get_selected_str(obj, minuteStrBuf, sizeof(minuteStrBuf));
		update_label();
	}
}

static void TimerSecondRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
	if (event == LV_EVENT_VALUE_CHANGED) {
		memset(secondStrBuf, 0, sizeof(secondStrBuf));
		lv_roller_get_selected_str(obj, secondStrBuf, sizeof(secondStrBuf));
		update_label();
	}
}

static void SettingTimerUI(void)
{
	uint16_t hourIndex = timerTmp / 3600 + 2;
	if (hourRoller == NULL) {
		RollerSetting(hourRoller, HourBuf, 30, hourIndex, TimerHourRollerEventHandler);
	}

	uint16_t minuteIndex = timerTmp % 3600 / 60 + 5;
	if (minuteRoller == NULL) {
		RollerSetting(minuteRoller, MinuteBuf, 133, minuteIndex, TimerMinuteRollerEventHandler);
	}

	uint16_t secondIndex = timerTmp % 60 + 5;
	if (secondRoller == NULL) {
		RollerSetting(secondRoller, SecondBuf, 234, secondIndex, TimerSecondRollerEventHandler);
	}


}

static void InitRollerStyle(void)
{
	//		lv_style_reset(&rollerBgStyle);
	lv_style_init(&rollerBgStyle);
	lv_style_set_bg_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_bg_grad_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_bg_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
	lv_style_set_radius(&rollerBgStyle, LV_STATE_DEFAULT, 0);
	lv_style_set_border_width(&rollerBgStyle, LV_STATE_DEFAULT, 0);
	lv_style_set_text_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
	lv_style_set_text_line_space(&rollerBgStyle, LV_STATE_DEFAULT, 32);
	lv_style_set_text_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_GRAY);
	//		lv_style_reset(&rollerSelStyle);
	lv_style_init(&rollerSelStyle);
	lv_style_set_bg_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_bg_grad_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	lv_style_set_text_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x00, 0xd8, 0xff));
}

void SetupScreen(lv_obj_t *obj)
{
	InitRollerStyle();
	InitTableview(obj);
	SettingTimerUI();
}
int main(int argc, char** argv)
{
    /*Initialize LittlevGL*/
    lv_init();

    /*Initialize the HAL for LittlevGL*/
    hal_init();

    /*
     * Demos, benchmarks, and tests.
     *
     * Uncomment any one (and only one) of the functions below to run that
     * item.
     */

	SetupScreen(lv_scr_act());
   // lv_demo_widgets();
    //lv_demo_benchmark();
    //lv_demo_keypad_encoder();
    //lv_demo_printer();
    //lv_demo_stress();
    //lv_ex_get_started_1();
    //lv_ex_get_started_2();
    //lv_ex_get_started_3();

    //lv_ex_style_1();
    //lv_ex_style_2();
    //lv_ex_style_3();
    //lv_ex_style_4();
    //lv_ex_style_5();
    //lv_ex_style_6();
    //lv_ex_style_7();
    //lv_ex_style_8();
    //lv_ex_style_9();
    //lv_ex_style_10();
    //lv_ex_style_11();

    /*
     * There are many examples of individual widgets found under the
     * lv_examples/src/lv_ex_widgets directory.  Here are a few sample test
     * functions.  Look in that directory to find all the rest.
     */
    //lv_ex_arc_1();
    //lv_ex_cpicker_1();
    //lv_ex_gauge_1();
    //lv_ex_img_1();
    //lv_ex_tileview_1();

    while (1) {
        /* Periodically call the lv_task handler.
        * It could be done in a timer interrupt or an OS task too.*/
        lv_task_handler();
        Sleep(10);       /*Just to let the system breathe */
    }

    return 0;
}

/**********************
*   STATIC FUNCTIONS
**********************/


/**
* Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library
*/
static void hal_init(void)
{
    /* Add a display
    * Use the 'monitor' driver which creates window on PC's monitor to simulate a display*/
    monitor_init();

    static lv_disp_buf_t disp_buf1;
    static lv_color_t buf1_1[LV_HOR_RES_MAX * 120];
    lv_disp_buf_init(&disp_buf1, buf1_1, NULL, LV_HOR_RES_MAX * 120);

    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
    disp_drv.buffer = &disp_buf1;
    disp_drv.flush_cb = monitor_flush;
    lv_disp_drv_register(&disp_drv);

    /* Add the mouse (or touchpad) as input device
    * Use the 'mouse' driver which reads the PC's mouse*/
    mouse_init();
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);          /*Basic initialization*/
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = mouse_read;         /*This function will be called periodically (by the library) to get the mouse position and state*/
    lv_indev_drv_register(&indev_drv);

    /* If the PC keyboard driver is enabled in`lv_drv_conf.h`
    * add this as an input device. It might be used in some examples. */
#if USE_KEYBOARD
    lv_indev_drv_t kb_drv;
    lv_indev_drv_init(&kb_drv);
    kb_drv.type = LV_INDEV_TYPE_KEYPAD;
    kb_drv.read_cb = keyboard_read;
    kb_indev = lv_indev_drv_register(&kb_drv);
#endif

    /* Tick init.
    * You have to call 'lv_tick_inc()' in every milliseconds
    * Create an SDL thread to do this*/
    SDL_CreateThread(tick_thread, "tick", NULL);
}

/**
* A task to measure the elapsed time for LittlevGL
* @param data unused
* @return never return
*/
static int tick_thread(void *data)
{
    while (1) {
        lv_tick_inc(5);
        SDL_Delay(5);   /*Sleep for 1 millisecond*/
    }

    return 0;
}

I then rebuilt the project and ran it in the debugger which gives the following output:

.

All I can suggest now is you double check the git clone is up to date.
If you have other code in the project this should also be carefully checked.

I would also suggest as a test you make a copy of you main.c file and save it somewhere safe, create a new blank main.c file and copy the code above into the file, rebuild the project and see if you get the same results as I do.

I hope that helps,

Kind Regards,

Pete.

I’m very thank you for you build new project to test my code.I’m trying download your project.
what’s your LVGL version and I did not find you change my code.

I’ve fixed it a few days ago in master. Could you try with the latest version?

Thank you very much I will update my LVGL .Is the latest version different from V7? My project is very huge.

No; master contains the development version of 7.2 which should be a drop-in replacement for 7.0.

1.I use the lv_style_reset() before lv_style_init(),because I buid some screens and roller screen just one of them and The roller screen will enter and exit many time and every screen has many object styles.The lv_obj_add_style() function will malloc memory so I don’t know when I should clean the memory then I clean the styles when I enter someone screen evey time and again malloc those memory.
2.

Hi @zhuxiya,

You only need to call your InitRollerStyle(); function once at the beginning to initialise the style. You can then call RollerSetting() and reuse the style over and over as you have declared your style variables as static globals with in the module. If that makes sense?

Kind Regards,

Pete

Thank you ,that’s an strange thing,I update the lvgl from https://github.com/lvgl/lv_sim_visual_studio_sdl.git to v7.1.and use pete-pjb teacher’s code without any change,it works perfect the same as pete-pjb teacher showed animation,but with the same code on my old v7,it apears my problem which showed in the topic head.

Thank you ,I have down load the lvgl dev-7.1 form https://github.com/lvgl/lv_sim_visual_studio_sdl.git,I put pete-pjb teacher’s code in the lv_sim_visual_studio_sdl.It works very well the same as pete-pjb teacher’s showed animation.but the same code without any change in lvgl dev7.it come out the problem which I showed animation in the head of topic.

Thank you very much, I update the lvgl from v7 to v7.1,I copy your code with no change in the v7.1 lvgl,it has no problem but I copy your code in v7.0 it apear the problem.I don’t know why.

I put my old code in the lv_sim_visual_studio_sdl with which use dev-7,and add the lv_style_init() function in static void InitTableview(lv_obj_t *obj) and Comment out the lv_style_reset() function in static void InitRollerStyle(void) function it also works very well.
I guess the prroblem really connect with the lvgl version
/****my old code/
#include “lvgl/lvgl.h”
#include “roller_test.h”

static lv_obj_t *tabview = NULL;
static lv_obj_t *tab1 = NULL;
static lv_style_t rollerBgStyle, rollerSelStyle;
static char hourStrBuf[3] = { 0 };
static char minuteStrBuf[3] = { 0 };
static char secondStrBuf[3] = { 0 };
static lv_obj_t *hourRoller = NULL;
static lv_obj_t *minuteRoller = NULL;
static lv_obj_t *secondRoller = NULL;
static uint32_t timerTmp = 60;
static const char *HourBuf = “00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23”;
static const char *MinuteBuf = “00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29”
“\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59”;
static const char *SecondBuf = “00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29”
“\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59”;

static void InitTableview(lv_obj_t *obj)
{
static lv_style_t bgStyle;
static lv_style_t scrlStyle;
tabview = lv_tabview_create(obj, NULL);
lv_obj_set_size(tabview, LV_HOR_RES, LV_VER_RES);
lv_style_init(&bgStyle);
lv_obj_add_style(tabview, LV_OBJ_PART_MAIN, &bgStyle);
lv_tabview_set_btns_pos(tabview, LV_TABVIEW_TAB_POS_NONE);
lv_obj_align(tabview, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);

tab1 = lv_tabview_add_tab(tabview, "Tab1");
lv_page_set_scrlbar_mode(tab1, LV_SCRLBAR_MODE_OFF);
lv_style_init(&scrlStyle);
lv_obj_add_style(tab1, LV_PAGE_PART_SCROLLABLE, &scrlStyle);
lv_tabview_set_tab_act(tabview, 1, LV_ANIM_OFF);

}

static void RollerSetting(lv_obj_t *roller, const char *opt, lv_coord_t xpos, uint16_t index, lv_event_cb_t event)
{
roller = lv_roller_create(tab1, NULL);
lv_roller_set_options(roller, opt, LV_ROLLER_MODE_INIFINITE);
lv_obj_set_size(roller, 36, 150);
lv_obj_add_style(roller, LV_ROLLER_PART_BG, &rollerBgStyle);
lv_obj_add_style(roller, LV_ROLLER_PART_SELECTED, &rollerSelStyle);
lv_roller_set_auto_fit(roller, false);
lv_roller_set_visible_row_count(roller, 3);
lv_roller_set_selected(roller, index, LV_ANIM_OFF);
lv_obj_set_event_cb(roller, event);
lv_obj_align(roller, NULL, LV_ALIGN_IN_TOP_LEFT, xpos, 40);
}

static void TimerHourRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
if (event == LV_EVENT_VALUE_CHANGED) {
memset(hourStrBuf, 0, sizeof(hourStrBuf));
lv_roller_get_selected_str(obj, hourStrBuf, sizeof(hourStrBuf));
}
}

static void TimerMinuteRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
if (event == LV_EVENT_VALUE_CHANGED) {
memset(minuteStrBuf, 0, sizeof(minuteStrBuf));
lv_roller_get_selected_str(obj, minuteStrBuf, sizeof(minuteStrBuf));
}
}

static void TimerSecondRollerEventHandler(lv_obj_t *obj, lv_event_t event)
{
if (event == LV_EVENT_VALUE_CHANGED) {
memset(secondStrBuf, 0, sizeof(secondStrBuf));
lv_roller_get_selected_str(obj, secondStrBuf, sizeof(secondStrBuf));
}
}

static void SettingTimerUI(void)
{
uint16_t hourIndex = timerTmp / 3600 + 2;
if (hourRoller == NULL) {
RollerSetting(hourRoller, HourBuf, 30, hourIndex, TimerHourRollerEventHandler);
}

uint16_t minuteIndex = timerTmp % 3600 / 60 + 5;
if (minuteRoller == NULL) {
	RollerSetting(minuteRoller, MinuteBuf, 133, minuteIndex, TimerMinuteRollerEventHandler);
}

uint16_t secondIndex = timerTmp % 60 + 5;
if (secondRoller == NULL) {
	RollerSetting(secondRoller, SecondBuf, 234, secondIndex, TimerSecondRollerEventHandler);
}

}

static void InitRollerStyle(void)
{
//lv_style_reset(&rollerBgStyle);
lv_style_init(&rollerBgStyle);
lv_style_set_bg_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_bg_grad_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_bg_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
lv_style_set_radius(&rollerBgStyle, LV_STATE_DEFAULT, 0);
lv_style_set_border_width(&rollerBgStyle, LV_STATE_DEFAULT, 0);
lv_style_set_text_opa(&rollerBgStyle, LV_STATE_DEFAULT, LV_OPA_100);
lv_style_set_text_line_space(&rollerBgStyle, LV_STATE_DEFAULT, 32);
lv_style_set_text_color(&rollerBgStyle, LV_STATE_DEFAULT, LV_COLOR_GRAY);
//lv_style_reset(&rollerSelStyle);
lv_style_init(&rollerSelStyle);
lv_style_set_bg_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_bg_grad_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_text_color(&rollerSelStyle, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x00, 0xd8, 0xff));
}

void SetupScreen(lv_obj_t *obj)
{
InitRollerStyle();
InitTableview(obj);

SettingTimerUI();

}
/*******************************************************************/