Petla animacji, MouseListener

0

Witam

Mam problem z pętlą animacji.

void loopAnim(){
while(true){
update();
gx2=(Graphics2D)image.getGraphics();
paint(gx2);
gx2.dispose();
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

Tak ona wygląda.
Dokładnie chodzi oto ze mam mouselistener dodany do jPanel i bez tej pętli wszystko działa -> myszka jest obsługiwana. Natomiast gdy uruchomię ta pętle, myszka nie jest obsługiwana i moje pytanie jest dlaczego ?

0

Bo ta pętla wykonuje się pewnie w wątku Swinga, więc nie łapie myszki, bo wykonuje tą pętlę.

Użyj SwingWorkera.

0

Kilka różnych uwag.
Jak napisał kolega powyżej, pętla taka nie może być wykonywana w wątku Swinga.
Metody paint nigdy nie wywołuje się w takiej pętli (w ogóle się jej jawnie nie wywołuje). Jeżeli już chcesz zaprzęgać AWT/Swinga do animacji, to w miejscu paint użyj repaint opakowanej w wywołanie invokeLater.
Oprócz tego wszystkie listenery powinny szybko aktualizować stan animacji (jakieś zmienne), natomiast update powinno z tego stanu korzystać do sterowania animacją.
Dodatkowo stan pauzy animacji powinien blokować wywoływanie update, a pętla powinna nadal działać (np. w animacji 3d kamera w czasie pauzy normalnie obraca obraz, a w przypadku gry platformowej (2d) klawisze kierunków mogą pozwolić na obejrzenie obrazu poziomu).

Wywołanie getGraphics jest do wyrzucenia za wyjątkiem sytuacji gdybyś chciał sam kontrolować buforowanie obrazu (np. przez wymiany stron). W takim wypadku używa się innej metody zamiast pary repaint/paint - po to, aby nie dostawały kontekstu graficznego komponentu, lecz Twojego bufora. Wtedy też należy użyć metody setIgnoreRepaint do ignorowania systemu wymuszającego odrysowanie (czyli jeżeli nie wywołasz repaint, to paint będzie nieużywane).

Zamiast while(true) użyj w jej warunku jakiejś zmiennej, żeby móc gładko kontrolować zakończenie animacji bez ordynarnego zatrzymywania wątku przez stop, destroy, suspend (obecnie wszystkie są deprecated). Animacja powinna się normalnie zakończyć zanim animowany komponent zostanie wyłączony przez setVisible(false), usunięty ze swojego rodzica przez remove, removeAll lub w przypadku apletu po wywołaniu metody stop i przed ponownym wywołaniem start.

Na koniec zauważ, że taka pętla zależnie od ilości czasu spędzonego w update oraz paint (repaint) dawać będzie zmienną ilość klatek animacji w sekundzie. Czas użyty w metodzie sleep powinien być obliczany na podstawie czasu wykonania wcześniejszych metod, tak aby pętla wykonywała się zawsze tyle samo razy w jednej sekundzie. Wymogiem każdej gry jest stała liczba aktualizacji (updates per second - UPS), a zaleceniem każdej animacji stała liczba odrysowań (frames per second - FPS).

0

Jeszcze zamieszczę kod obsługi animacji z mojego programu, gdzie nie ma potrzeby rysowania non-stop, tylko gdy na scenie są animowane obiekty:
http://pastebin.com/3L8Q25Dp

Wszelkie akcje zmieniające tą listę dzieją się w wątku Swinga (dokładnie w momencie rysowania, gdzie są usuwane i ruchów myszką, gdzie są dodawane).

Przy usuwaniu schematu z dokumentu zmienna rendering jest ustawiana na false i renderLock.notify(), co kończy wykonywanie tego wątku.

Robiłem to nie znając jeszcze SwingWorkera:p

0

Dzięki za pomoc, teraz mogę ruszyć dalej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1