Wprowadzenie do programowania współbieżnego. Grafika, Proste Animacje

Podobne dokumenty
Programowanie Obiektowe Java

Aplikacje w Javie- wykład 11 Wątki-podstawy

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ

Wielowątkowość. Programowanie w środowisku rozproszonym. Wykład 1.

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

Aplikacja wielowątkowa prosty komunikator

Język Java wątki (streszczenie)

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Java: otwórz okienko. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003

Materiał pomocniczy do kursu Podstawy programowania Autor: Grzegorz Góralski ggoralski.com

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Język Java część 2 (przykładowa aplikacja)

Aplikacja wielow tkowa prosty komunikator

Dokumentacja do API Javy.

Kontenery i komponenty graficzne

Język Java część 2 (przykładowa aplikacja)

Obiektowe programowanie rozproszone Java RMI. Krzysztof Banaś Systemy rozproszone 1

WSPÓŁBIEŻNOŚĆ. MATERIAŁY:

Interfejsy w Java. Przetwarzanie równoległe. Wątki.

Język Java wątki (streszczenie)

Kurs programowania. Wykład 8. Wojciech Macyna

Java. Programowanie Obiektowe Mateusz Cicheński

WIELOWĄTKOWOŚĆ. Waldemar Korłub. Platformy Technologiczne KASK ETI Politechnika Gdańska

Wywoływanie metod zdalnych

SWING c.d. przydatne narzędzia: JFileChooser, JOptionPane. drag'n drop, menu kontekstowe.

Programowanie współbieżne Laboratorium nr 11

Współbieżność w środowisku Java

JAVA. Strumienie wejścia i wyjścia. Pliki - zapis i odczyt

Programowanie obiektowe

Kurs programowania. Wykład 8. Wojciech Macyna. 10 maj 2017

Podstawy współbieżności

Programowanie komputerów

Programowanie obiektowe

II Tworzenie klasy Prostokąt dziedziczącej z klasy wątku

1. Co można powiedzieć o poniższym kodzie (zakładając, że znajduje się on w jednym pliku A.java)?

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

1. Co będzie wynikiem wykonania poniŝszych instrukcji? g2d.gettransform().scale(1, -1); g2d.gettransform().translate(4, -8); g2d.drawline(4, 0, 4, 4);

PROJEKTOWANIE ABSTRAKCYJNEJ KLASY FIGURA PRZECHOWUJĄCEJ WSPÓLNE CECHY OBIEKTÓW GRAFICZNYCH

Wywoływanie metod zdalnych

Java - interfejs graficzny

Multimedia JAVA. Historia

Programowanie obiektowe

Graphic User Interfaces pakiet Swing

Aplikacje RMI Lab4

1 Atrybuty i metody klasowe

Grafika i komunikacja człowiek komputer Laboratorium. Część 1: Wstęp do grafiki

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Remote Method Invocation 17 listopada 2010

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Przetwarzanie równoległe i współbieżne

Programowanie zdarzeniowe

Wątki w Javie. Piotr Tokarski

Remote Method Invocation 17 listopada Dariusz Wawrzyniak (IIPP) 1

Podejście obiektowe do budowy systemów rozproszonych

Remote Method Invocation 17 listopada rozproszonych. Dariusz Wawrzyniak (IIPP) 1

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Polimorfizm. dr Jarosław Skaruz

Programowanie obiektowe

Programowanie graficznego interfejsu użytkownika. Wykład 8. Maciej Wołoszyn 10 maja 2006

Java Podstawy. Michał Bereta

Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Języki i metody programowania Java INF302W Wykład 2 (część 1)

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Programowanie w JAVA Lab. 5 - Wątki. 1. Wykorzystując metodę Monte Carlo narysować wykres funkcji oraz obliczyć całkę: 7 x ) xy, 8,8

Tworzenie elementów graficznych

Aplikacje RMI

1. Co można powiedzieć o poniższym kodzie? public interface I { void m1() {}; static public void m2() {}; void abstract m3();

Programowanie obiektowe

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Programowanie współbieżne i rozproszone

Wykład 6. Rafał Skinderowicz

Metody Metody, parametry, zwracanie wartości

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Programowanie w Sieci Internet. Python: Wątki. Kraków, 12 grudnia 2014 r. mgr Piotr Rytko Wydział Matematyki i Informatyki

Podejście obiektowe do budowy systemów rozproszonych

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

Wątki (Threads) Potrzeby. Przetwarzanie równoległe i współbieŝne. Cechy programowania wątkowego. Concurrent programming is like

Podstawy programowania w lejos

Enkapsulacja, dziedziczenie, polimorfizm

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

Wykład 4: Klasy i Metody

Programowanie obiektowe

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

package pakieta; import pakietb.b; package pakietb; public class B { B(){} public class A { private B b; A(B b) { this.b = b; } }

Tworzenie i wykorzystanie usług

Zdalne wywołanie metod - koncepcja. Oprogramowanie systemów równoległych i rozproszonych Wykład 7. Rodzaje obiektów. Odniesienie do obiektu

Oprogramowanie systemów równoległych i rozproszonych Wykład 7

Rozdział 4 KLASY, OBIEKTY, METODY

Języki i Techniki Programowania II. Wykład 7. Współbieżność 1

Zaawansowane aplikacje WWW - laboratorium

Systemy wirtualnej rzeczywistości. Komponenty i serwisy

6.1 Pojęcie wątku programu 6.2 Klasy Timer, TimerTask 6.3 Klasa Thread 6.4 Synchronizacja pracy wątków 6.5 Grupowanie wątków

Wykład 8: Obsługa Wyjątków

Podstawy tworzenia aplikacji z wykorzystaniem języka Java ME ćwiczenia 2

SWING ZAGADNIENIA: wprowadzenie, kontenery I komponenty, LayoutManager, komponenty tekstowe.

Transkrypt:

Wprowadzenie do programowania współbieżnego Grafika, Proste Animacje

Procesy i wątki Proces to wykonujący sie program wraz z dynamicznie przydzielanymi mu przez system zasobami (np. pamięcią operacyjna, zasobami plikowymi). Każdy proces ma własną przestrzeń adresowa. Systemy wielozadaniowe pozwalają na równoległe (teoretycznie) wykonywanie wielu procesów, z których każdy ma swój kontekst i swoje zasoby. Wątek to sekwencja działań, która wykonuje sie w kontekście danego procesu (programu) Każdy proces ma co najmniej jeden wykonujący sie watek. W systemach wielowątkowych proces może wykonywać równolegle (teoretycznie) wiele wątków, które wykonują sie jednej przestrzeni adresowej procesu.

Wątki Z punktu widzenia programisty wspólny dostęp wszystkich wątków jednego procesu do kontekstu tego procesu ma zarówno zalety jak i wady. Zaletą jest możliwość łatwego dostępu do wspólnych danych programu. Wadą jest brak ochrony danych programu przed równoległymi zmianami, dokonywanymi przez różne wątki, co może prowadzić do niespójności danych, a czego unikanie wiąże się z koniecznością synchronizacji działania wątków. (więcej szczegółów nt. modelu pamieci w filmiku szkoleniowym Google: Java Memory Model : http://www.youtube.com/watch?v=wtvookllvt8 )

Klasa Thread http://docs.oracle.com/javase/7/docs/api/java/lang/thread.html Podstawowa klasa pozwalająca na uruchamianie tworzenie, uruchamianie i zarządzanie wątkami. Oprócz szeregu metod służących do zarządzania wątkami, klasa Thread implementuje interfejs Runnable, zawierający jedną metodę run() która jest wykonywana w momencie uruchamiania wątku Aby uruchomić watek, należy utworzyć obiekt klasy Thread i dla tego obiektu wywołać metodę start():

Klasa Thread Definiowanie klasy dziedziczącej po klasie Thread: class MyThread extends Thread {... public void run() { // kod do wykonania Tworzenie i uruchamianie wątku: MyThread t = new MyThread(); t.start(); Metoda run() nie jest wywoływana jawnie lecz pośrednio poprzez metodę start(). Użycie metody start() powoduje wykonanie działań zawartych w ciele metody run(). Jeśli w międzyczasie nie zostanie przerwane zadanie, w ciele którego dany wątek działa, to końcem życia wątku będzie koniec działania metody run().

ThreadExample.java class MyThread extends Thread{ final int threadid; public MyThread(int threadid) { super(); this.threadid = threadid; @Override public void run() { for(int ii = 0; ii < 10; ii++){ System.outprintln("Thread " + Thread.currentThread().getName() + " prints " + ThreadExample.nextNumber());

ThreadExample.java public class ThreadExample { static int currentint = 0; public static void main(string[] args) { int nthreads = 5; Thread[] threads = new Thread[nthreads]; for(int ii = 0; ii < nthreads; ii++){ threads[ii] = new MyThread(ii); for(int ii = 0; ii < nthreads; ii++){ threads[ii].start(); static int nextnumber(){ currentint++; return currentint;

Interfejs Runnable Inny sposób tworzenia wątków polega na implementacji do obiektu interfejsu Runnable: 1.Zdefiniować klasę implementującą interfejs Runnable (np. class Klasa implements Runnable). 2.Zdefiniowanie metody run (). 3.Utworzenie obiekt tej klasy (np. Klasa k = new Klasa(); ) 4.Utworzenie obiektu klasy Thread, przekazując w konstruktorze referencję do obiektu utworzonego w kroku 3 (np. Thread thread = new Thread(k);) 5.Wywołać na rzecz nowoutworzonego obiektu klasy Thread metodę start ( thread.start();)

RunnableExample.java class MyRunnableExample implements Runnable{ final int threadid; public MyRunnableExample(int threadid) { super(); this.threadid = threadid; public void run() { for(int ii = 0; ii < 10; ii++){ System.out.println("Thread " + Thread.currentThread().getName() + " prints " + RunnableExample.nextNumber());

RunnableExample.java public class RunnableExample { static int currentint = 0; public static void main(string[] args) { int nthreads = 5; Thread[] threads = new Thread[nthreads]; for(int ii = 0; ii < nthreads; ii++){ threads[ii] = new Thread(new MyRunnableExample(ii)); for(int ii = 0; ii < nthreads; ii++){ threads[ii].start(); static int nextnumber(){ currentint++; return currentint;

Wykonawcy Executors Samodzielne zarządzanie wątkami może być czasem kłopotliwe, dlatego od Java 1.5 zaleca się uruchamiać wątki przy pomocy tzw. klas wykonawców (executors). Pozwalają one na odseparowanie zadań do wykonania od mechanizmów tworzenia i uruchamiania wątków. ExecutorService exec = Executors.newFixedThreadPool(2); //Executors.newSingleThreadExecutor(); exec.execute(b1); exec.execute(b2); // b1, b2 obiekty implementujace Runnable exec.shutdown();

Wykonawcy Executors Executors.newSingleThreadExecutor() - Wykonawca uruchamiający podane mu zadania w jednym wątku (po kolei) Executors.newFixedThreadPool( int n) - Wykonawca, prowadzący pulę wątków o zadanych maksymalnych rozmiarach Pule wątków pozwalają na ponowne użycie wolnych wątków, a także na ew. limitowanie maksymalnej liczby wątków w puli.

JButtonRunnable.java public class JButtonRunnable extends JButton implements Runnable { (...) String[] tekst = {"To", "jest", "animowany", "przycisk"; (...) public void run() { int i = 0; while(czynny){ if (i < tekst.length-1 ) i++; else i = 0; settext(tekst[i]); try { Thread.sleep(pauza); catch (InterruptedException e) { e.printstacktrace();

JButtonRunnable.java metoda main() JFrame f = new JFrame(); f.setlayout(new GridLayout(2,1)); f.setsize(200, 200); f.setdefaultcloseoperation(jframe.exit_on_close); JButtonRunnable b1 = new JButtonRunnable(); f.add(b1); String[] innytekst = {"inny", "tekst", "do", "anim", "przycisku"; // wykorzystanie drugiego konstruktora pozwalajacego zmienic tekst i szybkosc: JButtonRunnable b2 = new JButtonRunnable(innyTekst, 1600); f.add(b2); ExecutorService exec = Executors.newFixedThreadPool(2); exec.execute(b1); exec.execute(b2); exec.shutdown(); f.setvisible(true);

ScheduledExecutorService ScheduledExecutorService - wykonawca zarządzający tworzeniem i wykonaniem wątków w określonym czasie lub z określoną periodycznością: schedule(runnable command, long delay, TimeUnit unit) Jednokrotnie uruchomienie zadania po upływie czasu delay scheduleatfixedrate(runnable command, long initialdelay, long period, TimeUnit unit) Periodyczne wykonywanie zadania (z możliwym opóźnieniem startu), czas liczony miedzy rozpoczeciem kolejnych iteracji schedulewithfixeddelay(runnable command, long initialdelay, long delay, TimeUnit unit) Periodyczne wykonywanie zadania (z możliwym opóźnieniem startu) - czas liczony od zakonczenia jednej iteracji do rozpoczecia nastepnej

ScheduledExecutorExample.java import static java.util.concurrent.timeunit.*; (...) final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); scheduler.scheduleatfixedrate(r, 0, 1, SECONDS); scheduler.schedulewithfixeddelay( (new Runnable() { public void run() { System.out.println("Po 5 sekundach - potem co 3 sekundy"); ), 5, 2, SECONDS); import static java.util.concurrent.timeunit.*; MILLISECONDS, NANOSECONDS

ScheduledExecutorExample.java scheduler.schedule(new Runnable() { @Override public void run() { System.out.println("Koniec programu po 15 sekundach"); scheduler.shutdownnow(); System.exit(0);, 15, SECONDS);

JButtonScheduled.java public class JButtonScheduled extends JButton implements Runnable { String[] tekst = {"To", "jest", "przycisk", "animowany", "przez", ScheduledExecutorService"; int i = 0; public JButtonScheduled() { super(); public void run() { if (i < tekst.length-1 ) i++; else i = 0; settext(tekst[i]);

JButtonScheduled.java final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3); // zadanie powtarzane cyklicznie - czas liczony od uruchomienia poprzedniego wykonania takie zadanie moze byc przerwane jedynie przez anulowanie - patrz nizej final ScheduledFuture<?> sc1 = scheduler.scheduleatfixedrate(b1, 1000, 50, MILLISECONDS); // zadanie powtarzane - czas liczony od zakonczenia poprzedniego wykonania scheduler.schedulewithfixeddelay(b2, 2, 1, SECONDS); // jednokrotne wywolanie metody run z zadanym opoznieniem scheduler.schedule(b3, 5, SECONDS); //Anulowanie pierwszego watku po 15 sekundach scheduler.schedule (new Runnable() { public void run() { sc1.cancel(true);, 15, SECONDS);

Wątki w Swingu W Java wątek odpowiadający za obsługę GUI nosi nazwę Event Dispatch Thread (EDT). Jak sama nazwa mówi zajmuję się on obsługą kolejki zdarzeń i informowaniem o nich obiektów nasłuchujących (czyli Listenerów), dodatkowo zarządza rozłożeniem komponentów, ich wyświetleniem, zmianą właściwości komponentów (np. dezaktywacja przycisku) i obsługą zadań. Zadaniami tymi powinny być tylko i wyłącznie krótkotrwałe procesy.

Wątki w Swingu Zaleca się, żeby każda aplikacja tworzyła i uruchamiała GUI poprzez metodę invokelater, np.. public static void main(string[] args) { SwingUtilities.invokeLater(new Runnable(){ public void run() { JFrame f = new JFrame(); f.setsize(200,200); f.setvisible(true); ); //lub w niemal równoważny sposób: public static void main(string[] args) { EventQueue.invokeLater( new Runnable(){ public void run() { JFrame f = new JFrame(); f.setsize(200,200); f.setvisible(true); );

Swing - EDT invokelater ( Runnable r ) invokeandwait ( Runnable r) Obie te metody przyjmują instancję Runnable a jej metodę run wykonują w EDT. Różnica jest taka że wywołanie invokeandwait kończy się z chwilą wykonania metody run, a wykonanie metody invokelater z chwilą zlecenia zadania do EDT.

Blokowanie GUI Umieszczanie zbyt długich zadań w Event Dispatch Thread (EDT) może skutecznie zablokować GUI. przykład: LongTaskInEDT.java

Klasa javax.swing.timer Pozwala uruchomić jedno lub kilka zdarzeń akcji ( ActionEvent) z zadanym opóźnieniem lub interwałem czasowym. Zdarzenia będą wykonywane w ustalonych interwałach w wątku EDT timer = new Timer(speed, this); timer.setinitialdelay(pause); timer.start(); timer.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { // kod wykonywany cyklicznie );

Klasa javax.swing.timer Przykład: NoClick.java Timer timer = new Timer(2500, null); timer.addactionlistener(new ActionListener() { @Override public void actionperformed(actionevent e) { autopress.doclick(); ); timer.start();

Klasa java.util.timer Działanie zbliżone do scheduledexecutor omawianego wcześniej Przykład: UtilTimer.java Timer timer = new Timer(true); timer.scheduleatfixedrate(new TimerTask() { // ewentualnie w invokelater: public void run() { autopress.etbackground(newcolor(rand.nextint()));, 250, 250 );

SwingWorker - http://docs.oracle.com/javase/7/docs/api/javax/swing/swingworker.html Klasa SwingWorker została zaprojektowana do szybkiego tworzenia wątków, które pracują równolegle do EDT. public abstract class SwingWorker<T,V> extends Object implements RunnableFuture SwingWorker to klasa abstrakcyjna, czyli możemy utworzyć obiekt tylko i wyłącznie klasy po niej dziedziczącej. Implementowany interfejs jest połączeniem interfejsów Runnable i Future (z niego właśnie pochodzi metoda get() zwracająca rezulat obliczeń). Parametr T określa typ zwracany przez metody doinbackground() i get() o których później. Jest to po prostu rezultat naszego zadania np. obrazek. Parametr V określa typ danych pośrednich, które może produkować zadanie, przykładowo linie tekstu z wczytywanego pliku. Dane te można wyłuskać za pomocą metody process(list dane), a które przekazuje do niej metoda publish(v... dane), która powinna być używana w implementacji metody doinbackground(). Uwaga! Aby metody nie zwracały nic (void) w deklaracji klasy należy podstawić parametr Void (przez duże V )

SwingWorker wybrane metody abstract protected doinbackground() - w niej powinniśmy dostarczyć zadanie do wykonania. Jeśli przesłonimy także metodę process(list dane), możemy przy pomocy publish(v... dane) przekazywać do process(list dane) cząstkowe wyniki działania zadania. protected process(list dane) - dzięki tej metodzie możemy operować na pośrednich danych zwróconych przez publish(v... dane). W tej metodzie możemy bezpiecznie operować na komponentach graficznych ponieważ działa ona asynchronicznie w EDT. protected void publish(v... chunks) - przesyła szczątkowe dane metodzie protected process(list dane), nie ma potrzeby jej przesłaniania, ale można to zrobić w przypadku gdy np. chcemy wykonać jakieś extra operację na dostarczanych danych. protected void done() - wywoływana po zakończeniu zadania, wykonywana w EDT, można w niej przeprowadzić sprzątanie i zaprezentować w GUI główny rezultat wykonywanego zadania, czyli pobrać rezultat działania doinbackground() przy pomocy metody get()

SwingWorkerDemo.java button.addactionlistener(new ActionListener(){ public void actionperformed(actionevent e) { SwingWorker<String, Void> worker = new SwingWorker<String, Void>(){ protected String doinbackground() throws Exception { progressbar.setindeterminate(true); Thread.sleep(5000); return "Element zwracany przez metode"; protected void done() { try { etykieta.settext(get()); progressbar.setindeterminate(false); catch (Exception ex) { ex.printstacktrace(); ; worker.execute(); );

SwingWorkerCopyFiles.java OnCopyActionListener - interfejs wyboru plików i uruchamiania SwingWorkera: copyswingworker.execute(); protected Void doinbackground() kopiowanie Wykorzystanie metod setprogress(), getprogress() i interfejsu zmiany stanu : setprogress(progress); addpropertychangelistener ( progressbar.setvalue(getprogress());

Przedstawione zostały wybrane sposoby tworzenia i uruchamiania wątków. W ogólności tworzenie aplikacji wielowątkowych jest dość trudnym zadaniem (często trzeba uwzględnić np. synchronizowanie wątków, dostępu do zasobów, komunikację między wątkami itp.)

GRAFIKA Kilka przykładów wykorzystania grafiki w Javie Wyświetlanie plików Graficznych: ImagePanelDemo.java + ImagePanel.java Logo.java URL resource = getclass().getresource("obrazki/zdjecie.jpg"); - pobieranie zasobu z popakietu

GRAFIKA (Java2D) Klasa Graphics2D dużo większe możliwości tworzenia grafiki (m.in. łatwa obsługa przezroczystości, wypełnienia gradientowe, transformacje geometryczne, ) SimpleGraphics.java przykład wykorzystania klasy Graphics2d Gradient.java przykład wypełniania gradientowego TextureGraphics,java przykład wykorzystania tekstur SaveImage.java przykład tworzenia buforrowanego obrazka i zapisu do pliku graficznego.

Animacje Ogólny schemat tworzenia animacji: Wykorzystać jedną z omawianych wcześniej metod tworzenia wątków do periodycznego przerysowywania wybranego komponentu (np. dziedziczącego z JPanel ) z każdorazową zmianą rysowanej sceny Przerysowywanie komponentu (np.component.repaint() ) zaleca się umieszczać w EDT (metodą invokelater), (dla prostych animacji pominięcie tego będzie praktycznie bez wpływu na działanie )

Przykładowe proste animacje ProstaAnimacja.java animowany JPanel PlikiGraficzne0.java, PlikiGraficzne.java animacja z kilku plików jpg (periodyczne seticon() w JLabel ) PlikiGraficzneTimer.java j.w. z wykorzystaniem klasy Timer (swing) i możliwością sterowania wątkiem Prostokat.java, Rysowanie7.java animacja obiektu Prostokat (na podstawie przykładów RysowanieMysz6.java z wykładu 4)

Animacje eliminowanie migotania Jeśli animacje migają warto zastosować tzw. podwójne buforowanie, które polega na utworzeniu obiektu pośredniego (np. klasy BufferedImage) na którym następuje rysowanie sceny, a odświeżanie polega tylko na podmienieniu obrazka wyświetlanego w metodzie paintcomponent (np. g.drawimage( pilkaimg, 0, 0, this ); ) przykład w Rysowanie8.java i RysowanieUproszczone.java Tworzenie złożonej sceny może trwać dłużej (np. wczytanie pliku tła, obliczanie współrzędnych animowanych obiektów) zdecydowanie powinno być poza EDT, natomiast odświeżanie obrazka w EDT

Polecana dalsza lektura dla zaawansowanych http://fivedots.coe.psu.ac.th/~ad/jg/index.html - internetowa wersja obszernej książki Killer Game Programming in Java