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()
• Wyzwalane przez system ( system-triggered)
– paint()
• Wyzwalane przez aplikację ( application-triggered)
– repaint()
– update()
– 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)
•
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);
}
•
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 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
• 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ść...)
• Klasa java. awt. Image (abstrakcyjna)
• Pakiet java. awt. image przetwarzanie obrazków
• Metody getImage(), createImage()...
•
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
• 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;
}