Graficzny interfejs użytkownika w pythonie dla noki ma dużo większe możliwości niż tylko rysowanie prostych figur typu elipsa czy kwadrat, pozwala między innymi na wczytanie obrazu z pliku. Wyobraźmy sobie jaką dzięki temu możemy stworzyć grafikę np dla przełączników, potencjometrów, kontrolek itp. Myślę że przydadzą się podstawowe informacje z tego zakresu więc omówię teraz pracę na plikach graficznych. Nie trudno zgadnąć od czego zaczniemy, od podstawowej wersji skryptu z interfejsem użytkownika typu graficznego
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Używając grafiki w której będzie następowało nakładanie na siebie obrazów i cykliczne ich przemieszczanie lub zamienianie musimy pomyśleć o szybkości z jaką będzie wykonywane odrysowywanie całego wyświetlacza, w wielu przypadkach będziemy widzieli efekt migotania przy czyszczeniu ekranu i nakładaniu na nim nowego zestawu grafik. Żeby tego uniknąć ja używam rysowania w pamięci i kiedy mam gotowy obraz to po prostu wrzucam go na ekran nadpisując ten który jest obecnie wyświetlony. Przy takim rozwiązaniu pozbywam się zupełnie zjawiska migotania. Zanim jednak przedstawię sposób jak tego dokonać to wykonamy najpierw prostą czynność jaką jest wczytanie pliku graficznego i wyświetlenie go na ekranie
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Utworzyliśmy zmienną loco do której został przypisany plik graficzny znajdujący się na karcie pamięci w katalogu python czyli tam gdzie jest nasz skrypt, lokalizacja może być dowolna, ja jednak trzymam grafikę dla skryptu tam gdzie mam skrypt. W funkcji odswiezanie został nałożony obraz zmiennej loco na wyświetlacz zaczynając od górnego lewego brzegu ekranu. Teraz utworzymy ten sam obraz w pamięci i nałożymy go na ekran
język pascal
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Efekt powinien być taki sam tzn wyświetli nam się plik graficzny na ekranie, różnica jest taka że plik graficzny został narysowany w pamięci i potem nałożony został na wyświetlacz. Utworzyliśmy zmienną bufor którą możemy traktować jak nowy wyświetlacz ale taki który istnieje tylko w pamięci telefonu i na nim możemy wykonywać wszystkie operacje graficzne jak na wyświetlaczu tym który mamy fizycznie w telefonie. Skoro znamy taki sposób to możemy wykorzystać to do poruszania lub zmieniania obiektu graficznego i nie powinniśmy zaobserwować żadnego efektu migotania przy odrysowywaniu pliku graficznego na nowej pozycji. Dopiszmy więc obsługę przycisków kierunkowych dżoja i przy okazji wymuszenie orientacji ekranu, po naciśnięciu przycisku kierunkowego powinien poruszać się plik graficzny w odpowiednim kierunku
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Utworzyliśmy zmienne xloco i yloco które będą przechowywały współrzędne położenia loco w bufer. Zależnie od naciśniętego przycisku kierunkowego dżoja zmieniamy te współrzędne i tworzymy nowy obraz w pamięci, kiedy obraz jest gotowy to wywołujemy funkcję odświeżenia ekranu gdzie nakładany jest obraz bufor na nasz wyświetlacz. Proszę zwrócić uwagę że naciskając np lewy przycisk dżoja zwiększamy zmienną xloco zamiast domyślnie ją zmniejszać jeśli chcemy żeby obraz poruszał się w lewą stronę. Przy wykonywaniu nakładania obrazu górny lewy brzeg ekranu ma współrzędne 0,0 i poruszając się do środka ekranu nie dodajemy tylko odejmujemy współrzędne, więc w moim przypadku jeśli mam wyświetlacz o rozdzielczości 320x240 to ostatnie wartości współrzędnych będą równe -320 i -240. Mamy już podstawową wiedzę o technice nadawania ruchu wyświetlonej grafice z pliku, proszę sobie wyobrazić jakie można byłoby tworzyć fajne ślizgacze dla potencjometrów, im bardziej wybujała wyobraźnia tym ciekawszy będzie interfejs bo tylko wyobraźnia ogranicza programistę. Oprócz zwykłego wyświetlenia pliku graficznego python daje nam możliwość rotacji tego obrazu w 90, 180 i 270 stopniach i przerzuceniu w poziomie i pionie, czasem to bardzo przydatna rzecz. Wykonamy teraz skrypt w którym po naciśnięciu któregoś z przycisków kierunkowych dżoja będziemy obracać i przewracać nasz obrazek
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jeszcze jedna podstawowa możliwość to rozciągnie obrazu, python umożliwia rozciąganie w trybach z zachowniem proporcji lub bez ich zachowania
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Widzimy że obrazek wychodzi poza widzialny obszar wyświetlacza mimo że ustawiliśmy rozciągnie dokładnie do jego całej wielkości. Dzieje się tak dlatego że mamy widoczne belki górną i dolną czyli interfejs jest w trypie normal. Górna belka przesuwa wyświetlacz ku dołowi ale nie zmienia jego wielkości więc mamy mniej widoku dolnej części wyświetlacza o tyle ile wysoka jest górna belka, dodatkowo mamy widoczną dolną belkę więc jeszcze bardziej zmniejszony obszar widoczności dolnej części wyświetlacza. Jeśli chcemy mieć pełną widoczność wyświetlacza to powinniśmy zastosować tryb ekranu full bez górnej i dolnej belki. W kodzie widać że zmienna loco jest kopią zmiennej img. W zmiennej img przechowywany jest obraz z pliku i pozostaje on nie zmieniany żebyśmy nie musieli ładować tego pliku od początku przy każdej operacji rozciągnia, w funkcji obsługi dżoja do zmiennej loco przypisujemy kopię zmiennej img i od razu rozciągamy obraz w odpowiedni sposób. Spróbujmy teraz wykonać jakiś bardziej praktyczny przykład budowy interfejsu z obsługą dżoja. Zaczniemy od przygotowania sobie tła które u mnie będzie drewnianym stołem i jakąś jedną strzałkę skierowaną w górę, wszystkie pliki graficzne których używam znajdują się w załączniku
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Stworzyliśmy zmienne do przechowywania obrazów tła i strzałki oraz zmienne które są kopiami obrazu strzałki z rotacją w odpowiednim kierunku. Układając strzałki na wyświetlaczu podzieliliśmy go na 20 części żeby było łatwiej je układać i robić to w sposób uniwersalny dla różnych wielkości wyświetlacza. Widzimy że strzałki ułożyły się fajnie ale są przesunięte w prawo mimo że miało być na środku. Obrazy rysowane są od górnego lewego rogu w prawą stronę w dół i patrząc na górną strzałkę widać że jest ona położona tą krawędzią na środku ale nie jest to środek samej strzałki. Trzeba więc poprawić obrachunki uwzględniając rozmiar obrazu strzałek czyli pobrać wielkość obrazka strzałki
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Strzałki są już wyśrodkowane w poziomie, utworzyliśmy zmienną polowa do której zapisujemy połowę szerokości obrazu strzałki i tą zmienną używamy w określaniu położenia poziomego wszystkich strzałek. Było możliwe użycie tylko jednego wymiaru ponieważ wszystkie strzałki są takie same i mają tą samą wysokość i szerokość przez co po ich rotacji ciągle zmienna polowa przechowuje prawdziwą połowę ich szerokości. Byłoby fajnie jakby jeszcze nie bylo widać czarnego tła na strzałkach. Da się pozbyć tego tła na zasadzie stworzenia maski. Określając maskę musimy powiedzieć pythonowi jaki kolor ma być maską, ja stosuję do tego automat który pobiera samodzielnie kolor z obrazu z pierwszego górnego lewego piksela
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Całkiem nam to ładnie wyszło, teraz do obsługi przycisków dodamy zdarzenia które wizualnie pokażą nam że przycisk jest naciśnięty. Możemy to zrobić na dwa sposoby, pierwszy to taki że będziemy rysować np elipsę która otacza odpowiednią strzałkę lub elipsę która będzie znajdowała się pod strzałką co może dać ciekawy efekt. Drugi sposób to taki że wczytujemy jeszcze jeden plik graficzny, obracamy tworząc jego kopie w czterech rotacjach i będziemy go podstawiali w miejsce strzałki która oznacza naciśnięty przycisk dżoja. Spróbujmy najpierw ten pierwszy sposób
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Wygląda ciekawie, teraz spróbujemy ten drugi sposób czyli podstawianie innego pliku graficznego, ja wykonam to tak że będzie to taka sama strzałka ale w innym kolorze
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Ze względu na to że użyliśmy tych samych strzałek tylko w innym kolorze to nie musieliśmy tworzyć dla nich nowej maski i mogliśmy korzystać z maski która została utworzona dla pierwszych strzałek. W funkcji skanowania klawiatury zostaje odrysowywany cały obraz i zależnie od przycisku kierunkowego dżoja nakładny jest obraz odpowiedniej strzałki. Zrobimy jeszcze jeden fajny skrypt tym razem z potencjometrem ale żeby było ciekawiej to z potencjometrem obrotowym, zaczynamy od podstawowej wersji interfejsu graficznego z nałożonym obrazem tła i jakimś pokrętłem, dla intuicji dodamy strzałki do obsługi potencjometru
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Dopiszmy obsługę strzałek, kiedy naciśniemy dżoja to strzałki zmienią kolor
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jak teraz pokazać graficznie że obracamy potencjometrem, wiemy że python umożliwia nam rotację tylko w czterech kierunkach a my potrzebujemy płynnej rotacji. Ja do tego stosuję geometrię i ruch po okręgu, idea polega na tym że nie obracam całym kołem tylko przemieszczam się po jego krawędzi, w naszym przypadku wędrującym po kole będzie znacznik pokrętła i da nam to wrażenie obrotu. Naszym znacznikiem niech będzie małe czerwone kółeczko które w pokrętle pełni rolę diody led. Taką diodę także stworzymy z pliku graficznego
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Musimy teraz obliczać sobie ruch tej diody, jak korzystam z takiego wzoru
Kod:
polozenie_x = promien_kola * cos( (2 * PI/360) * kąt ) + srodek_kola_x
polozenie_y = promien_kola * sin( (2 * PI/360) * kąt ) + srodek_kola_y
język python
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Nieznacznie uległ zmianie sposób odświeżania grafiki, trzeba tutaj było zrobić tak żeby po przyciśnięciu i trzymaniu dżoja w górę lub w dół zobrazować to zmieniając kolor strzałki i jednocześnie zmieniać wartości współrzędnych dla naszej wędrującej po okręgu diodzie led. Wiemy że w chwili nacisnięcia dżoja wywoływana jest tylko raz funkcja skanowania klawiatury dlatego utworzyliśmy zmienną przycisk do której zostaje zapisana informacja o naciśnięciu dżoja, trzymając naciśnięty dżoj pracuje dla nas funkcja ekran do której dodaliśmy zmianę wartości zależnie od tego który przycisk dżoja jest naciśnięty. Ufff to tyle jeśli chodzi o rozszerzone możliwości interfejsu użytkownika typu graficznego, python ma jeszcze dużo innych rzeczy ale to już wykracza poza nasz temat którym było sterownie bluetooth, omówiliśmy to co było ważniejsze i może się przydać w czasie budowy interfejsu opartego na grafice.
Zamknęliśmy okrągły tydzień od kiedy poznawalismy pythona dla noki, myślę że po tym tygodniu każdy potrafi sobie zaprojektować fajny interfejs do sterowania modułem bluetooth i zrobić to w sposób przemyślany, dopasowany do założeń całego projektu. Następnym razem pogadam któtko o obsłudze wyświetlacza dotykowego, o czujnikach ruchu, podpowiem parę ciekawych sztuczek i na tym będziemy kończyć ten artykuł.
Edit: Screeny z postu zostały przeniesione na serwer forum