📚 راهنمای کامل ماژول LVGL برای EVM – نسخه مدیریت حافظه

 

🎯 معرفی ماژول LVGL

 

ماژول LVGL امکان ایجاد رابط کاربری گرافیکی روی ESP32 را برای ماشین مجازی جاوا  برای امبدد بردها را فراهم می‌کند. این ماژول تمام ویجت‌های اصلی LVGL را پشتیبانی می‌کند.


🏗️ ساختار اصلی

 

ایجاد و مدیریت آبجکت‌ها

 

// ایجاد صفحه اصلی
let screen = lv.lv_scr_act();

// ایجاد آبجکت جدید
let obj = lv.lv_obj_create(screen);

// تنظیم موقعیت و سایز
lv.lv_obj_set_pos(obj, 10, 20);
lv.lv_obj_set_size(obj, 100, 50);

🔥 مدیریت حافظه و تخریب آبجکت‌ها (جدید)

 

تخریب ایمن آبجکت‌ها

 

// 🔥 روش صحیح تخریب آبجکت
let obj = lv.lv_obj_create(screen);
let style = lv.lv_style_create();

// تنظیم استایل و خصوصیات
lv.lv_obj_add_style(obj, style, 0);

// 🔥 تخریب صحیح آبجکت و استایل
lv.destroy_obj({
    nativePtr: obj,
    stylePtr: style
});

console.log("Object destroyed successfully!");

پاکسازی کامل تمام آبجکت‌ها

 

// 🔥 پاکسازی ایمن تمام آبجکت‌های صفحه
let count = lv.safe_destroy_all();
console.log("Destroyed " + count + " objects");

// 🔥 پاکسازی انتخابی
let parent = lv.lv_obj_create(screen);
// ایجاد چندین child
let child1 = lv.lv_obj_create(parent);
let child2 = lv.lv_obj_create(parent);

// پاکسازی تمام children های یک parent
lv.lv_obj_delete_all_children(parent);

توابع جدید مدیریت حافظه

 

// بررسی valid بودن آبجکت
if (lv.lv_obj_is_valid(obj)) {
    console.log("Object is valid");
} else {
    console.log("Object is invalid");
}

// تخریب فوری آبجکت
lv.lv_obj_del(obj);

// تخریب غیرهمزمان (برای جلوگیری از deadlock)
lv.lv_obj_del_async(obj);

// پاکسازی استایل
lv.lv_style_destroy(style);

🎨 مدیریت استایل‌ها

 

ترتیب صحیح کار با LVGL:

 

  1. ایجاد استایل
  2. مقداردهی اولیه استایل (init_style)
  3. تنظیم خصوصیات استایل
  4. اعمال استایل به آبجکت
  5. تخریب استایل وقتی نیاز نیست
// ایجاد و مقداردهی استایل
let style = lv.lv_style_create();
lv.init_style(style); // 🔥 تابع جدید برای مقداردهی اولیه

// تنظیم خصوصیات
lv.set_style_bg_color(style, lv.lv_color_hex(0xFF0000));
lv.set_style_bg_opa(style, lv.LV_OPA_COVER);
lv.set_style_radius(style, 10);

// اعمال استایل
lv.lv_obj_add_style(obj, style, 0);

// 🔥 وقتی کارمان تمام شد:
lv.destroy_obj({
    nativePtr: obj,
    stylePtr: style
});

پالت رنگ‌های پیش‌فرض

 

// استفاده از پالت‌های پیش‌فرض
let red = lv.lv_palette_main(lv.LV_PALETTE_RED);
let blue = lv.lv_palette_main(lv.LV_PALETTE_BLUE);
let green = lv.lv_palette_main(lv.LV_PALETTE_GREEN);

// تبدیل RGB به رنگ LVGL
let customColor = lv.rgba_to_color(1.0, 0.5, 0.0, 1.0); // 🔥 تابع جدید

📋 ویجت‌های اصلی

 

۱. Label (متن)

 

// ایجاد لیبل
let label = lv.lv_label_create(screen);

// تنظیم متن
lv.lv_label_set_text(label, "Hello EVM!");

// تنظیم متن طولانی با اتوماتیک برش
lv.lv_label_set_long_mode(label, lv.LV_LABEL_LONG_SCROLL_CIRCULAR);

// تنظیم موقعیت
lv.lv_obj_set_pos(label, 10, 10);

// تنظیم استایل متن
let textStyle = lv.lv_style_create();
lv.init_style(textStyle);
lv.set_style_text_color(textStyle, lv.lv_color_hex(0xFFFFFF));
lv.set_style_text_font(textStyle, lv.lvgl_style_get_font(16)); // 🔥 انتخاب فونت
lv.lv_obj_add_style(label, textStyle, 0);

// 🔥 مدیریت حافظه
// بعد از استفاده:
lv.destroy_obj({
    nativePtr: label,
    stylePtr: textStyle
});

۲. Button (دکمه)

 

// ایجاد دکمه
let btn = lv.lv_btn_create(screen);
lv.lv_obj_set_size(btn, 80, 40);
lv.lv_obj_set_pos(btn, 50, 100);

// اضافه کردن متن روی دکمه
let btnLabel = lv.lv_label_create(btn);
lv.lv_label_set_text(btnLabel, "Click Me!");
lv.lv_obj_center(btnLabel);

// استایل دکمه
let btnStyle = lv.lv_style_create();
lv.init_style(btnStyle);
lv.set_style_bg_color(btnStyle, lv.lv_palette_main(lv.LV_PALETTE_BLUE));
lv.set_style_bg_opa(btnStyle, lv.LV_OPA_COVER);
lv.set_style_radius(btnStyle, 10);
lv.lv_obj_add_style(btn, btnStyle, 0);

// 🔥 ثبت event با مدیریت حافظه
lv.lv_obj_add_event_cb(btn, function(obj, event) {
    console.log("Button clicked! Event:", event);
}, lv.LV_EVENT_CLICKED);

// 🔥 تخریب ایمن
lv.destroy_obj({
    nativePtr: btn,
    stylePtr: btnStyle
});

۳. Slider (اسلایدر)

 

// ایجاد اسلایدر
let slider = lv.lv_slider_create(screen);
lv.lv_obj_set_size(slider, 150, 10);
lv.lv_obj_set_pos(slider, 20, 60);

// تنظیم محدوده
lv.lv_slider_set_range(slider, 0, 100);

// تنظیم مقدار اولیه
lv.lv_slider_set_value(slider, 50, lv.LV_ANIM_OFF);

// استایل اسلایدر
let sliderStyle = lv.lv_style_create();
lv.init_style(sliderStyle);
lv.set_style_bg_color(sliderStyle, lv.lv_palette_main(lv.LV_PALETTE_GREY));
lv.set_style_bg_opa(sliderStyle, lv.LV_OPA_50);
lv.set_style_outline_width(sliderStyle, 0);
lv.lv_obj_add_style(slider, sliderStyle, 0);

// event برای تغییر مقدار
lv.lv_obj_add_event_cb(slider, function(obj, event) {
    let value = lv.lv_slider_get_value(obj);
    console.log("Slider value:", value);
}, lv.LV_EVENT_VALUE_CHANGED);

۴. Switch (سوییچ)

 

// ایجاد سوییچ
let sw = lv.lv_switch_create(screen);
lv.lv_obj_set_pos(sw, 20, 160);

// استایل سوییچ
let switchStyle = lv.lv_style_create();
lv.init_style(switchStyle);
lv.set_style_bg_color(switchStyle, lv.lv_palette_main(lv.LV_PALETTE_GREEN));
lv.lv_obj_add_style(sw, switchStyle, 0);

// event برای تغییر وضعیت
lv.lv_obj_add_event_cb(sw, function(obj, event) {
    let isOn = lv.lv_obj_has_state(obj, lv.LV_STATE_CHECKED);
    console.log("Switch is:", isOn ? "ON" : "OFF");
}, lv.LV_EVENT_VALUE_CHANGED);

۵. Checkbox (چک‌باکس)

 

// ایجاد چک‌باکس
let cb = lv.lv_checkbox_create(screen);
lv.lv_obj_set_pos(cb, 20, 200);
lv.lv_checkbox_set_text(cb, "Enable Feature");

// استایل چک‌باکس
let checkboxStyle = lv.lv_style_create();
lv.init_style(checkboxStyle);
lv.set_style_text_color(checkboxStyle, lv.lv_color_hex(0x333333));
lv.lv_obj_add_style(cb, checkboxStyle, 0);

// event برای تغییر وضعیت
lv.lv_obj_add_event_cb(cb, function(obj, event) {
    let isChecked = lv.lv_obj_has_state(obj, lv.LV_STATE_CHECKED);
    console.log("Checkbox is:", isChecked ? "checked" : "unchecked");
}, lv.LV_EVENT_VALUE_CHANGED);

۶. Dropdown (لیست کشویی)

 

// ایجاد dropdown
let dropdown = lv.lv_dropdown_create(screen);
lv.lv_obj_set_pos(dropdown, 20, 240);
lv.lv_obj_set_size(dropdown, 120, 40);

// تنظیم گزینه‌ها
lv.lv_dropdown_set_options(dropdown, "Option 1\nOption 2\nOption 3\nOption 4");

// استایل dropdown
let dropdownStyle = lv.lv_style_create();
lv.init_style(dropdownStyle);
lv.set_style_bg_color(dropdownStyle, lv.lv_color_hex(0xF0F0F0));
lv.set_style_border_width(dropdownStyle, 1);
lv.set_style_border_color(dropdownStyle, lv.lv_color_hex(0xCCCCCC));
lv.lv_obj_add_style(dropdown, dropdownStyle, 0);

// event برای انتخاب گزینه
lv.lv_obj_add_event_cb(dropdown, function(obj, event) {
    let selected = lv.lv_dropdown_get_selected(obj);
    console.log("Selected option:", selected);
}, lv.LV_EVENT_VALUE_CHANGED);

۷. Textarea (ورودی متن)

 

// ایجاد textarea
let ta = lv.lv_textarea_create(screen);
lv.lv_obj_set_size(ta, 200, 60);
lv.lv_obj_set_pos(ta, 20, 280);

// تنظیم placeholder
lv.lv_textarea_set_placeholder_text(ta, "Enter text here...");

// تنظیم متن تک خطی
lv.lv_textarea_set_one_line(ta, true);

// استایل textarea
let textareaStyle = lv.lv_style_create();
lv.init_style(textareaStyle);
lv.set_style_bg_color(textareaStyle, lv.lv_color_hex(0xFFFFFF));
lv.set_style_border_width(textareaStyle, 1);
lv.set_style_border_color(textareaStyle, lv.lv_color_hex(0xCCCCCC));
lv.set_style_pad_all(textareaStyle, 8);
lv.lv_obj_add_style(ta, textareaStyle, 0);

// event برای تغییر متن
lv.lv_obj_add_event_cb(ta, function(obj, event) {
    let text = lv.lv_textarea_get_text(obj);
    console.log("Textarea content:", text);
}, lv.LV_EVENT_VALUE_CHANGED);

📊 ویجت‌های پیشرفته

 

Arc (پیشرفت دایره‌ای)

 

// ایجاد arc
let arc = lv.lv_arc_create(screen);
lv.lv_obj_set_size(arc, 100, 100);
lv.lv_obj_set_pos(arc, 50, 50);

// تنظیم محدوده و مقدار
lv.lv_arc_set_range(arc, 0, 100);
lv.lv_arc_set_value(arc, 75);

// تنظیم زوایا
lv.lv_arc_set_bg_angles(arc, 0, 270);

// استایل arc
let arcStyle = lv.lv_style_create();
lv.init_style(arcStyle);
lv.set_style_arc_color(arcStyle, lv.lv_palette_main(lv.LV_PALETTE_BLUE));
lv.set_style_arc_width(arcStyle, 8);
lv.lv_obj_add_style(arc, arcStyle, 0);

Bar (نوار پیشرفت)

 

// ایجاد bar
let bar = lv.lv_bar_create(screen);
lv.lv_obj_set_size(bar, 200, 20);
lv.lv_obj_set_pos(bar, 20, 120);

// تنظیم محدوده و مقدار
lv.lv_bar_set_range(bar, 0, 100);
lv.lv_bar_set_value(bar, 60, lv.LV_ANIM_ON);

// استایل bar
let barStyle = lv.lv_style_create();
lv.init_style(barStyle);
lv.set_style_bg_color(barStyle, lv.lv_palette_main(lv.LV_PALETTE_GREEN));
lv.set_style_bg_opa(barStyle, lv.LV_OPA_COVER);
lv.lv_obj_add_style(bar, barStyle, 0);

Roller (غلتک)

 

// ایجاد roller
let roller = lv.lv_roller_create(screen);
lv.lv_obj_set_pos(roller, 20, 300);
lv.lv_obj_set_size(roller, 100, 120);

// تنظیم گزینه‌ها
lv.lv_roller_set_options(roller, "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember", lv.LV_ROLLER_MODE_NORMAL);

// تنظیم سطرهای قابل مشاهده
lv.lv_roller_set_visible_row_count(roller, 3);

// event برای انتخاب
lv.lv_obj_add_event_cb(roller, function(obj, event) {
    let selected = lv.lv_roller_get_selected(obj);
    let text = lv.lv_roller_get_options(obj).split('\n')[selected];
    console.log("Selected month:", text);
}, lv.LV_EVENT_VALUE_CHANGED);

Spinner (لودر چرخان)

 

// ایجاد spinner
let spinner = lv.lv_spinner_create(screen, 1000, 60);
lv.lv_obj_set_size(spinner, 50, 50);
lv.lv_obj_set_pos(spinner, 100, 100);

// استایل spinner
let spinnerStyle = lv.lv_style_create();
lv.init_style(spinnerStyle);
lv.set_style_arc_color(spinnerStyle, lv.lv_palette_main(lv.LV_PALETTE_BLUE));
lv.set_style_arc_width(spinnerStyle, 6);
lv.lv_obj_add_style(spinner, spinnerStyle, 0);

🎨 مدیریت تصاویر با کش

 

// 🔥 سیستم کش تصاویر
let imgDesc = image.png_decode("images/logo.png"); // 🔥 کش خودکار
let img = lv.lv_img_create(screen);
lv.lv_img_set_src(img, imgDesc);
lv.lv_obj_set_pos(img, 50, 50);

// بررسی وجود فایل
if (image.file_exists("images/logo.png")) {
    console.log("File exists!");
}

// تنظیم pivot برای تصاویر
let pivot = [25, 25];
lv.lv_img_set_pivot(img, pivot);

// 🔥 تخریب تصویر وقتی نیاز نیست
image.png_destroy(imgDesc);

// 🔥 مدیریت کش تصاویر
let cacheInfo = image.get_cache_info();
console.log("Cache hits:", cacheInfo.hits, "Misses:", cacheInfo.misses);

// پاکسازی کش
image.clear_image_cache();


🎨 مدیریت تصاویر

 

نمایش تصاویر

 

// ایجاد آبجکت تصویر
let img = lv.lv_img_create(screen);
lv.lv_obj_set_pos(img, 50, 50);

// تنظیم منبع تصویر (از SPIFFS)
lv.lv_img_set_src(img, "A:/images/logo.png");

// تنظیم opacity
lv.lv_obj_set_style_img_opa(img, lv.LV_OPA_70, 0);

ترنسفورمیشن تصاویر

 

// چرخش تصویر
lv.lv_img_set_angle(img, 45); // 45 درجه

// زوم
lv.lv_img_set_zoom(img, 256); // 100% (256 = 1.0)

// جابجایی
lv.lv_img_set_offset_x(img, 10);
lv.lv_img_set_offset_y(img, -5);

🏗️ Layout و Flexbox

 

Flex Layout

 

// تنظیم flex flow
lv.lv_obj_set_flex_flow(parent, lv.LV_FLEX_FLOW_ROW_WRAP);

// تنظیم alignment
lv.lv_obj_set_style_flex_main_place(parent, lv.LV_FLEX_ALIGN_SPACE_EVENLY, 0);
lv.lv_obj_set_style_flex_cross_place(parent, lv.LV_FLEX_ALIGN_CENTER, 0);

// تنظیم grow برای آبجکت‌ها
lv.lv_obj_set_flex_grow(child1, 1);
lv.lv_obj_set_flex_grow(child2, 2); // دو برابر child1

انواع Flex Flow

 

lv.LV_FLEX_FLOW_ROW                 // ردیف
lv.LV_FLEX_FLOW_COLUMN             // ستون
lv.LV_FLEX_FLOW_ROW_WRAP           // ردیف با wrap
lv.LV_FLEX_FLOW_COLUMN_WRAP        // ستون با wrap
lv.LV_FLEX_FLOW_ROW_REVERSE        // ردیف معکوس

مدیریت State و Flags

 

مدیریت State

 

// اضافه کردن state
lv.lv_obj_add_state(obj, lv.LV_STATE_CHECKED);
lv.lv_obj_add_state(obj, lv.LV_STATE_DISABLED);

// حذف state
lv.lv_obj_clear_state(obj, lv.LV_STATE_DISABLED);

// بررسی state
let isChecked = lv.lv_obj_has_state(obj, lv.LV_STATE_CHECKED);

مدیریت Flags

 

// اضافه کردن flag
lv.lv_obj_add_flag(obj, lv.LV_OBJ_FLAG_CLICKABLE);
lv.lv_obj_add_flag(obj, lv.LV_OBJ_FLAG_SCROLLABLE);

// حذف flag
lv.lv_obj_clear_flag(obj, lv.LV_OBJ_FLAG_SCROLLABLE);

// بررسی flag
let isClickable = lv.lv_obj_has_flag(obj, lv.LV_OBJ_FLAG_CLICKABLE);

مدیریت تایمرها (جدید)

 

تایمرهای setTimeout/setInterval

 

// 🔥 setTimeout با مدیریت حافظه
let timer1 = setTimeout(function() {
    console.log("Timeout executed!");
}, 1000);

// 🔥 setInterval
let timer2 = setInterval(function() {
    console.log("Interval tick!");
}, 2000);

// 🔥 حذف تایمرها
clearTimeout(timer1);
clearInterval(timer2);

🎯 مدیریت موقعیت و Alignment

 

تراز کردن آبجکت‌ها

 

// تراز مرکزی
lv.lv_obj_center(obj);

// تراز نسبی
lv.lv_obj_align(obj, lv.LV_ALIGN_TOP_LEFT, 10, 10);
lv.lv_obj_align(obj, lv.LV_ALIGN_BOTTOM_RIGHT, -10, -10);

// تراز نسبت به آبجکت دیگر
let parent = lv.lv_obj_create(screen);
let child = lv.lv_obj_create(parent);
lv.lv_obj_align_to(child, parent, lv.LV_ALIGN_CENTER, 0, 0);

ثابت‌های Alignment

 

// انواع تراز
lv.LV_ALIGN_TOP_LEFT
lv.LV_ALIGN_TOP_MID
lv.LV_ALIGN_TOP_RIGHT
lv.LV_ALIGN_BOTTOM_LEFT
lv.LV_ALIGN_BOTTOM_MID
lv.LV_ALIGN_BOTTOM_RIGHT
lv.LV_ALIGN_LEFT_MID
lv.LV_ALIGN_RIGHT_MID
lv.LV_ALIGN_CENTER

🔄 انیمیشن و Effects

 

انیمیشن‌های ساده

 

// fade in
lv.lv_obj_fade_in(obj, 1000, 0); // 1000ms delay

// fade out
lv.lv_obj_fade_out(obj, 1000, 0);

// حذف تمام انیمیشن‌ها
lv.lv_anim_del_all();

ترنسفورمیشن‌ها

 

// چرخش
lv.lv_style_set_transform_angle(style, 45); // 45 درجه

// مقیاس
lv.lv_style_set_transform_zoom(style, 1.5); // 150%

// موقعیت
lv.lv_style_set_translate_x(style, 10);
lv.lv_style_set_translate_y(style, -5);


🎮 مدیریت رویدادها با مدیریت حافظه

 

ثبت event handler ایمن

 

// 🔥 ثبت event با مدیریت حافظه
lv.lv_obj_add_event_cb(btn, function(obj, event) {
    console.log("Event:", event);
    console.log("Position:", lv.indev_get_x(), lv.indev_get_y()); // 🔥 توابع جدید
}, lv.LV_EVENT_CLICKED);

// 🔥 حذف event
lv.lv_obj_remove_event_cb(btn);

// 🔥 حذف تمام eventهای یک آبجکت
lv.lv_obj_remove_all_event_cb(btn);

// 🔥 گرفتن اطلاعات eventهای فعال
let eventInfo = lv.get_active_events_info();
console.log("Active events:", eventInfo.count);

انواع رویدادها

 

lv.LV_EVENT_PRESSED
lv.LV_EVENT_RELEASED
lv.LV_EVENT_CLICKED
lv.LV_EVENT_VALUE_CHANGED
lv.LV_EVENT_FOCUSED
lv.LV_EVENT_DEFOCUSED

📱 مدیریت صفحه نمایش

 

اطلاعات صفحه نمایش

 

// 🔥 توابع جدید برای اندازه صفحه
let screenWidth = lv.get_screen_width();
let screenHeight = lv.get_screen_height();
console.log("Screen size:", screenWidth, "x", screenHeight);

// 🔥 چرخش صفحه نمایش
lv.disp_set_rotation(0); // 0-3 (0°, 90°, 180°, 270°)

موقعیت‌یابی پیشرفته

 

// 🔥 گرفتن موقعیت مطلق
let absX = lv.lv_obj_get_abs_x(obj);
let absY = lv.lv_obj_get_abs_y(obj);

// تنظیم pivot برای تصاویر
let pivot = [50, 50];
lv.lv_img_set_pivot(img, pivot);

🎯 مثال کامل با مدیریت حافظه

 

برنامه نمونه – کنترل پنل با مدیریت حافظه

 

class UIController {
    constructor() {
        this.screen = lv.lv_scr_act();
        this.objects = [];
        this.styles = [];
        this.initUI();
    }

    initUI() {
        // ایجاد دکمه‌ها
        this.createButton("Start", 50, 30, this.onButtonClick.bind(this));
        this.createButton("Stop", 180, 30, this.onButtonClick.bind(this));
        
        // ایجاد اسلایدر
        this.createSlider(20, 100, this.onSliderChange.bind(this));
        
        // ایجاد سوییچ
        this.createSwitch(20, 150, this.onSwitchChange.bind(this));
        
        // ایجاد چک‌باکس
        this.createCheckbox(20, 200, "Enable Feature", this.onCheckboxChange.bind(this));
    }

    createButton(text, x, y, callback) {
        let style = lv.lv_style_create();
        lv.init_style(style);
        lv.set_style_bg_color(style, lv.lv_palette_main(lv.LV_PALETTE_BLUE));
        lv.set_style_radius(style, 10);

        let btn = lv.lv_btn_create(this.screen);
        lv.lv_obj_set_size(btn, 120, 50);
        lv.lv_obj_set_pos(btn, x, y);
        lv.lv_obj_add_style(btn, style, 0);

        let label = lv.lv_label_create(btn);
        lv.lv_label_set_text(label, text);
        lv.lv_obj_center(label);

        // ثبت event
        lv.lv_obj_add_event_cb(btn, callback, lv.LV_EVENT_CLICKED);

        this.objects.push(btn);
        this.styles.push(style);

        return { obj: btn, style: style };
    }

    createSlider(x, y, callback) {
        let slider = lv.lv_slider_create(this.screen);
        lv.lv_obj_set_size(slider, 200, 20);
        lv.lv_obj_set_pos(slider, x, y);
        lv.lv_slider_set_range(slider, 0, 100);
        lv.lv_slider_set_value(slider, 50, lv.LV_ANIM_OFF);

        lv.lv_obj_add_event_cb(slider, callback, lv.LV_EVENT_VALUE_CHANGED);
        this.objects.push(slider);

        return slider;
    }

    createSwitch(x, y, callback) {
        let sw = lv.lv_switch_create(this.screen);
        lv.lv_obj_set_pos(sw, x, y);
        lv.lv_obj_add_event_cb(sw, callback, lv.LV_EVENT_VALUE_CHANGED);
        this.objects.push(sw);
        return sw;
    }

    createCheckbox(x, y, text, callback) {
        let cb = lv.lv_checkbox_create(this.screen);
        lv.lv_obj_set_pos(cb, x, y);
        lv.lv_checkbox_set_text(cb, text);
        lv.lv_obj_add_event_cb(cb, callback, lv.LV_EVENT_VALUE_CHANGED);
        this.objects.push(cb);
        return cb;
    }

    // Event handlers
    onButtonClick(obj, event) {
        let text = lv.lv_label_get_text(lv.lv_obj_get_child(obj, 0));
        console.log("Button clicked:", text);
    }

    onSliderChange(obj, event) {
        let value = lv.lv_slider_get_value(obj);
        console.log("Slider value:", value);
    }

    onSwitchChange(obj, event) {
        let isOn = lv.lv_obj_has_state(obj, lv.LV_STATE_CHECKED);
        console.log("Switch is:", isOn ? "ON" : "OFF");
    }

    onCheckboxChange(obj, event) {
        let isChecked = lv.lv_obj_has_state(obj, lv.LV_STATE_CHECKED);
        console.log("Checkbox is:", isChecked ? "checked" : "unchecked");
    }

    destroyAll() {
        // 🔥 تخریب تمام آبجکت‌ها به صورت ایمن
        this.objects.forEach((obj, index) => {
            if (this.styles[index]) {
                lv.destroy_obj({
                    nativePtr: obj,
                    stylePtr: this.styles[index]
                });
            } else {
                lv.lv_obj_del(obj);
            }
        });

        this.objects = [];
        this.styles = [];

        // 🔥 پاکسازی باقی‌مانده‌ها
        let count = lv.safe_destroy_all();
        console.log("Total destroyed:", count);
    }
}

// استفاده از کلاس
let ui = new UIController();

// وقتی برنامه تمام شد:
// ui.destroyAll();

🔧 الگوهای مدیریت حافظه

 

الگوی ۱: مدیریت دستی

 

function createTemporaryUI() {
    let tempObj = lv.lv_obj_create(screen);
    let tempStyle = lv.lv_style_create();
    lv.init_style(tempStyle);
    
    // استفاده از آبجکت
    
    // 🔥 تخریب وقتی کار تمام شد
    return function cleanup() {
        lv.destroy_obj({
            nativePtr: tempObj,
            stylePtr: tempStyle
        });
    };
}

let cleanup = createTemporaryUI();
// بعد از استفاده:
cleanup();

الگوی ۲: مدیریت خودکار با کلاس

 

class ManagedObject {
    constructor(parent) {
        this.obj = lv.lv_obj_create(parent);
        this.style = lv.lv_style_create();
        lv.init_style(this.style);
        lv.lv_obj_add_style(this.obj, this.style, 0);
    }

    destroy() {
        lv.destroy_obj({
            nativePtr: this.obj,
            stylePtr: this.style
        });
        this.obj = null;
        this.style = null;
    }

    // وقتی آبجکت از scope خارج می‌شود
    __destruct() {
        if (this.obj) this.destroy();
    }
}

🚨 نکات مهم مدیریت حافظه

 

کارهای ضروری

 

// ✅ همیشه استایل‌ها را مقداردهی اولیه کنید
lv.init_style(style);

// ✅ همیشه از destroy_obj استفاده کنید
lv.destroy_obj({ nativePtr: obj, stylePtr: style });

// ✅ eventها را حذف کنید وقتی نیاز نیستند
lv.lv_obj_remove_event_cb(obj);

// ✅ تایمرها را حذف کنید
clearTimeout(timer);

کارهای ممنوع

 

// ❌ هرگز مستقیماً حافظه را آزاد نکنید
// lv_mem_free(obj); // اشتباه!

// ❌ آبجکت‌ها را بدون حذف event رها نکنید

// ❌ استایل‌های استفاده شده را مستقیماً حذف نکنید

بررسی سلامت حافظه

 

// بررسی وضعیت کش تصاویر
let cacheInfo = image.get_cache_info();
console.log("Image cache:", cacheInfo);

// بررسی eventهای فعال
let eventInfo = lv.get_active_events_info();
console.log("Active events:", eventInfo.count);

// بررسی valid بودن آبجکت‌ها
if (lv.lv_obj_is_valid(obj)) {
    console.log("Object is healthy");
}

📊 ثابت‌های جدید

 

مدیریت حافظه

 

// ماکزیمم سایز کش تصاویر
image.MAX_CACHE_SIZE = 10;

// انواع فونت‌های قابل انتخاب
lv.lvgl_style_get_font(8);   // فونت 8px
lv.lvgl_style_get_font(12);  // فونت 12px  
lv.lvgl_style_get_font(16);  // فونت 16px
lv.lvgl_style_get_font(20);  // فونت 20px (پیش‌فرض)
lv.lvgl_style_get_font(24);  // فونت 24px

🔧 نکات مهم و بهترین روش‌ها

 

// پاک‌سازی استایل‌ها وقتی استفاده نمی‌شوند
// lv.lv_style_reset(style); // در LVGL 8.3+

// استفاده از استایل‌های مشترک برای آبجکت‌های مشابه

بهینه‌سازی عملکرد

 

// غیرفعال کردن scroll برای آبجکت‌های ساده
lv.lv_obj_clear_flag(obj, lv.LV_OBJ_FLAG_SCROLLABLE);

// استفاده از انیمیشن فقط وقتی لازم است
lv.lv_slider_set_value(slider, 75, lv.LV_ANIM_OFF); // بدون انیمیشن

عیب‌یابی

 

// بررسی visibility
let isVisible = lv.lv_obj_is_visible(obj);

// بررسی موقعیت و سایز
let x = lv.lv_obj_get_x(obj);
let y = lv.lv_obj_get_y(obj);
let width = lv.lv_obj_get_width(obj);
let height = lv.lv_obj_get_height(obj);

🎨 پالت رنگ‌های کامل

 

// تمام پالت‌های رنگی موجود
lv.LV_PALETTE_RED
lv.LV_PALETTE_PINK
lv.LV_PALETTE_PURPLE
lv.LV_PALETTE_DEEP_PURPLE
lv.LV_PALETTE_INDIGO
lv.LV_PALETTE_BLUE
lv.LV_PALETTE_LIGHT_BLUE
lv.LV_PALETTE_CYAN
lv.LV_PALETTE_TEAL
lv.LV_PALETTE_GREEN
lv.LV_PALETTE_LIGHT_GREEN
lv.LV_PALETTE_LIME
lv.LV_PALETTE_YELLOW
lv.LV_PALETTE_AMBER
lv.LV_PALETTE_ORANGE
lv.LV_PALETTE_DEEP_ORANGE
lv.LV_PALETTE_BROWN
lv.LV_PALETTE_BLUE_GREY
lv.LV_PALETTE_GREY

این راهنمای کامل تمام ویجت‌های اصلی LVGL را همراه با مدیریت حافظه پیشرفته پوشش می‌دهد و بهترین روش‌ها برای ایجاد رابط‌های کاربری پایدار و بدون memory leak را ارائه می‌کند.

📦 لینک‌های مرجع و منابع

🔗 مخزن گیت‌هاب ESP32 EVM:

https://github.com/hadipic/evm-linux?tab=readme-ov-file

https://github.com/hadipic/esp32-evm-bin?tab=readme-ov-file

🔗 کانال تلگرام EVM:
https://t.me/esp32_evm

🔗 معرفی ماشین مجازی EVM در شاپ الکترونیک

https://shop-electronic.ir/ماشین-مجازی-جاوا-برای-امبد-بردها-evm-embedded-virtual-machi/

🔗لینک اپارات

https://aparat.com/v/ejyt63u