How to make template out of components?

Description

What do you want to achieve?

making template composed of two or more component. so it is like a new component that has some features like positon
in my case I have a name label , a slider and another label to show slider value in a row

You need to fill out the whole template. You can’t just erase part of it.

hardware is not part of my question,it is a general question and those other parts are irrelevant , but if you have a point I will

It’s fine this time, but for the future, we want to make it a rule that you have to fill out the template. We get lots of requests where little to no useful information is provided at the start.

I suggest you make a function that creates the objects on a given container and sets their positions and then reuse that function throughout your code.

I always read all part of template and if there is a relevant part I fill that part

I will make a try your idea but the hardest part I think is event call back part of slider

My approach usually is to create a gui folder where lvgl is a submodule inside it and create files like gui_slider.c with functions:

gui_slider_t * gui_slider_create(lv_obj_t * parent, gui_slider_type_t type, void (*cb) (gui_slider_t *, int32_t)) 
{
  /*Alloacte `gui_slider_t`*/

  /*Create a slider and save it in `gui_slider_t`*/

  /*Set a generic callback which will call `cb` on value change*/

  /*Set size, ranges and styles according to type*/

  /*Create additoinal objects (like labels) and save them in `gui_slider_t`*/

  /*Other settings an adjustments*/

  /*Return `gui_slider_t *` */
} 

void gui_slider_set_title(gui_slider_t * slider, const char * title)
{
   /*Set the text of a label stored in `gui_slider_t`*/
} 

You can do anything you want it’s just what worked well in my projects and aligns to my coding style and taste.

1 Like

Thank you for suggestion but there are some issues that I did not understand ,

one of labels inside my template is sync with slider that shows value of slider . so It’s handler must be called inside slider callback. with this structure how is it possible to do this? keep this in mind that I don’t want to declare this label globally because I want to use it in a for-loop.

You can use the lv_obj_set_user_data(slider, custom_slider_dsc) the user data type can be set in lv_conf.h as lv_obj_user_data_t (the default void* could work for you)

Or a more professional way it to add custom data to the slider’s extended data. See this post.

1 Like

I studied your article, that was so advanced for me(took me 8 hours that can write something) but gave me a lot of insight though I am not finished with that. I end up with something like this.

 typedef struct
{

  lv_obj_t *slider; /*Include the ancestors extend data first*/ 
  lv_obj_t *value_label;
  lv_obj_t *name_label;

  /*Add new data*/
} gui_slider_t;

void slider_event_handler(lv_obj_t *obj, lv_event_t event)
{
  gui_slider_t *ext = lv_obj_get_ext_attr(obj);

  if (event == LV_EVENT_VALUE_CHANGED)
  {
    char val[5];
    sprintf(val, "%d", lv_slider_get_value(obj) );
    lv_label_set_text(ext->value_label, val);
    //printf("Value: %d\n", );
  }
}

gui_slider_t *gui_slider_create(lv_obj_t *parent, lv_event_cb_t cb)
{

  

  //slider part

    static lv_style_t style_bg;
    static lv_style_t style_indic;
    static lv_style_t style_knob;

    lv_style_copy(&style_bg, &lv_style_pretty);
    style_bg.body.main_color =  LV_COLOR_BLACK;
    style_bg.body.grad_color =  LV_COLOR_GRAY;
    style_bg.body.radius = LV_RADIUS_CIRCLE;
    style_bg.body.border.color = LV_COLOR_WHITE;


    lv_style_copy(&style_indic, &lv_style_pretty_color);
    style_indic.body.radius = LV_RADIUS_CIRCLE;
    style_indic.body.shadow.width = 8;
    style_indic.body.shadow.color = style_indic.body.main_color;
    style_indic.body.padding.left = 3;
    style_indic.body.padding.right = 3;
    style_indic.body.padding.top = 3;
    style_indic.body.padding.bottom = 3;

    lv_style_copy(&style_knob, &lv_style_pretty);
    style_knob.body.radius = LV_RADIUS_CIRCLE;
    style_knob.body.opa = LV_OPA_70;
    style_knob.body.padding.top = 10 ;
    style_knob.body.padding.bottom = 10 ;
  /*Create a slider*/
	lv_obj_t* slider = lv_slider_create(parent, NULL);
  lv_slider_set_range(slider, 0, 6);
  lv_obj_set_pos(slider, 50, 0);
	
  lv_slider_set_style(slider, LV_SLIDER_STYLE_BG, &style_bg);
  lv_slider_set_style(slider, LV_SLIDER_STYLE_INDIC, &style_indic);
  lv_slider_set_style(slider, LV_SLIDER_STYLE_KNOB, &style_knob);
  lv_obj_set_event_cb(slider, cb);
  lv_obj_set_width(slider, 90);
 
  
	lv_obj_allocate_ext_attr(slider, sizeof(gui_slider_t));
	
	
  /*Create additoinal objects (like labels) and save them in `gui_slider_t`*/

  lv_obj_t *value_label = lv_label_create(parent, NULL);
  lv_obj_t* name_label = lv_label_create(parent, NULL);

  
	
  gui_slider_t *ext = lv_obj_get_ext_attr(slider);
//	ext->slider=slider;
	ext->value_label=value_label;
	ext->name_label=name_label;
	
	
	

  //label name part

  lv_label_set_long_mode(name_label, LV_LABEL_LONG_BREAK); /*Break the long lines*/
  lv_label_set_recolor(name_label, true);                  /*Enable re-coloring by commands in the text*/
  lv_obj_set_pos(name_label, 10, 0);
  lv_obj_set_width(name_label, 120);
	
	
	// value label

 lv_label_set_long_mode(value_label, LV_LABEL_LONG_BREAK); /*Break the long lines*/
  lv_label_set_recolor(value_label, true);                  /*Enable re-coloring by commands in the text*/
  lv_obj_set_pos(value_label, 160, 5);       /*Center aligned lines*/
  lv_label_set_text(value_label, "0");
  lv_obj_set_width(value_label, 60);
	
	
  /*Other settings an adjustments*/
  return ext;
  /*Return `gui_slider_t *` */
}

in main i will call
gui_slider_t *x1= gui_slider_create(page, slider_event_handler);

when I changed slider value it changed from 0 to 7480 while I set it from 0 to 6
what is my mistake?

problem is

	lv_obj_allocate_ext_attr(slider, sizeof(gui_slider_t));

in gui_slider_create function I tested this in simulator and adding this line prevent tft from start

It took me a lot of time without any success so I abandon this subject and declare everything globally until a solution provided

The ancestor data needs to be of type lv_slider_ext_t not lv_obj_t *

I wanted it to be simple and easy to digest. I’ll improve it.

1 Like