Rysowanie w AWT

Praca z obrazami

Krystian Ignasiak

K.Ignasiak@ire.pw.edu.pl

http://tiger.ire.pw.edu.pl/pzdt

Klasa Component – istotne metody

• addNotify()

• update(...)

• paint(...)

• repaint(...)

• Dimension getPreferredSize()

OdświeŜanie komponentów graficznych 1/2

• Wyzwalane przez podsystem graficzny

( system-triggered)

– Komponent graficzny powinien zostać

narysowany po raz pierwszy

– Ko

K mp

m onen

e t z

m

z i

m en

e ił rozm

z i

m ar

a

– Zawartość komponentu została przysłonięta

• Wyzwalane przez aplikację ( application-triggered)

– Aplikacja uznaje, Ŝe jej stan wewnętrzny wymaga przemalowania komponentu

OdświeŜanie komponentów graficznych 2/2

• Wyzwalane przez podsystem graficzny

( system-triggered)

– Z wątku obsługi zdarzeń zostanie wywołana metoda paint()

• Wy

W zwala

l ne p

rzez a

pli

l k

i ację

j (

appli

l c

i ati

t o

i n-

n

triggered)

– Aplikacja woła repaint()

– Z wątku obsługi zdarzeń zostanie wywołana metoda update() (scalanie wywołań !)

– Standardowa realizacja update() najpierw wypełni tło aktualnym kolorem tła komponentu, następnie wywoła metodę paint()

Mechanizm rysowania AWT

• Wyzwalane przez system ( system-triggered)

– paint()

• Wyzwalane przez aplikację ( application-triggered)

– repaint()

– update()

– paint()

Metoda paint()

• Metoda typu callback – programista dostarcza implementację zaplanowanej funkcjonalności

• public void paint(Graphics g)

• Kontekst graficzny ustawiony prawidłowo:

– kolor, czcionka, współrzędne, itd

• Aplikacja powinna umieścić kod związany z rysowaniem komponentu tylko wewnątrz

metody paint() (lub w metodach z niej wołanych z przekazaniem kontekstu g)

Przykład – metoda paint()

•

public void paint(Graphics g) {

Dimension size = getSize();

int d = Math.min(size.width, size.height); int ed = d/20;

int x = (size.width - d)/2;

int y = (size.height - d)/2;

g.fillOval(x, y, d, d);

g.setColor(Color.black);

g.drawOval(x

g.drawOva

,

l(x

y,

,

d,

y,

d);

d,

g.fillOval(x+d/3-(ed/2), y+d/3-(ed/2), ed, ed); g.fillOval(x+(2*(d/3))-(ed/2), y+d/3-(ed/2), ed, ed); g.drawArc(x+d/4, y+2*(d/5), d/2, d/3, 0, -180);

}

Metoda update()

•

Pozwala inaczej traktować komponenty lekkie i cięŜkie

•

Realizacja metody update() w klasie Component

– public void update(Graphics g) {

paint(g);

}

•

Realizacja metody update() w klasie Container

– public void update(Graphics g) {

if (isShowing(

if

))

(isShowing(

{

))

if (! (peer instanceof LightweightPeer)) {

g.clearRect(0, 0, width, height);

}

paint(g);

}

}

•

Realizacja metody update() w klasie Canvas

– public void update(Graphics g) {

g.clearRect(0, 0, width, height);

paint(g);

}

Komponenty lekkie i cięŜkie

• Komponenty cięŜkie ( heavyweight) to takie, które wykorzystują komponent graficzny

rodzimego systemu operacyjnego

• Komponenty lekkie ( lightweight) to takie, któ

t re n

ie

i k

orzysta

t ją

j z

p

omocy s

yste

t mu

operacyjnego i cała ich funkcjonalność i

sposób rysowania oprogramowane są tylko w

Javie

• Większość komponentów AWT to

komponenty cięŜkie, większość

komponentów Swing to komponenty lekkie

Wskazówki rysowania

• Nigdy nie wołamy bezpośrednio paint() – zawsze repaint()

• Kod związany z rysowaniem umieszczamy w

metodzie paint() lub w metodach z niej wołanych

• Inkrementalne rysowanie komponentów realizujemy prze

z z

e

z o

dpowi

w ed

e nie

e o

program

a o

m wa

w n

a ie

e update()

• Jeśli klasa dziedziczy po Container i realizuje własną metodę paint() – naleŜy wywołać super. paint() dla zapewnienia odrysowania lekkich komponentów w tym kontenerze

• Komponenty powinny ograniczać to co realizują w metodzie paint() do niezbędnego minimum (regiony obcinania działają na naszą korzyść...)

Praca z obrazkami (Image)

• Klasa java. awt. Image (abstrakcyjna)

• Pakiet java. awt. image przetwarzanie obrazków

• Metody getImage(), createImage()...

Przykład

•

import java.awt.*;

import java.awt.event.*;

public class GetImage extends Frame {

GetImage(String title, String imageFileName) {

//...

setVisible(true);

}

public void addNotify() {

super.addNotify();

img = Toolkit.getDefaultToolkit().getImage(fileName);

}

public void paint(Graphics g) {

try { g.drawImage(img, 0, 0, this); }

catch (NullPointerException npe) { }

}

public static void main(String[] args) {

new GetImage("GetImage - GIF", "1.gif");

}

}

Asynchroniczne ładowanie obrazków

• getImage() nie powoduje ściągnięcia danych obrazowych (sterowanie wraca

natychmiast do metody wołającej)

• getImage() jedynie zleca ściągnięcie danych o

sobnemu w

ątk

t owi,

i k

tó

t ry j

e

j st

t

nadzorowany przez obiekt obserwujący

• ImageObserver

Interfejs ImageObserver

• Definiuje pewne stałe (ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH)

• Definiuje metodę:

boolean imageUpdate(Image

boolean

img,

imageUpdate(Image

int infoflags, int x, int y,

int width, int height)

wołaną gdy nadejdą (lub nadchodzą) dane obrazowe

Realizacja imageUpdate w klasie Component

•

public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h){

int rate = -1;

if ((infoflags & (FRAMEBITS|ALLBITS)) != 0) {

rate = 0;

} else if ((infoflags & SOMEBITS) != 0) {

if (isInc) {

rate = incRate;

if (rate

if

<

(rate

0)

<

{

0)

rate = 0;

}

}

}

if (rate >= 0) {

repaint(rate, 0, 0, width, height);

}

return (infoflags & (ALLBITS|ABORT)) == 0;

}