Skocz do zawartości

getTextBounds - proszę o pomoc w napisaniu funkcji


Roberttar

Pomocna odpowiedź

Cześć

Nie mam pomysłu jak napisać funkcje, która by "odświerzała" wartości zmiennych na wyświetlaczu.

Mam kilka wartości zmiennych typu float (temperatury, wilgotność, ciśnienie, CO2, itp)

Potrzebuje funkcji, która by wyświetlała te wartości na wyświetlaczu.

Teraz mam to zrobione tak że podkładam prostokąt tft.fillRect o odpowiednich wymiarach, które ustaliłem doświadczalnie. Nie jest to najlepsza metoda bo ruszenie jednej pozycji na wyświetlaczu wymusza grzebanie i przerabianie wymiarów wszystkich pozostałych prostokątów.

Dzisiaj zobaczyłem że biblioteka arduino ma wbudowana funkcję getTextBounds. Nie wiem jak jej użyć aby była uniwersalna dla wszystkich wyświetlanych zmiennych.

Dopiero zaczynam programowanie a brak tej funkcji bardzo utrudnia mi dalszą pracę nad programem.

Jeżeli jest to skomplikowane to chętnie zapłacę za napisanie fragmentu kodu, który by mi to ogarnął.

Link do komentarza
Share on other sites

Poniżej wklejam fragment kodu jak to do tej pory zrobiłem. Nie wiem jak wyliczyć zmienne int x i int y.

Nie rozumiem funkcji getTextBounds 😞

float t_czerpnia2 - temperatura pobrana. 

void odswierzanie (float dane, int x,int y){
  int16_t x1, y1;
  uint16_t w, h;

  char result[8];
  dtostrf(dane, 6, 1, result); //zamiana na char z 1 miejscem po przecinku
  Serial.print(result);

  tft.setFont(&FreeSansBold9pt7b);
  tft.setTextSize(1);
  tft.getTextBounds(result, x, y, &x1, &y1, &w, &h);
  tft.print(result);
}

void wyswietlanie_temperatur(void) {
  // ******************** temperatury
 
  tft.setFont(&FreeSans9pt7b);
  tft.setTextSize(1);

  tft.setCursor(4, 35);
  tft.print("CZERP: ");
  //odswierzanie (float dane, int x, int y);  
  odswierzanie (t_czerpnia2, 35, 35);

Tak wygląda mój wyświetlacz. Te kolorowe pola to fillRectangle, które służą do odświeżania zawartości. pokolorowałem aby się w nich nie pogubić.

20210131_201929.thumb.jpg.19f1273195d3b382c3407d9eb98b15f8.jpg

image.png

Link do komentarza
Share on other sites

A na pewno masz kursor ustawiony tam, gdzie trzeba?

Co w stylu:
 

int x1,y1,w,h;
tft.getTextBounds(tekst,x,y,&x1,&y1,&w,&h);
tft.fillRect(x1,y1,w,h,kolorek);
tft.setCursor(x,y);
tft.print(tekst);

Zadziała, o ile tekst będzie stałej długości.

 

Link do komentarza
Share on other sites

Ale jak obliczyć x i y? Właśnie tu nie wiem jak do tego podejść. Jeszcze w pionie to nie ma problemu bo ustawiam sobie tekst w wierszach i podaje na którym pikselu będzie się zaczynał. Gorzej z "y" bo tam się zmienia i długość tekstu i wartość zmiennej.

Jak wywołuje funkcję odswierzanie zaraz po wyświetleniu tft.print("CZERP: "); to kursor powinien być na właściwej pozycji... tak mi się wydaje. Dopiero zaczynam zaczynam z wyświetlaczem tft.

Chociaż docelowo chciał bym uzyskać to że podaje tylko x i y całości wyrażenia (czyli "CZERP: xx.x") a odświeża mi się tylko zawartość zmiennej xx.x.

Całe popołudnie spędziłem żeby to ogarnąć i nic mądrego nie wymyśliłem.

Jutro zobaczę ten przykład, który napisałeś. Ale to raczej nie rozwiąże problemu bo zmienna może mieć różną długość bo to wskaźnik temperatury i może mieć wartości ujemne i dodatnie od -15stC do + 40stC.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

20 minut temu, Roberttar napisał:

Ale jak obliczyć x i y?

Przecież tego nie liczysz, tylko podajesz do setCursor (patrz fragment z mojego poprzedniego posta). Jak masz wypisać wartość na pozycji (35,40) to chyba jasne, że podajesz 35 i 40, prawda? A jeśli koniecznie musisz wypisywać teksty tam gdzie akurat kursor stoi - może zamiast pytać o każdą funkcję zajrzysz do pliku który masz na dysku (libraries/Adafruit_GFX_Library/Adafruit_GFX.h czy jakoś tak) i popatrzysz, jakie tam masz metody i co robią? Bo za chwilę obwieścisz całemu światu że dokonałeś wiekopomnego odkrycia, mianowicie że istnieją metody getCursorX i getCursorY... a przecież jest to w tym pliku bardzo ładnie opisane.

20 minut temu, Roberttar napisał:

zmienna może mieć różną długość bo to wskaźnik temperatury i może mieć wartości ujemne i dodatnie od -15stC do + 40stC.

No to co? Robisz to na jakimś Uno czy ESP? Bo jeśli ESP to sprintf Twoim przyjacielem. Jeśli na Uno to w sumie też możesz użyć sprintfa tylko to wymaga nieco lawirowania.

Poza tym ja unikam jak ognia czcionek proporcjonalnych, bo z nimi zawsze jakieś problemy przy wyświetlaczach.

 

Edytowano przez ethanak
Link do komentarza
Share on other sites

Bardzo dziękuje za tą podpowiedź. Dzięki tej podpowiedzi udało mi się z grubsza ogarnąć odświeżanie :).

Mam kolejny problem, którego nie mogę przeskoczyć. Chodzi o przesyłanie argumentu "suffix" do funkcji. Nie mogę go przesłać jako char. Udało mi się przesłać wstawiając jako argument, który przyjmuje funkcja const char* suffix.

Działa, ale nie do końca poprawnie. Suffix nie jest odświeżany :(. Chciał bym skleić ze sobą wartość + suffix ale czego bym nie próbował to zawsze dostaje od kompilatora że niepoprawny typ zmiennych. Rozumiem że nie można ze sobą połączyć char i wskaźnika char.

Nie potrafię przesłać do zmiennej łańcucha char (bez wskaźnika)

Poniżej fragment kodu.

void odswierzanie (float dane, int x,int y, int kolor, const char * suffix){
  int16_t x1, y1;
  uint16_t w, h;

  char tekst[8];
   dtostrf(dane, 6, 1, tekst); //zamiana na char z 1 miejscem po przecinku  
  tft.getTextBounds(tekst,x,y,&x1,&y1,&w,&h);
  tft.fillRect(x1,y1,w,h,kolor);
  tft.setCursor(x,y);
  tft.setFont(&FreeSansBold9pt7b);
  tft.setTextSize(1);
  tft.print(tekst);

  int x2 = tft.getCursorX ();
  int y2 = tft.getCursorY ();
  tft.getTextBounds(suffix,x2,y2,&x1,&y1,&w,&h);
  tft.fillRect(x1,y1,w,h,kolor);
  tft.setCursor(x2,y2);
  tft.setFont(&FreeSans9pt7b);
  tft.setTextSize(1);
  tft.print(suffix);  
}

void wyswietlanie_temperatur(void) {
  int x, y;
  // ******************** temperatury
  tft.setFont(&FreeSans9pt7b);
  tft.setTextSize(1);
  tft.setCursor(4, 35);
  tft.print("CZERP: ");
  x = tft.getCursorX ();
  y = tft.getCursorY ();  
  odswierzanie (t_czerpnia2, x, y, ILI9341_MAGENTA, "stC");

 

Link do komentarza
Share on other sites

19 minut temu, Roberttar napisał:

nie można ze sobą połączyć char i wskaźnika char

Oczywiście że nie. Pomijając fakt, że w rzeczywistości chodzi Ci o wskaźnik na char i wskaźnik na char a nie char i wskaźnik - wskaźnik to po prostu miejsce w przestrzeni pamięci, a sklejanie miejsc (pomijając napęd warp w Enterprise) niespecjalnie dobrze wychodzi. To tak jakby stacja benzynowa była na piętnastym kilometrze, bar na trzydziestym pierwszym - nijak nie ma jak połączyć piętnaście z trzydzieści jeden żeby wyszła stacja benzynowa z barem 😞

Wspominałem o sprintf?

sprintf(bufor,"%6.2f%s", zmienna, suffix); // jeśli Twój sprintf obsługuje floaty

 

25 minut temu, Roberttar napisał:

Nie potrafię przesłać do zmiennej łańcucha char (bez wskaźnika)

Ja też nie - jako że ów "łańcuch char" to w rzeczywistości wskaźnik, zrobienie wskaźnika bez wskaźnika przekracza moje skromne umiejętności 😞

Alternatywa: użyć String. Te sobie możesz dodawać i sklejać jak chcesz i z czym chcesz, ale zwykły sprintf daje dużo więcej możliwości formatowania.

Aha, i zanim zadasz następne pytanie naucz się co to jest char, czym się różni od char * i ogólnie zacznij używać nazw typów prawidłowo a nie jak popadnie.

Link do komentarza
Share on other sites

Nadal nie rozumiem :(. Program piszę dla ESP, więc obsługuje sprintf.

zmienna - to to co chcę wyświetlić w tft.print(zmienna);

bufor - char bufor;

suffix - tą wartość przesyłam do funkcji.

jeżeli tak to zrobię nadal nie mam odpowiednich typów zmiennych.

Jestem pogubiony w tych tablicach char :(. nie mogę ustawić zmiennej typu string dla suffix

jeżeli zrobię tak:

void odswierzanie (float dane, int x,int y, int kolor, string suffix){

}

tonie działa.

Funkcja odświeżania:

void odswierzanie (float dane, int x,int y, int kolor, const char * suffix){
  char bufor;
  char zmienna;
  sprintf(bufor,"%6.2f%s", zmienna, suffix);
  tft.print(zmienna);
}

funkcja temperatur:

void wyswietlanie_temperatur(void) {
  int x, y;
  // ******************** temperatury
  tft.setFont(&FreeSans9pt7b);
  tft.setTextSize(1);
  tft.setCursor(4, 35);
  tft.print("CZERP: ");
  x = tft.getCursorX ();
  y = tft.getCursorY ();  
  odswierzanie (t_czerpnia2, x, y, ILI9341_MAGENTA, "stC");
}

 

Link do komentarza
Share on other sites

Zaczniesz wreszcie odróżniać:

  • string (z std C++, zapomnij na razie o jego istnieniu)
  • String (z Arduino)
  • char
  • char *
  • char []
  • char * []

Dopóki tego nie ogarniesz będziesz mógł liczyć na przypadek (że przypadkowo wciśniesz kilkaset klawiszy w losowej kolejności i wyjdzie Ci program). A ja nawet nie mam jak pomóc bo nie rozumiesz języka w którym do Ciebie piszę 😞

Ja naprawdę chcę pomóc, ale dopóki się nie zaczniemy rozumieć jest to po prostu niewykonalne. A nie będę tu wykładał podstaw języka, które można znaleźć w dowolnym kursie Arduino, C czy C++.

Link do komentarza
Share on other sites

Zmieniłem i wysyłam suffix w stringu. Teraz wygląda to tak jak poniżej. Jednak nie działa :(.

Nie mogę połączyć 2 tablic char.

void odswierzanie (float dane, int x,int y, int kolor, String suffix){
  int16_t x1, y1;
  uint16_t w, h;

  char suffix2[3];
  strcpy(suffix2, suffix.c_str());

  char tekst[8];
   dtostrf(dane, 6, 1, tekst); //zamiana na char z 1 miejscem po przecinku  
   char tekst2[] = {tekst[8] , suffix2[3]};
  tft.getTextBounds(tekst2,x,y,&x1,&y1,&w,&h);
  tft.fillRect(x1,y1,w,h,kolor);
  tft.setCursor(x,y);
  tft.setFont(&FreeSansBold9pt7b);
  tft.setTextSize(1);
  tft.print(tekst2);
  Serial.print(tekst2);
}

 

16 godzin temu, ethanak napisał:

Dopóki tego nie ogarniesz będziesz mógł liczyć na przypadek (że przypadkowo wciśniesz kilkaset klawiszy w losowej kolejności i wyjdzie Ci program). A ja nawet nie mam jak pomóc bo nie rozumiesz języka w którym do Ciebie piszę 😞

Ja naprawdę chcę pomóc, ale dopóki się nie zaczniemy rozumieć jest to po prostu niewykonalne. A nie będę tu wykładał podstaw języka, które można znaleźć w dowolnym kursie Arduino, C czy C++.

Dziękuje za porady. Na pewno się przyłożę aby zrozumieć jakie są różnice  w char. Dopiero zaczynam więc prosze o wyrozumiałość. Czytam i oglądam różne kursy, czytam Symfonia C++. Kiedyś coś tam programowałem w Basic, jeszcze na Atari i Commodore 🙂 ale teraz ten język obiektowy jakoś nie mogę go zatrybić.

Przy okazji nauki próbuje napisać jakiś konkretny, praktyczny program, który mi się do czegoś przyda. Chociaż robię też zadania z kursów.

Link do komentarza
Share on other sites

31 minut temu, Roberttar napisał:

Nie mogę połączyć 2 tablic char.

Pisałem coś o barach, stacjach benzynowych i kilometrach? Nie możesz i nie będziesz mógł. Tablica to nic innego jak wskaźnik, czyli adres, a adresów się raczej zgrać do kupy nie da. Jak Ziutek mieszka w małym domku na Grzybowej 17, a Grażyna na Rosolnej 4 to żebyś nie wiem jak grzyby do rosołu wsypywał i numerki dodawał nie sprawisz, że nagle oba domki połączą się w jeden większy...

Pokazywałem przykład ze sprintf? Nie chcesz - to nie. Ale w ten sposób daleko nie zajdziesz, jak będziesz na pałę wymyślał jakieś własne konstrukcje języka z nadzieją, że któraś z nich jest prawidłowa.

A co do zrozumienia... na razie próbujesz napisać wierszyk, przy czym naukę literek odkładasz na później. Zostaw ten program w spokoju, weź się za kurs Arduino, jak przynajmniej pierwszą część zaliczysz to wrócisz i sam się będziesz śmiać jak zobaczysz, jakie bzdury próbowałeś wypisywać. A wtedy pogadamy o programie.

 

Link do komentarza
Share on other sites

Faktycznie dużo jeszcze nie potrafię w tym języku. Codziennie się uczę. Kursy "przerobiłem" w większości. Szkoda że na kursach, które są dostępne w internecie nie wszystko jest dobrze wyjaśnione. Nie znalazłem materiału, który wyjaśni mi różnice miedzy char, char*, char[], char*[]. Może faktycznie za słabo i za krótko szukałem. Wydawało mi się że po kursach ogarnę większość właściwego programu lecz natknąłem się po napisaniu prawie 1000 linii kodu na problem, którego nie potrafię rozwiązać.

Nie używałem wcześniej zmiennych char i tablic powiązanych z tą zmienną. Do tekstów używałem String.

Napisałem 4 posty wyżej że próbowałem użyć tego kodu co podesłałeś. Jednak coś namieszałem w typach zmiennych i wskaźnikach.

Muszę to sobie na spokojnie ogarnąć.

Dlatego proszę jeśli możesz mi pomóc i napisać jak to powinienem w kodzie napisać, łącznie z podaniem typów zmiennych to pomóż. Ja na pewno nie odpuszczę tematu i dokształcę się odnośnie tablic char.

Link do komentarza
Share on other sites

4 minuty temu, Roberttar napisał:

Dlatego proszę jeśli możesz mi pomóc i napisać jak to powinienem w kodzie napisać, łącznie z podaniem typów zmiennych to pomóż. Ja na pewno nie odpuszczę tematu i dokształcę się odnośnie tablic char.

Nie, nie w tej kolejności. Najpierw będziesz znał wszystkie typy języka C (C++ na razie odpuśćmy). Mogę co najwyżej pokazać przykładową funkcję, ale nie będzie to żaden gotowiec.

// dla czcionek monospace, dla innych nie zadziała!
// dlaczego?

void wypisz(int x, int y, float ile, const char *czego)
{
    char bufor[16];
    int x1, y1, w, h;
    sprintf(bufor,"%5.1f %s", ile, czego);
    // jeśli ustawiasz czcionki, wielkości i takie tam
    // to najpóźniej tutaj
    tft.getTextBounds(bufor, &x1, &y1, &w, &h);
    tft.fillRect(x1,y1,w,h,KOLOR_TLA);
    tft.setCursor(x,y);
    tft.print(bufor);
    
}

// wywołanie gdzieś w kodzie, :

    float temp = cośtam costam;
    tft.setTextColor(KOLOR_TEKSTU);
    tft.setFont("fajnaCzcionkaMono");
    wypisz(50,25,temp," C");

Nie sprawdzałem, ale chyba jest prawidłowo (mogłem pomylić nazwy metod ale to sobie poprawisz).

I nie wracaj dopóki nie będziesz wiedział co oznacza każda linijka! 🙂

 

 

Link do komentarza
Share on other sites

Dziękuje za podpowiedź. Jestem już poza warsztatem. Jutro wstawię ten kod i dostosuje go do swoich potrzeb.

Między czasie na szybko obkomentowałem opisując co każda linia "robi"

void wypisz(int x, int y, float ile, const char *czego) // tworzy funkcje wypisz z argumentami: integer x,y, float - ile i stałą tablicą jednowymiarową ze wskaźnikim na początek tej tablicy bez podania ilości elementów
{
    char bufor[16]; //zmienna bufor, tablica 16 elementów
    int x1, y1, w, h; //zmienne integer
    sprintf(bufor,"%5.1f %s", ile, czego);  // tworzy łańcuch (tablicę) w zmiennej bufor 
                                            //%5.1f podstawia ciąg znaków ze zmiennej ile
                                            //formatowanie 5 znaków i jedno miejsce dziesiętne dopełnione zerem
                                            //kolejnye wyrażenie %s podsyawia ciąg znaków ze zmiennej czego
  // jeśli ustawiasz czcionki, wielkości i takie tam
  // to najpóźniej tutaj
    tft.getTextBounds(bufor, &x1, &y1, &w, &h);//wywołanie pobiera minimalny obszar jaki zajmuje wyświetlany tekst ze zmiennej
                                                //nie wiem dlaczego są używane referencje
                                                //zmienne określają lewy górny róg kursora i szerokość oraz wysokość
    tft.fillRect(x1,y1,w,h,KOLOR_TLA); // wywołanie rysujące prostokąt o parametrach
                                        // pobranych przez getTextBounds
                                        //nadal nie rozumiem dlaczego przed zmiennymi jest &
                                        // przecież do tego czasu te zmienne nie zostały by zmienione

    tft.setCursor(x,y);// ustawia kursor na pozycji x,y
    tft.print(bufor); //drukuje zawartość zmiennej bufor
    
}

// wywołanie gdzieś w kodzie, :

    float temp = cośtam costam; // zmienna typu float - ułamek, 7 miejsc po przecinku
    tft.setTextColor(KOLOR_TEKSTU); //wywołanie ustawiające kolor 
    tft.setFont("fajnaCzcionkaMono"); // wywołanie ustawiające czcionkę
    wypisz(50,25,temp," C"); // wywołanie funkcji wypisz z argumentami

 

Link do komentarza
Share on other sites

21 minut temu, Roberttar napisał:

nie wiem dlaczego są używane referencje

To nie są referencje tylko wskaźniki (w C++ to dwie zupełnie różne rzeczy). A dlaczego? Bo funkcja musi zwrócić cztery wartości (położenie i wielkość).

Załóżmy, że chcesz mieć funkcję zwracającą np. iloraz i resztę z dzielenia. Wyobraź sobie coś takiego:
 

void podziel(int x, int y, int iloraz, int reszta)
{
	iloraz = x / y;
	reszta = x % y;
}

I teraz spróbujmy to wywołać:

podziel(7,3,iloraz,reszta);

I co? I nic. Wartości zmiennych iloraz i reszta zostały przekazane do funkcji, funkcja zmieniła sobie te wartości... o, słowo kluczowe: sobie. Bo w żaden sposób wynik jej szlachetnej działalności nie został udostępniony światu. Równie dobrze moglibyśmy napisać:

podziel (7,3,100,101);

i na 100% 100 pozostanie nadal setką i nie zmieni się magicznie na dwa 🙂 [1]

Czyli jak to zrobić? spróbujmy inaczej:

void podziel(int x, int y, int *iloraz, int *reszta)
{
  *iloraz = x / y;
  *reszta  x % y;
}

I wywołujemy:

podziel(7, 3, &iloraz, &reszta);

Bardzo podobnie - tylko zamiast wartości "iloraz" i "reszta" przekazujemy adresy, pod którymi kryją się te zmienne. A funkcja po prostu umieszcza wyniki pod tymi adresami.

Tak więc po powrocie z funkcji zmienne będą miały nowe wartości.

Czy to jasne?

---

[1] Ciekawostka: kto wie, w jakim języku programowania 100 stanie się w takiej sytuacji nagle dwójką?

 

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.