2009-05-30 10 views
5

Chcę narysować wykres, który aktualizuje się w czasie rzeczywistym (rośnie od prawej). Najskuteczniejszym sposobem na zrobienie tego byłoby skopiowanie wszystkiego z x [0 .. width-2] pozostawionego przez 1 piksel, a następnie narysowanie nowej wartości na x [szerokość-1].Android: Skuteczne przewijanie zawartości płótna?

Mam niewielkie doświadczenie z Androidem, ale z tego, co mogę powiedzieć, Canvas nie działa na jego zawartości. Czy za każdym razem muszę przemalować cały ekran? To wymaga skalowania i wygładzania, więc martwię się, że będzie wolno.

Czy powinienem narysować bajt [] [], a następnie użyć tego do namalowania na ekranie (przesuwając zawartość mojego bufora za każdym razem)?

+0

Myślę, że widzę możliwe podejście przy użyciu Bitmap, getPixels i setPixels. Nie jestem pewien, czy to złe podejście, ale robię to. Proszę doradź! –

Odpowiedz

0

Po prostu myśl, którą być może już rozważałeś, ale nie przesuwałbym zawartości bufora - spróbowałbym użyć jej jako okrągłego bufora. Zachowaj indeks do bieżącej kolumny, a po zawinięciu do lewej kolumny ponownie możesz narysować do miejsca docelowego w dwóch segmentach - co znajduje się po prawej stronie bieżącej kolumny, a następnie po lewej stronie, w tym ostatnio wypełniona kolumna. W ten sposób nie będziesz musiał niczego przesuwać, a każde odświeżenie ekranu to tylko dwa blity (kopie bitmapowe) dla dwóch segmentów. Jeśli ten bit jest zbyt wolny, nadal można go zawsze zamalować na drugi bufor poza ekranem, zanim za jednym zamachem wszystko zostanie zesłane na ekran. Z pewnością jedna duża plama na ekranie jest dość szybka, nie?

+0

Również coś, o czym zapomniałem wspomnieć (co znowu można uznać za oczywiste, ale nie wiem, co wiesz, więc wybacz mi) - Upewniam się, że obraz/obrazy bufora są/są inicjowane w celu dopasowania do rozmiaru obszaru ekranu, na którym chcesz rysować, i przeskaluj trochę wykresu graficznego, który robisz do tych, tak aby podczas robienia dużych blasów źródło i miejsce docelowe pasowały jak najwięcej (ta sama wysokość i format bitmapy) i nie wymagane jest skalowanie. – themightyjon

1

Jeśli Twój wykres jest ograniczony, spróbuj najpierw renderować go wszystkie do obrazu, a następnie wymieszać odpowiednie części z tego obrazu na płótnie. Staraj się unikać "poruszania się" pikseli w buforze, ponieważ może to wprowadzać zależności między twoimi odczytami i zapisami i może naprawdę zabić wydajność. Właściwiej może być skopiowanie z 1 bufora do drugiego i na zmianę, który z nich zostanie pobłogosławiony na ekranie. Na koniec, jeśli musisz ręcznie pracować nad pikselami, upewnij się, że uruchamiasz obraz w liniach zamiast w kolumnach i że zaczynasz od początku linii, aby pomóc w buforowaniu.

1

Jeśli chodzi o wydajność, bez profilowania nie możemy powiedzieć.

Możliwe, że rysunek liniowy jest przyspieszany sprzętowo w telefonie docelowym i należy narysować wykres od podstaw, używając prymitywów rysowania linii w każdej klatce.

Z drugiej strony, prosta manipulacja piksel bufor obrazu będzie:

Utwórz obraz, który jest właściwy rozmiar i wyczyścić go do „background_color”. Ten obraz musi mieć funkcję setpixel().

Masz tablicę wartości, które rejestrują y każdego x, więc dla każdej kolumny wiesz, gdzie ostatnio został naniesiony wykres.

Traktuj ten "chart_image" i "chart_array" jako bufor cykliczny. Dla każdego kroku czasowego:

Y = ...; 
X = time_since_start % chart_width; 
chart_image.setpixel(X,chart_array[X],background_color); // clear previous line 
chart_array[X] = Y; 
chart_image.setpixel(X,chart_array[X],foreground_color); // draw new plot 

A teraz musisz go zmącić. Trzeba Blit obraz dwukrotnie:

X = time_since_start % chart_width; 
// the newest data is on the left of the chart_image but gets drawn on the right side of the output 
blit(out_x+X,out_y, // destination coordinates 
    chart_image, 
    0,0, // top left of part of chart_image to blit 
    X,chart_height); // bottom right of chart_image part 
// the oldest data is on the right of the chart_image but gets drawn on the left side of the output 
blit(out_x,out_y, 
    chart_image, 
    X,0, 
    chart_width,chart_height); 

Robi się bardziej skomplikowane, jeśli chcesz korzystać z linii zamiast pojedynczych pikseli, ale drawline() zamiast setpixel() może sprawić, że praca z tym podejściem zbyt.

(Przepraszam, że nie znamy interfejsów API Androida, ale podejście jest ogólne.)

0

Ponieważ mogę przyjąć za pewnik, że przechowujesz dane wykresu w pamięci, przerysowanie nie powinno stanowić problemu. Nie jest to wcale intensywne, aby przerysować zbiór punktów w każdej klatce. Przesuwanie pamięci jest intensywne, wszystko zmienia się, a tylko maluje tylko to, czego potrzebujesz. Najgorszy scenariusz, ponieważ jest to funkcja czasu, tylko jedna wartość na kolumnę wyświetlacza, około 800 pikseli/wartości w krajobrazie, które system musi narysować. To banalne. Czy profilowałeś to? EDYCJA: Pamiętaj, to nie jest tak, że system musi narysować każdy punkt, tylko czerpie z pamięci, a następnie używa jej prymitywów. Nie myśl, jakby to iterowało rysowanie punktu, wyrzucanie do pamięci wideo, a potem znowu.

Powiązane problemy