Professional Documents
Culture Documents
forelesningen
• Objektorientering
– Objektorientert grafikk
• Javaprogrammering
– Grafikk med Java2D
– Egne Swingkomponenter
1
Grafikk
tekst
linjer
1D
fasonger
2D
bilder
2
Java2Ddemo
C:\Program files\
java\jdk1.5.0_11\demo\jfc\
Java2D\Java2Demo.jar
3
Output av grafikk
• En komponent får tildelt et rektangel som den kan tegne innenfor
• Når innholdet skal tegnes blir komponentens paintmetode kalt
• paintmetoden kaller tre andre metoder (i denne rekkefølge):
– paintComponent tegner komponentens eget innhold
– paintBorder – tegner rammen rundt
– paintChildren – tegner delkomponentene
• Dersom en ønsker egen grafikk, bør en subklasse JComponent eller
JPanel og redefinere paintComponentmetoden:
public class MinKomponent extends JComponent {
...
protected void paintComponent(Graphics g) {
// tegn en linje
g.drawLine(10, 10, 50, 50);
}
...
}
4
paintComponentmetoden
• Hver komponent har en bredde (width) og en høyde
(height) som definerer området som er tilgjengelig
• Hver komponent har i tillegg en ramme som stjeler plass
på innsiden og som reduserer området et bør tegnes på
– getInsets() returnerer et Insetsobjekt
– Insetsobjektet har 4 attributter, top, left, bottom og right, som angir hvor mange
punkter som rammen dekker på de 4 sidene
• Før grafikken tegnes er det lurt å beregne området som er
tilgjengelig:
Insets insets = getInsets();
int x = insets.left;
int y = insets.top;
int bredde = getWidth() - insets.left -
insets.right;
int høyde = getHeight() - insets.top -
insets.bottom;
5
Graphics/Graphics2Dobjektet
• Graphicsparameteret til paintComponentmetoden brukes
ved tegning av alt innhold
• parametret er deklarert som en Graphics, men for en
JComponentsubklasse er det alltid et Graphics2Dobjekt
– protected void paintComponent(Graphics g) {
Graphics2D graphics = (Graphics2D)g;
// heretter brukes graphics
• Graphics2Dobjektet har essensielt to typer metoder:
– tegning av grafikk, såkalte grafikkprimitiver, f.eks.
• drawLine, drawRect, drawArc, diverse drawImagemetoder, fillRect, fillPolygon, ...
– styring av hvordan tegningen blir utført, dvs. hvordan kall til grafikkprimitivene
farger punktene i vinduet (eller hva en nå tegner på), f.eks.
• strektype – setStroke
• farge og mønster – setColor og setPaint
• skriftstype setFont
6
Underliggende grafikkmodell
• Matrise av punkter
– adresseres med x,ykoordinater (doubleverdier)
– hvert punkt er kvadratisk (!)
• Hvert punkt har en farge
– en kan bruke et visst antall farger på en gang (2, 256, ..., 2^24)
– en farge er satt sammen av mengden rødt, grønt og blått, hver angitt som
et tall mellom 0 og 255 (8 bit)
– noen systemer tillater også en gjennomsiktighetsverdi (alphakanal)
– fargekonstanter for de vanligste fargene finnes i Colorklassen
• Grafikkprimitiver
– omsettes til sett av punktverdier (rasterering)
– kombineres med punktene som er der fra før,
som regel ved å overskrive fargeverdien som er der fra før
7
Graphics2Dobjektet
• Alt som vises i vinduet er resultatet av kall
til Graphics2Dmetoder
• Graphics2Dobjekter brukes også for å
tegne bilder (Image) programmatisk
• Nøkkelen til grafikkprogrammering ligger i
å forstå mulighetene som Graphics2D
objektet gir!
8
Graphics2D og bilder
• Graphics2D har metoder for å tegne bilder
– alle heter drawImage og tar inn et Image og en posisjon (x, y)
– bilder kan skaleres ved å angi en størrelse (bredde, høyde) som
bildet tegnes innenfor
• Bilder representeres generelt av klassen Image,
med BufferedImage som den mest
anvendelige subklassen
• Bilder kan lages på flere måter
– en bildefil kan lastes inn, f.eks. angitt ved en URL
– en kan lage tomme (og gjennomsiktige) bilder som siden kan
tegnes på vha. et spesielt Graphics2Dobjekt (mer om det siden)
9
Innlesing av bilder
• ImageIOklassen inneholder statiske
metoder for bl.a. å lese inn bilder
– ImageIO.read(InputStream) – fra strøm
– ImageIO.read(URL) – fra URL, f.eks. http:// eller file:/
– ImageIO.read(File) – fra File, f.eks. C:/temp/
• readmetodene returnerer BufferedImage
instanser, som kan
– tegnes vha. Graphics2D med g2d.drawImage(BufferedImage,
BufferedImageOp op, int x, int y) // op kan være null
– tegnes på vha. et spesiell Graphics2Dobjekt (mer om det siden)
10
Innlesing av bilder
• Bilder kan legges inn i et Javaprosjekt og
leses inn vha. en spesiell teknikk
– legg bildefilen(e) i undermapper til en mappe som er markert som
sourcemappe, f.eks. direkte i srcmappa eller en egen resources
mappe
– lag en InputStream til filen vha.
obj.getClass().getResourceAsStream(”<filnavn>”);
– obj er et objekt definert i prosjektet ditt og kan gjerne være this
– filnavn er enten
• et absolutt filnavn med sti tilsvarende pakkestrukturen
• et relativt filnavn (evt. uten sti), tilsvarende pakkestrukturen ift. obj
sin pakke
– InputStreamobjektet gis så til ImageIO.read(InputStream) og du
får et BufferedImage i retur
11
Innlesing av bilder: Eksempel
• En klasse MyComponent
ligger i pakken java2d i
srcmappa (se figur)
• En bildefil hal.PNG
ligger i pakken/mappen
java2d i resourcesmappa
– resourcesmappa er laget vha. New>Source Folder... eller som en vanlig mappe og
markert som en sourcemappe, vha. høyreklikk og Build Path>Use as Source Folder
– undermapper lages vha. New>Package, som vanlig
• I MyComponentklassen kan en nå lage en InputStream til
filen vha.
– // absolutt sti
this.getClass().getResourceAsStream(”/java2d/hal.PNG”);
– // relativ sti til MyComponent sin pakke
this.getClass().getResourceAsStream(”hal.PNG”);
12
Lage tomt og
gjennomsiktig bilde
public BufferedImage lagGjennomsiktigBilde(int w, int h) {
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
int rød = 0, grønn = 0, blå = 0, transparens = 255;
int fargeverdi = rød << 24 | grønn << 16 | blå << 8 |
transparens;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, fargeverdi);
}
}
return image;
}
13
Tegne på et bildeobjekt
• En lager et spesielt Graphics2Dobjekt for
bildet, vha. Image.createGraphics()metoden
public Image lagBildetegning (int w, int h) {
BufferedImage image = lagGjennomsiktigBilde(w, h);
// lag et Graphics2D-objekt for å tegne i bildet
Graphics2D graphics = image.createGraphics();
graphics.drawLine(0, 0, w, h);
// si fra at graphics-objektet ikke trengs mer
graphics.dispose();
return image;
}
14
Tegne på et bildeobjekt
• En kan også be en JComponent om å tegne i
bildet, ved å kalle paintmetoden med en
bildeGraphics2D
public Image lagJComponentbilde(int w, int h,
JComponent comp) {
BufferedImage image = lagGjennomsiktigBilde(w, h);
Graphics2D graphics = image.createGraphics();
comp.setSize(w, h);
comp.paint(graphics);
graphics.dispose();
return image;
}
15
Tegne på et bildeobjekt
• En kan lage et bilde med tekst i, vha. JLabel
public Image lagTekstbilde(int w, int h, String s) {
JLabel label = new JLabel(s);
return lagJComponentbilde(w, h, label);
}
• En kan også lage en Cursor (muspeker) vha. et bilde!
public static Cursor lagCursor(Image image,
String name, int x, int y) {
return Toolkit.getDefaultToolkit().createCustomCursor(
image, new java.awt.Point(x, y), name);
}
16
Graphics2Dtilstander
• font – Font
• farge – Color
• transformasjon – Transform
• blandingsregel – Composite
• maling – Paint
• strek – Stroke
17
Output av grafikk
• Koordinatsystem
– lokalt koordinatsystem oversettes til enhetskoordinater
– koordinater kan speiles (x) og forskyves (x+dx)
– generelle transformasjoner
18
Transformasjoner
• Før grafikkprimitiver gjøres om til fargede
punkter, utføres en transformasjon på
koordinatene
• De nye koordinatene beregnes vha. en formel
– x’ = m11 x + m12 y + m1
– y’ = m21 x + m22 y + m2
• Eller på matriseform
[ m11 m12
m21 m22 ] [ ] +[ ] = [ ]
x
y
m1
m2
x’
y’
19
Transformasjoner...
• Ved riktig oppbygning av matrisen, kan
mange effekter oppnås
• translasjon
(dx, dy)
[ 1 0 dx
0 1 dy ]
• skalering
(x0, y0, sx, sy)
[sx 0 x0(1-sx)
0 sy y0(1-sy) ]
20
• rotasjon(ø) [cos ø -sin ø 0
sin ø cos ø 0 ]
Transformasjoner...
• AffineTransformobjekter brukes for å
defineren transformasjonen knyttet til et
Graphics2Dobjekt
– graphics.setTransform(transform);
• AffineTransformklassen inneholder mange
hjelpemetoder for å lage de vanligste
matrisene:
– AffineTransform.getTranslateInstance(dx, dy);
– AffineTransform.getScaleInstance(sx, sy);
• Tranformasjonsmatriser kan settes sammen
for å få kombinert effekten
– t1.concatenate(t2); // t1 endres ved å multiplisere med t2
21
Persistent output
• Tegneprimitiver som objekter
– Istedenfor å tegne direkte vha. tegneprimitiver, kan en lage objekter
som tegner seg selv
– Java har standardklasser for flere 2dimenasjonale objekter som kan
brukes istedenfor tegneprimitivene
• Shapeobjekter representererer 2dimensjonale
figurer
– defineres vha. posisjon og utstrekning
– vet om et punkt er på innsiden eller utsiden
• Displayliste
– kontinuerlig visning av tegneobjekter, f.eks. Shapeobjekter
– tegning gjennom manipulering av liste
• sette inn og fjerne elementer
• endre objektattributter
• Forenklende og raskere
• God støtte for valg av grafiske objekter
22
Oppdatering av grafikk
• paintmetoden(e) kalles automatisk når vinduet trenger
oppfriskning
– når vinduet vises første gang
– når komponenten gjøres synlig vha. setVisible
– når brukeren aktivt får vinduet/komponenten til å bli synlig, f.eks. i en JTabbedPane
• Det er bare i paint/paintComponentmetoden en kan tegne
– trenger et Graphics2Dobjekt og dette kan ikke brukes utenfor paintmetodene
• Når en endrer på et objekt på som skal tegnes, f.eks. i
mousePressed og mouseDraggedmetoden, har en ikke noe
Graphics2Dobjekt å tegne med.
• Nøkkelen er å utføre endringen på Shapeobjektene (eller
hva en nå bruker), og så be Swing utføre den nødvendige
oppfriskningen av skjermen/vinduet/komponenten
– repaint()
23
repaintmetoden
• repaintmetoden brukes for å be Swing utføre den
nødvendige oppfriskningen av
skjermen/vinduet/komponenten:
– public mouseDragged(MouseEvent me) {
// endre på objektet som manipuleres med musa
rect.setRect(e.getX(), e.getY(), 20, 20);
// tving frem oppfriskning av komponentens innhold
repaint();
}
• Repaint ber systemet om å trigge oppfrisning av
skjerminnholdet. Dette vil skje så snart som mulig, men
først etter at lyttermetoden din er ferdig.
– lyttermetoder som mousePressed og mouseDragged utfører endring, kaller repaint
og returnerer
– systemet vil så kalle paint på de nødvendige komponentene, for å at innholdet skal
bli oppdatert
• Når man endrer en komponent, f.eks. label.setText() så blir
repaint kalt av komponenten, men når vi lage
24
komponenten selv, må vi også gjøre den delen av jobben
Læringsmål for
forelesningen
• Objektorientering
– Objektorientert grafikk
• Javaprogrammering
– Grafikk med Java2D
– Egne Swingkomponenter
25