Dzisiaj zajmiemy się tematyką wprowadzenia tekstu przez wyświetlacz dotykowy w LVGL. W przypadku starszych wyświetlaczy, bez opcji "dotykowej", trzeba było mieć osobną klawiaturę by w ogóle coś wpisać. Było to dość problematyczne. W przypadku wyświetlacza dotykowego możemy natomiast po prostu wyświetlić "wirtualną" klawiaturę na ekranie i obsłużyć ją 100% w kodzie. LVGL oferuje gotowy mechanizm takiej klawiatury, który tutaj przedstawię. Następnie rozwinę pokazany przykład tak, by utworzyć z niego prosty formularz logowania - login i hasło. Przy okazji poćwiczymy też zmianę aktywnego widoku (tam i z powrotem - logowanie i wylogowanie).
W poprzednich częściach do tworzenia UI używałem SquareLine Studio, ale dziś tworzyć będę wszystko w kodzie.
Ten temat stanowi kontynuację serii o płytce ESP32-2432S028R:
ESP32 i wyświetlacz dotykowy - tutorial - część 1 - jak programować? Podstawy
ESP32 i wyświetlacz dotykowy - część 2 - jak rysować piksele, linie, kształty, kwestia wydajności
ESP32 i wyświetlacz dotykowy - tutorial cz. 3 - interakcje, gry i zabawy
ESP32 i wyświetlacz dotykowy - tutorial cz. 4 - pogoda z internetu, API, JSON
ESP32 i wyświetlacz dotykowy - część 5 - LVGL w SquareLine Studio
ESP32 i wyświetlacz dotykowy - część 6, kontrola lampy RGB, RGB picker
Zacznijmy od prostego przykładu klawiatury z dokumentacji. Zasadniczo tylko poprawiłem tutaj pobieranie wskaźnika na obiekt ekranu:
Kod: C / C++
Powyższy kod w pełni tworzy wymagane elementy, ustawia ich pozycje i wymiary. Przyjrzyjmy się mu bliżej.
Mamy tu następujące sekcje. Tworzenie głównego panelu z opcją przewijania (scroll):
Kod: C / C++
Tworzenie klawiatury:
Kod: C / C++
Tworzenie pola tekstowego:
Kod: C / C++
Ustawienie obsługi jego zdarzeń, ustawienie jego tekstu, pozycjonowania (względem górnego lewego rogu):
Kod: C / C++
Tekst "placeholder" to ten szary tekst będący podpowiedzią co wpisać który wyświetla się zanim my coś sami wpiszemy.
Drugie pole, jak wyżej:
Kod: C / C++
Przypięcie klawiatury do pierwszego pola:
Kod: C / C++
Kompilujemy i wgrywamy. W rezultacie mamy klawiaturę, która automatycznie dodaje znaki do wybranego pola.
Okej, ale co z drugim polem? Czemu nie da się do niego pisać?
To dlatego, że musimy ręcznie przepiąć klawiaturę do tego pola, które jest aktywne.
Przeróbmy nasz przykład na formę logowania. W tym celu dodajemy obsługę zdarzeń dla każdego z pól. W momencie zdarzenia FOCUSED (aktywowania danego pola), przepinamy na nie klawiaturę. W momencie utraty FOCUSED, tę klawiaturę chowamy.
Kod: C / C++
Zmodyfikowałem też lekko tworzenie pól. LVGL nawet oferuje gotowe funkcje do tworzenia form logowania, w tym do pola z hasłem - lv_textarea_set_password_mode. Więcej informacji w dokumentacjam.
Wspomniana obsługa zdarzenia musi być przypięta do obu pól. Wystarczy jedna funkcja. Cały kod:
Kod: C / C++
Wgrywamy, oto rezultat:
Rzeczywiście, wygląda to jak forma do logowania a i nawet hasło jest poprawnie zakryte gwiazdkami.
Pora na drobną kosmetykę - przycisk login i label.
Dopiszmy, najpierw jakiś label informujący o stanie logowania:
Kod: C / C++
Potem, osobno dodajemy przycisk z odpowiednim napisem. Można mu też ustawić obsługę kliknięcia - zdarzenie EVENT_CLICKED poprzez lv_obj_add_event_cb.
Kod: C / C++
Event na razie dodałem zakomentowany. Sprawdźmy jak sam przycisk wygląda...
Rezultat:
Zrobiliśmy coś nie tak! Przycisk jest nad klawiaturą. Widać, że kolejność gra rolę. Najprościej jest przenieść tworzenie klawiatury wcześniej. Albo można użyć:
Kod: C / C++
To przeniesie klawiaturę na pierwszy plan:
Teraz można zająć się obsługą samego przycisku. Zaprogramujemy to, co się stanie w momencie zdarzenia-kliknięcia w przycisk.
Najpierw jednak musimy wyjąć zmienne z funkcji, dla uproszczenia utworzę po prostu je jako zmienne globalne.
Kod: C / C++
Potem możecie sobie to upakować wedle uznania do klasy, albo ewentualnie zostawić jako globalne tylko jakoś to oznaczyć, lepiej nazwać, może "g_fieldLogin"?
Nas bardziej interesuje obsługa kliknięcia. Usuwamy "komentarz" z funkcji ustawiającej event i bierzemy się za jej implementację:
Kod: C / C++
Najpierw pobieramy wpisane napisy do pól, czyli to, co podał użytkownik:
Kod: C / C++
Potem, w ramach demonstracji, sprawdzamy czy login to "ele" a hasło to "12". Normalnie tutaj byłoby nieco inne sprawdzenie, może zapytanie HTTP do serwera przez API?
Kod: C / C++
Ostatecznie, zależnie od poprawności danych, wyświetlamy błąd lub sukces. Można tu też dać przejście do innego ekranu.
Kod: C / C++
W sumie to można by jeszcze kolorować tekst... w ten sposób komunikat o błędzie może być na czerwono, a komunikat o sukcesie będzie na zielono. Też jest do tego osobna funkcja:
Kod: C / C++
Pora sprawdzić naszą pracę. Rezultat:
Hasło i login są poprawnie sprawdzane. Pora wdrożyć drugi ekran.
Można to zrealizować na różne sposoby, ale ja założyłem, że przy przełączaniu zwalniam pamięć starego ekranu i tworzę drugi na nowo. Nie można niszczyć istniejącego ekranu (aktywnego), więc najpierw tworzę nowy, aktywuję go, a potem niszczę stary. W sumie pewnie można by oba też trzymać w pamięci i przełączać, też by było okej, jedyną zła opcją jaką można tu obrać jest tworzenie kolejnych ekranów bez zwalniania poprzednich, bo w ten sposób szybko skończy się na pamięć.
Kod: C / C++
W tym konkretnym miejscu tworzymy nasz drugi ekran, ekran powitalny po logowaniu:
Kod: C / C++
Swoją drogą spodobała mi się funkcja lv_label_set_text_fmt - od razu wspiera ona formatowanie tekstu, tak jak printf. Można wygodnie ustawiać tekst dla obiektu typu label.
Reszta tak jak wcześniej:
Kod: C / C++
Sprawdźmy działanie logowania, tym razem na filmie:
Jeszcze możemy nieco rozwinąć nasz przykład i zademonstrować wertykalne przewijanie w ekranie po zalogowaniu. Dodajmy nieco więcej tekstów oraz upewnijmy się, czy włączona jest flaga LV_OBJ_FLAG_SCROLLABLE.
Kod: C / C++
Dla wygody teksty dodamy w pętli, powiedzmy, że będzie ich 50.
Kod: C / C++
Nie podałem tu wysokości panelu - ona sama się dostosuje do wymogów tego co jest w środku.
Została jeszcze reszta kodu, to z tym przyciskiem do wylogowania:
Kod: C / C++
Oto końcowy rezultat na filmie:
Z góry przepraszam za "brak responsywności" na filmach, to nie kwestia kodu, mogłem dla większej precyzji operować rysikiem.
Podsumowując, LVGL oferuje wygodne, gotowe mechanizmy do obsługi pól tekstowych oraz wprowadzania do nich danych. Wystarczy kilka linijek kodu by uruchomić dotykową klawiaturę do złudzenia przypominającą popularne urządzenia mobilne. Wprowadzanie danych też odbywa się automatycznie, a my potem możemy dowolnie je przetwarzać, np. zrealizować w oparciu o to formularz logowania.
Przy okazji w tym temacie też poćwiczyliśmy tworzenie interfejsów z poziomu kodu, bez udziału SquareLine Studio, co zasadniczo pod wieloma względami dla mnie okazało się prostsze niż wcześniej prezentowany sposób oparty o edytor wizualny... ale na ten moment obie metody macie opisane, każdy wybierze wedle własnego uznania.
Przedstawiony tu projekt można pociągnąć dalej i zrobić w oparciu o niego jakiś zabezpieczony hasłem panel dostępu do ustawień inteligentnego domu lub do jakiejś maszyny, można by też spróbować zrobić klienta jakiegoś prostego komunikatora który by chodził w pełni na ESP, może np. klienta GG?
A jak Wy byście wykorzystali pokazany tu system wprowadzania/klawiatury?
Zapraszam do komentowania.
Fajne? Ranking DIY Pomogłem? Kup mi kawę.