How to Access and Modify Individual Tab Buttons in LVGL Tabview?

Hello,

I am working with the lv_tabview widget in LVGL, and I need to access and modify the individual tab buttons to change their styles based on certain conditions.

I have tried using lv_tabview_get_tab_btns to get the button matrix, but I am not sure how to iterate through the individual buttons and apply different styles. Here are the steps I’ve tried:

  1. Created the tabview and added tabs using lv_tabview_add_tab.
  2. Used lv_tabview_get_tab_btns to get the button matrix object.
  3. Attempted to iterate through the buttons using lv_btnmatrix_get_map.

The code block should be formatted like:

/*void cDPgrammeWindow::updateTabValue(lv_obj_t *tabview, int tab_index)
{
    // Définir les styles
    static lv_style_t style_red;
    static lv_style_t style_green;

    lv_obj_t *tab;
    char tmpTxt1[150];
    int Freq2 = 0, L1 = 0, L2 = 0, F1 = 0, DbLevel = 0, NoiseLevel = 0, SNR = 0;
    bool conditionDP = false;
    
    lv_style_init(&style_red);
    lv_style_set_text_color(&style_red, lv_palette_main(LV_PALETTE_RED));

    lv_style_init(&style_green);
    lv_style_set_text_color(&style_green, lv_palette_main(LV_PALETTE_GREEN));

    if (DPgrammeProcessor == nullptr || DPgrammeProcessor->fullData.empty()) return;

    for (int i = 0; i < tab_index; i++) {

        if (i < DPgrammeProcessor->fullData.size()) {

            auto& data = DPgrammeProcessor->fullData.at(i);
            Freq2 = data.getF2();
            L1 = data.getPowerVoie1();
            L2 = data.getPowerVoie2();
            F1 = data.getF1();
            DbLevel = static_cast<int>(data.getSignalRounded());
            NoiseLevel = static_cast<int>(data.getNoiseRounded());
            SNR = static_cast<int>(data.getSignalNoiseRatioRounded());
            conditionDP = static_cast<bool>(data.getCondition());
        }

        char TmpLabel[32];
        sprintf(TmpLabel, "Fréq : %d Hz", Freq2);
        tab = lv_tabview_add_tab(tabview, TmpLabel);

        char tempLabel[70];
        const char *symbol = !conditionDP ? LV_SYMBOL_CLOSE : LV_SYMBOL_OK;
        lv_color_t color = !conditionDP ? lv_palette_main(LV_PALETTE_RED) : lv_palette_main(LV_PALETTE_LIGHT_GREEN);
        sprintf(tempLabel, "%s Fréq %d Hz", symbol, Freq2);
        lv_obj_set_style_bg_color(tab, color, 0);
        lv_obj_set_style_bg_opa(tab, LV_OPA_COVER, LV_PART_MAIN);
        lv_tabview_rename_tab(tabview, i, tempLabel);

        // Obtenir les boutons d'onglets
        lv_obj_t *tab_btns = lv_tabview_get_tab_btns(tabview);

        // Appliquer le style conditionnel au texte de l'onglet
        if (!conditionDP) {
            lv_obj_add_style(tab_btns, &style_red, LV_PART_MAIN);
        } else {
            lv_obj_add_style(tab_btns, &style_green, LV_PART_MAIN);
        }

        sprintf(tmpTxt1, "Niveau L1 : %d dB SPL\nNiveau L2 : %d dB SPL\nF1 : %d Hz\nF2 : %d Hz\nDb Level : %d dB\nNiveau de bruit : %d dB\nRapport signal/bruit : %d",
                L1, L2, F1, Freq2, DbLevel, NoiseLevel, SNR);

        lv_obj_t *label = lv_label_create(tab);
        lv_label_set_text(label, tmpTxt1);
        lv_obj_scroll_to_view(label, LV_ANIM_ON);
    }
}*/

Despite these steps, I am unable to properly access and style each button individually.

Can anyone provide guidance or examples on how to achieve this?

Thank you!

Screenshot

image

Hello everyone,

I found a solution to the problem of customizing the tab button styles in lv_tabview. Here’s the solution I implemented:

void cDPgrammeWindow::updateTabStyles(lv_obj_t *tabview, int btn_index, bool conditionDP) {
    // Obtenez la matrice de boutons du tabview
    lv_obj_t *tab_btns = lv_tabview_get_tab_btns(tabview);

    // Créez un rappel pour le dessin des boutons
    lv_event_cb_t draw_part_event_cb = [](lv_event_t * e) {
        lv_event_code_t code = lv_event_get_code(e);
        lv_obj_t * obj = lv_event_get_target(e);
        intptr_t data = (intptr_t)lv_event_get_user_data(e);
        int btn_index = data >> 1;
        bool conditionDP = data & 1;

        if (code == LV_EVENT_DRAW_PART_BEGIN) {
            lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e);

            // Personnalisez seulement si c'est un bouton de la matrice
            if (dsc->class_p == &lv_btnmatrix_class && dsc->type == LV_BTNMATRIX_DRAW_PART_BTN) {
                if (dsc->id == btn_index) {
                    if (conditionDP) {
                        dsc->label_dsc->color = lv_palette_main(LV_PALETTE_GREEN);
                    } else {
                        dsc->label_dsc->color = lv_palette_main(LV_PALETTE_RED);
                    }
                }
            }
        }
    };

    // Passez les données nécessaires 
    intptr_t user_data = (btn_index << 1) | conditionDP;
    lv_obj_add_event_cb(tab_btns, draw_part_event_cb, LV_EVENT_DRAW_PART_BEGIN, (void *)user_data);
}

void cDPgrammeWindow::updateTabValue(lv_obj_t *tabview, int tab_index) {
    lv_obj_t *tab;
    char tmpTxt1[150];
    int Freq2 = 0, L1 = 0, L2 = 0, F1 = 0, DbLevel = 0, NoiseLevel = 0, SNR = 0;
    bool conditionDP = false;

    if (DPgrammeProcessor == nullptr || DPgrammeProcessor->fullData.empty()) return;

    for (int i = 0; i < tab_index; i++) {
        if (i < DPgrammeProcessor->fullData.size()) {
            auto& data = DPgrammeProcessor->fullData.at(i);
            Freq2 = data.getF2();
            L1 = data.getPowerVoie1();
            L2 = data.getPowerVoie2();
            F1 = data.getF1();
            DbLevel = static_cast<int>(data.getSignalRounded());
            NoiseLevel = static_cast<int>(data.getNoiseRounded());
            SNR = static_cast<int>(data.getSignalNoiseRatioRounded());
            conditionDP = static_cast<bool>(data.getCondition());
        }

        char TmpLabel[32];
        sprintf(TmpLabel, "Fréq : %d Hz", Freq2);
        tab = lv_tabview_add_tab(tabview, TmpLabel);

        char tempLabel[70];
        const char *symbol = !conditionDP ? LV_SYMBOL_CLOSE : LV_SYMBOL_OK;
        lv_color_t color = !conditionDP ? lv_palette_main(LV_PALETTE_RED) : lv_palette_main(LV_PALETTE_LIGHT_GREEN);
        sprintf(tempLabel, "%s Fréq %d Hz", symbol, Freq2);
        lv_obj_set_style_bg_color(tab, color, 0);
        lv_obj_set_style_bg_opa(tab, LV_OPA_COVER, LV_PART_MAIN);
        lv_tabview_rename_tab(tabview, i, tempLabel);

        updateTabStyles(tabview, i, conditionDP);

        sprintf(tmpTxt1, "Niveau L1 : %d dB SPL\nNiveau L2 : %d dB SPL\nF1 : %d Hz\nF2 : %d Hz\nDb Level : %d dB\nNiveau de bruit : %d dB\nRapport signal/bruit : %d",
                L1, L2, F1, Freq2, DbLevel, NoiseLevel, SNR);

        lv_obj_t *label = lv_label_create(tab);
        lv_label_set_text(label, tmpTxt1);
        lv_obj_scroll_to_view(label, LV_ANIM_ON);
    }
}

This solution customizes the text color of the tab buttons based on a condition. I hope this helps anyone facing a similar issue!