Mam napisać program, który wyświetla animację. Z okienkiem itp nie mam problemu ale z samą animacja już tak. Otóż animacja to okręgi wyświetlane klatka po klatce. I to wszystko mam w pliku .txt. I w każdej linijce pierwsza liczba to nr klatki a reszta współrzędna x i y tej kuli (chyba max to 1200 tych kulek). Będę wdzięczny za pomoc jak to ogarnąć i w razie czego za udzielenie odpowiedzi na dodatkowe pytania.
Weź dowolny program w Swingu, który coś wyświetla jako animację, następnie podmień etap renderowania grafiki, tak aby wyświetlał co potrzebujesz.
Model powinien wczytać (zapewne przed rozpoczęciem) plik, ułożyć sobie informacje w nim zawarte w taki sposób aby dało się szybko wyrenderować kolejne klatki.
Poniżej podaję pisane na kolanie przykłady, w założeniu ma to ilustrować temat, a nie pokazywać ładne praktyki programistyczne :)
canvas = new Canvas() {
private static final long serialVersionUID = 1L;
@Override
public void paint(Graphics g) {
super.paint(g);
//tutaj sobie rysuj co wynika z modelu danych na daną klatkę, poniżej jakiś abstrakcyjny przykład
g.drawRect(0, 0, CANVAS_SIZE - 1, CANVAS_SIZE - 1);
for (int i = 0; i < 30; i++) {
int x = rng.nextInt(CANVAS_SIZE - 2);
int y = rng.nextInt(CANVAS_SIZE - 2);
g.fillOval(x, y, 8, 8);
}
}
};
A tak wygląda użycie:
while (true) {
try {
Thread.sleep(995);
modelAnimacji.tick(); //przygotowanie kolejnej klatki do wyświetlenia
canvas.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Super, a jeśli chodzi o wczytywanie 1 inta w danej linijce i później po kolei współrzędnych to jak to zrobić? Pewnie Scanner tylko jakie metody?
Może być, podaję szkic algorytmu: dopóki jest następna linijka, pobierz ją. Wynik rozbij (split) po spacjach, przekonwertuj odpowiednie elementy tej tablicy na int/Integer za pomocą Integer.valueOf.
Mam taką ramkę https://4programmers.net/Forum/Download/21630
i jak ustawić wysokość g,drawRect()
zajmował całą tą przestrzeń a nie więcej?
Mattii4211 napisał(a):
Mam taką ramkę https://4programmers.net/Forum/Download/21630
i jak ustawić wysokośćg,drawRect()
zajmował całą tą przestrzeń a nie więcej?
W zapodanym przykładzie ja robię:
private static final int CANVAS_SIZE = 500;
//.........
canvas.setSize(CANVAS_SIZE, CANVAS_SIZE);
//a to jest taki roboczy pomysł na zrobienie obramowania, tj: rysuję prostokąt od 0,0 do punktu 1 piksel od końca canvas
g.drawRect(0, 0, CANVAS_SIZE - 1, CANVAS_SIZE - 1);
Tylko problem jest taki, że moja ramka (BorderLayout) może zmienić rozmiar a Canvas()
musi cały czas być maksymalne
I jeszcze jedno pytanie BufferedReader in
czy (int) in.lines().count()
odczyta mi ilość linijek w pliku?
Zrobiłem g.drawrect(0,0, this.getsize().width, this.getSize().height)
Dobra analizuję ten twój przykład i jakoś nie wiem jak się za to zabrać. Dane w pliku od 2 linijki są tak poukładane: nr klatki, pozycja x pozycja y pozycja x .... Pozycje są double/float. I nie wiem za bardzo jak rozpracować to rysowanie tych kulek (drawOval).
Mattii4211 napisał(a):
Dobra analizuję ten twój przykład i jakoś nie wiem jak się za to zabrać. Dane w pliku od 2 linijki są tak poukładane: nr klatki, pozycja x pozycja y pozycja x .... Pozycje są double/float. I nie wiem za bardzo jak rozpracować to rysowanie tych kulek (drawOval).
Pierwszy z wyników Googla daje przyzwoity przykład: https://www.google.com/search?q=java+parse+file+of+doubles
Czyli powinieneś zrobić pętle po linijkach pliku, następnie zeskanować jeden int, i dowolną liczbę (par) doubli.
Odnośnie rysowania, nie ma pytania na które można by odpowiedzieć, natomiast zarzucę linkiem: https://docs.oracle.com/javase/8/docs/api/java/awt/Graphics.html#drawOval-int-int-int-int-
Dobra, ze wczytywaniem sobie poradziłem ale nie wiem jak narysować na raz 1200 tych piłek na 1 klatce. Robię for(int i=0; i<1200; i++)
i co dalej?
PS dane mam w ArrayList();
\Mam tak obecnie:
g.drawRect(0, 0, this.getSize().width, this.getSize().height);
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < numberOfBalls; i++) {
double x = positions.get(frame).get(j);
double y = positions.get(frame).get(j+ 1);
if(j > 1) {
x1 = positions.get(frame).get(j-2)+10d;
y1 = positions.get(frame).get(j - 1)+10d;
}
j = j+2;
Ellipse2D circle = new Ellipse2D.Double(x1+x+10d, y1+y+10d, 10, 10);
g2.draw(circle);
}
ale rysuje mi te kulki tylko tak jakby w jednym kwadracie
Mattii4211 napisał(a):
Dobra, ze wczytywaniem sobie poradziłem ale nie wiem jak narysować na raz 1200 tych piłek na 1 klatce. Robię
for(int i=0; i<1200; i++)
i co dalej?
PS dane mam w ArrayList();
Dla każdego takiego i
pobierasz z tej listy x, oraz y i wypełniasz "owal" na tej grafice. Przykład rysowania koła o promieniu 8 już podawałem powyżej, dokumentację do metody rysowania okręgu także.
PS Warunek kontynuacji pętli (i<1200
) powinien więc zależeć od rozmiaru tej listy, a nie od wpisanej literału zgodnego z jakimś jednym inputem. Taki kod będzie odporniejszy na błędy oraz czytelniejszy.
Część danych dla 1 klatki:
33.6075 15.7753 31.324 31.9376 36.4659 7.90205 13.4089 30.7292 11.111 22.1588 19.0959
Mattii4211 napisał(a):
Część danych dla 1 klatki:
33.6075 15.7753 31.324 31.9376 36.4659 7.90205 13.4089 30.7292 11.111 22.1588 19.0959
No ok, jako że niektóre z tych liczb przekraczają 10, a żadna nie przekracza 100, to może jest to procentowe położenie a nie bezwzględnie w pikselach? Wtedy wystarczy przemnożyć procent przez rozmiar canvasu. Np. 25% x 480px == 120 px współrzędna.
Dobra twój pomysł to strzał w 10 tylko w jaki sposób pobrać aktualny jego rozmiar, gdyż okno się może zmieniać i na początku mam scereenSize()/2
oraz jak sprawić, żeby kulki tylko w canvas się wyświetlały?
do Canvas() dodałem addComponentListener()
i mam coś takiego:
public void componentResized(ComponentEvent e) {
height = e.getComponent().getSize().height;
width = e.getComponent().getSize().width;
Jak rozciągam okno to rozciągają się elementy tylko jak wyliczam x i y : (positions.get(frame).get(j+ 1)/100.0d)*height;
to znów nie rozkładają się na cale okno
Pewnie jakiś prosty błąd ale już coraz gorzej myślę xd
Dodam jeszcze, że okienko ma BorderLayout()
a Canvas()
jest ustawiony jako Center