INF 1010, vår 2005 Løsningsforslag uke 10

Like dokumenter
INF 1010, vår 2005 Løsningsforslag uke 11

INF1010 Grafisk brukergrensesni3 med Swing og awt del 1 INF1010

Grafisk Brukergrensesnitt

INF1010. Grafisk brukergrensesni. med Swing og awt del 2. INF Grafisk brukergrensesni4 II

Vi lærte sist å lage vinduer. Om å lage et vindu. GUI (Graphical User Interface)-programmering. Inf GUI - del 2

LO191D/LC191D Videregående programmering

Gjennomgang av eksamen H99

INF1010 våren 2017 Onsdag 25. januar. Litt om unntak i Java

UNIVERSITETET I OSLO

INF1010 våren 2019 Onsdag 30. januar. Mer om unntak i Java (med litt repetisjon av I/O først)

Algoritmer og datastrukturer Kapittel 3 - Delkapittel 3.1

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

import javax.swing.*; import java.awt.*;

Grafiske brukergrensesnitt med Swing og AWT

Uke mars 2005 GUI - del 2. GUI (Graphical User Interface)-programmering

EKSAMEN. TILLATTE HJELPEMIDLER: Alle trykte og skrevne. INNFØRING MED PENN, evt. trykkblyant som gir gjennomslag

INF Våren Li' repe$sjon om Tråder og GUI. Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo. Ins$tu' for informa$kk

Post-it spørsmål fra timen (Arv og subklasser)

Eksamen. Objektorientert Programmering IGR 1372

UNIVERSITETET I OSLO Det matematisk-naturvitenskapelige fakultet

INF1010 våren 2018 tirsdag 23. januar

TOD063 Datastrukturer og algoritmer

INF1010 Grafisk brukergrensesni3 (GUI) med Swing/awt. del 1

INF Notater. Veronika Heimsbakk 10. juni 2012

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

Forelesning inf Java 4

6108 Programmering i Java. Leksjon 8. GUI: Grafisk brukergrensesnitt. Del 2: Roy M. Istad 2015

INF1010. Grafisk brukergrensesni. med Swing og awt del 2

AVDELING FOR INGENIØRUTDANNING EKSAMENSOPPGAVE. Antall sider (Inkl forsiden): 8. Alle trykte og håndskrevne

Vi lærte sist å lage vinduer. Om å lage et vindu. GUI (Graphical User Interface)-programmering. GUI - del 2

Oblig 4Hybelhus litt mer tips enn i oppgaven

GUI - del 2. Stein Gjessing Inst for Informatikk Univ. i Oslo

. Ved sensur vl1 ahe bokstaverte deloppgaver (a, b, c,...) telle like mye.

1. Finn klassene (hvilke objekter er det i problemet) 1. Dataene som beskriver problemet (hvilke objekter har vi og hvor mange klasser er det?

HØGSKOLEN I SØR-TRØNDELAG Avdeling for informatikk og e-læring AITeL

Inf 1010 GUI - del 2

UNIVERSITETET I OSLO

Forkurs INF1010. Dag 3. Andreas Færøvig Olsen Gard Inge Rosvold Institutt for Informatikk, 15.

INF1000: noen avsluttende ord

Forkurs INF1010. Dag 3. Andreas Færøvig Olsen Eivind Storm Aarnæs

JPanel. Komponent hieraki. Window/JWindow. Applet/JApplet. JDialog. JFrame

INF1010 våren 2006 Uke 19: 9. mai 2006 Et større eksempel: Solitaire (kabal)

Løsningsforslag Test 2

UNIVERSITETET I OSLO

Lenkelister. Lister og køer. Kopi av utvalgte sider fra forelesningen.

UNIVERSITETET I OSLO

Algoritmer og datastrukturer Kapittel 11 - Delkapittel 11.2

INF1000 : Forelesning 4

UNIVERSITETET I OSLO

INF1010, 22. mai Prøveeksamen (Eksamen 12. juni 2012) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

i=0 i=1 Repetisjon: nesting av løkker INF1000 : Forelesning 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker j=0 j=1 j=2 j=3 j=4

Oppgave 1. INF1000 Uke 13. Oppgave 2. Oppgave 3. Er dette lovlige deklarasjoner (når de foretas inni en metode)? JA NEI

UNIVERSITETET I OSLO

Spørsmål fra forrige forelesning. INF1000 Forelesning 7. Oppførselen til inword()/inint()/etc. Operator-presedens i Java

INF1000 EKSTRATILBUD. Stoff fra uke 1-5 (6) 3. oktober 2012 Siri Moe Jensen

LC191D/LO191D Videregående programmering mai 2010

INF 1000 Prøveeksamen. 23. november Ole Christian og Arne. Oppgave 1 (10 poeng) Er disse programsetningene lovlige i Java? Oppgave 2 (10 poeng)

Oblig 4 (av 4) INF1000, høsten 2012 Værdata, leveres innen 9. nov. kl

INF1000 (Uke 15) Eksamen V 04

INF1000 (Uke 15) Eksamen V 04

Graphics. Grafikk. Praktisk sett: Koordinatsystemet. kodeeksempel

UNIVERSITETET I OSLO

3 emner i dag! INF1000 Uke 5. Objekter og pekere. null. Litt om objekter, pekere og null Filer og easyio Litt mer om tekster

UNIVERSITETET I BERGEN Det matematisk-naturvitenskapelige fakultet

Eks 1: Binærtre Binærtretraversering Eks 2: Binærtre og stakk

Løsningsforslag ukeoppg. 6: 28. sep - 4. okt (INF Høst 2011)

INF Uke 10. Ukesoppgaver oktober 2012

INF Seminaroppgaver til uke 3

Oppgave 1. Oppgave 2. Oppgave 3. Prøveeksamen i INF1000. Ole Christian og Arne. 23. november 2004

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister

INF1000: Forelesning 11. Oppgave 2. Oppgave 1. Husk å melde deg på prøveeksamen i INF1000! Ole Christian Lingjærde 7.november 2006

UNIVERSITETET I OSLO

Introduksjon til objektorientert programmering

UNIVERSITETET I OSLO

Introduksjon til objektorientert. programmering. Hva skjedde ~1967? Lokale (og globale) helter. Grunnkurs i objektorientert.

Prøveeksamen i INF1000. Ole Christian og Arne. 23. november 2004

UNIVERSITETET I OSLO

Innhold uke 4. INF 1000 høsten 2011 Uke 4: 13. september. Deklarasjon av peker og opprettelse av arrayobjektet. Representasjon av array i Java

Gjøre noe i hele treet = kalle på samme metode i alle objekten. Java datastruktur Klassestruktur

TDT4100 Objektorientert programmering

GUI («Graphical User Interface») del 2

BOKMÅL Side 1 av 7. KONTINUASJONSEKSAMEN I FAG TDT4100 Objektorientert programmering / IT1104 Programmering, videregående kurs

Inf1010 Våren Feilsituasjoner og unntak i Java. Stein Gjessing, Institutt for informatikk, Universitetet i Oslo

UNIVERSITETET I OSLO

HØGSKOLEN I SØR-TRØNDELAG

UNIVERSITETET I OSLO

IN Notat om I/O i Java

Tre måter å lese fra terminal. Java 4. Eksempel. Formatert utskrift til skjerm

Forelesningsquiz. Forelesning inf Java 5. Sett dere to (eller tre) sammen og besvar de fire spørsmålene på utdelt ark. Tid: 15 min.

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister Videre

UNIVERSITETET I OSLO

Oppsummering. Kort gjennomgang av klasser etc ved å løse halvparten av eksamen Klasser. Datastrukturer. Interface Subklasser Klasseparametre

Hittil har programmene kommunisert med omverden via tastatur og skjerm Ønskelig at data kan leve fra en kjøring til neste

Forelesning inf Java 5

"behrozm" Oppsummering - programskisse for traversering av en graf (dybde først) Forelesning i INF februar 2009

Forelesning inf Java 5

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

Stein Gjessing, Institutt for informatikk, Universitetet i Oslo

Leksjon 7. Filer og unntak

TDT4100 Objektorientert programmering

Transkript:

INF 1010, vår 2005 Løsningsforslag uke 10 Anders Brunland 1. april 2005 Oppgave 1 Oppgave 15.4 i i Rett på Java. Løsningsforslag De forskjellige komponentene settes i metoden initcomponents. Her settes også lyttere til de to knappene. Det gjøres med anonyme klasser. En anonym klasse er en klasse som ikke har noe navn. Det vil si at objektet lages samtidig med at klassen deklareres. Konstruksjonen ser slik ut: new AbstractAction () { lesfil (); Her lages det en klasse som er en subklasse av den abstrakte klassen AbstractAction. AbstractAction-klassen har en abstrakt metode som må overskrives, nemlig metoden actionperfomed. Det gjøres i den anonyme klassen hvor metoden inneholder et kall videre til lesfil-metoden. Objektet lages (som vanlig) ved å bruke nøkkelorden new. Hele konstruksjonen over sendes som en parameter til addactionlistener-metoden til den aktuelle knappen. Dermed blir koden slik: lesfilknapp. addactionlistener ( new AbstractAction () { lesfil (); ); Programmet er listet i avsnitt A.1. Oppgave 2 Ta utgangspunkt i ko- Jobbing videre med frihåndstegne-programmet den MuseDemo.java og legg til følgende forbedringer: 1

Generell organisasjon av programmet Før jeg viser hvordan de enkelte delene i oppgaven er løst, vil jeg vise hvordan programmet er organisert. Programmet består av to klasser: Tegner og Tegnelerret (listet i avsnitt A.2 og A.3). Figur 1 viser programmet under kjøring. Figur 1: Skjermdump av Tegneprogrammet Klassen Tegnelerret er en subklasse av JPanel. Tegnelerrettet er i stand til å oppfatte hendelsen at en knapp på musa holdes nede, og at musa beveges. Når dette skjer, lagres posisjonen til musa i to arrayer, xpos og ypos, og en teller som angir antall punkter økes. Deretter kalles det på metoden repaint. Dette metodekallet er et signal til systemet om at det skal tegne opp komponenten på nytt. Systemet kaller da på metoden paintcomponent og sender med et objekt av typen Graphics, som representerer flaten det skal tegnes på. I Tegnlerret-klassen er paintcomponent-metoden overskrevet. Her går jeg igjennom alle koordinatene, og tegner strek mellom disse. Klassen Tegner er en subklasse av JFrame, og utgjør kontrolldelen av programmet. Tegnlerretklassen legges inn i CENTER-delen av JFramen. Knapper legges i en rekke til venstre (de samles i et eget JPanel som legges i WEST). Hver knapp har en egen anonym lytteklasse. Når brukeren for eksempel trykker på knappen for å slette tegningen (knappen merket clr ), kalles det på en metode (clear) på tegnelerretet. Figur 2 på neste side viser et forenklet klassediagram. Det opprinnelige programmet inneholder en bug hvis man tegner lenge nok, blir arrayene som holder på koordinatene fulle. Jeg har derfor lagt inn en metode som dobler størrelsen på arrayene når disse blir fulle. 2

JFrame JPanel Registrerer brukerens valg (via knapper) og oppdaterer attributtene i tegnlerretet. Eksempel på attributter som oppdateres er farge og tykkelse. Tegner Tegnelerret JButton Knapp Ansvar for tegningen. Registrerer musas bevegelser over komponenten, oppdaterer koordinatene og (via kall på repaint) tegner streker mellom koordinatene. Figur 2: Forenklet klassediagram for tegneprogrammet 3

a) Gjør det mulig å tegne flere uavhengigige streker (ikke bare en lang strek) Hint: du bør oppdage når noen slipper museknappen (du må implementere nok et grensesnitt) og da sette inn 0 i x- og y-arrayen for å signalisere slutt på et linjesegnent og begynnelse på neste. Samtidig i utttegningen må du aldri tegne hverken til eller fra verdien 0. Får du ikke til dette - se filen: Muse2Demo.java Løsningsforslag To endringer må til. I tillegg til å lytte på musebevegelser, må vi lytte på knappene på musa. Grensesnittet vi må implementere for dette heter MouseListener, og inneholder fem metoder. I midlertid er vi kun interessert i en av metodene, nemlig den som kalles når en museknapp slippes opp. I stedet for å implementere grensesnittet (og alle fem metodene) velger jeg derfor å lage lytteklassen som en subklasse av den abstrakte klassen MouseAdapter. MouseAdapter er en hjelpeklasse som gir en tom definisjon av alle metodene i MouseListenergrensesnittet. For eksempel er metoden mouseclicked implementert slik: public void mouseclicked ( MouseEvent e) { Fordelen med dette, er at jeg da kun trenger å skrive over den metoden jeg er interessert i, nemlig mousereleased: public void mousereleased ( MouseEvent e) { xpos [ ant ] = Integer. MIN_VALUE ; ypos [ ant ] = Integer. MIN_VALUE ; ant ++; Legg merke til at jeg bruker verdien Integer.MIN_VALUE som signal på at jeg ikke skal tegne en strek. I tegnemetoden sjekker jeg nå om det skal tegnes en strek mellom et punkt og forrige, ved ganske enkelt å teste mot verdien over i for-løkka som løper gjennom alle punktene: for ( int i = 1; i < ant ; i ++) { if ( xpos [i] > Integer. MIN_VALUE ) { g. drawline ( xpos [i - 1], ypos [i - 1], xpos [i], ypos [i ]); else { i ++; Legg merke til at hvis jeg ikke skal bruke punktet (dvs. at if-testen ikke slår til) økes verdien på i med to før neste iterasjon; én i else-grenen, og én som en del av forløkka. Effekten er at punktet hoppes over ved tegning. b) Legg farge på linjene. Hint: Innfør nok en array som hele tiden holder rede på hvilken fage et linjesegnemt har (se hvordag du setter farge i class Graphics i java-dok en). Du må selvsagt ogå innføre noen trykksnapper slik at brukeren kan velge farge ved f.eks å trykke på Rødknappen. 4

Løsningsforslag Jeg oppretter en array til som holder fargen for et gitt punkt. Metoden for å sette farge det skal tegnes med heter setcolor. For-løkka som gjør tegningen blir dermed slik: for ( int i = 1; i < ant ; i ++) { if ( xpos [i] > Integer. MIN_VALUE ) { g. setcolor ( farge[i ]); g. drawline ( xpos [i - 1], ypos [i - 1], xpos [i], ypos [i ]); else { i ++; c) Som b) men nå valg av tynnere eller tykkere linje.. Løsningsforslag Innfører en array til, som skal holde orden på tykkelsen til en gitt strek. En global variabel tykkelse økes eller minskes avhengig av hvilken knapp brukeren trykker. For å tegne en tykkere strek, bruker jeg metoden setstroke, som finnes i graphics-objektet. Dvs. - det finnes i et objekt av typen Graphics2D, som er en subklasse av Graphics. Objektet som blir sendt til paintcomponent-metoden har en metode som returnerer et nytt graphics-objekt (metoden create). Dette objektet kan omtypes ( castes ) til et Graphics2D objekt. I tillegg flytter jeg tegningen til en egen metode. De to metodene (paintcomponent og tegn blir slik: public void paintcomponent ( Graphics g) { super. paintcomponent (g ); Graphics2D g2d = ( Graphics2D ) g. create (); for ( int i =1; i< ant ; i ++) { if ( xpos [i] > Integer. MIN_VALUE ) { g2d. setcolor ( farge [i ]); tegn (g2d, i ); else { i ++; g2d. dispose (); void tegn ( Graphics2D g, int i) { float tykkelse = tykk [ i] + 1; // minste mulige tykkelse på en // strek er 1. g. setstroke ( new BasicStroke ( tykkelse )); // setter tykkelsen int x1 = xpos [i -1], x2 = xpos [i], y1 = ypos [i -1], y2 = ypos [i]; g. drawline (x1, y1, x2, y2 ); 5

d) Viskelær. Ved å trykke på en knapp som du legger inn, skal brukeren kunne skru av og på viskelærfunksjonen. Når den er på, skal alle punkter som er inenfor en bestemt radius (eks 10 pkt) fra musa, settes = 0. Hele tida mens du visker, skal effekten framvises på skjermen. (Bruk selvsagt Pytagoras til å finne avstanden mellom musas nåværende posisjon og alle punktene) Løsningsforslag Her velger jeg en litt annen fremgangsmåte en den som er antydet i oppgaven. Jeg innfører en bolsk variabel visk, som settes til true når brukeren velger viskelær. I tillegg øker jeg tykkelsen for punktet til 16, og setter fargen til å være den samme som bakgrunsfargen. e) Lagring og innlesning fra en fil på en tegning (bruk f.eks en dialog til å be om filnavmet). Løsningsforslag En dialog (inputdialog) lar brukeren skrive inn filnavn. Deretter skrives/leses antall punkter, og for hvert punkt, en linje med x-posisjonen, en linje med y- posisjonen, en linje med fargen og en linje med tykkelsen. For lesing/skriving bruker jeg klassene InExp og OutExp, som er superklasser til hhv. In- og Outklassene. Dette gjøres fordi jeg ønsker å kunne fange opp eventuelle feil som kan oppstå. Et eksempel på en slik feil er at brukeren ved lesing fra fil oppgir en fil som ikke finnes. Hvis det skjer, kastes et såkalt unntak (eng: Exception), som jeg kan fange opp. Unntak er behandlet i kapittel 19 i Rett på Java. A Programlistinger A.1 Editor.java import javax. swing.*; import java. awt.*; import java. awt. event.*; import easyio.*; import java.io.*; class Editor extends JFrame { JPanel filvindu ; JLabel filtekstlabel ; JTextField filnavnfelt ; JButton lesfilknapp ; JTextArea tekstvindu ; JButton lagrefilknapp ; String filnavn ; Editor () { initcomponents (); 6

layoutcomponents (); setdefaultcloseoperation( JFrame. EXIT_ ON_ CLOSE ); pack (); setvisible ( true ); void initcomponents () { filvindu = new JPanel (); // default flowlayout filtekstlabel = new JLabel (" Filnavn :"); filnavnfelt = new JTextField ( 20); filtekstlabel. setlabelfor ( filnavnfelt ); lesfilknapp = new JButton (" Les fil "); lesfilknapp. addactionlistener ( new AbstractAction () { lesfil (); ); filvindu. add ( filtekstlabel ); filvindu. add ( filnavnfelt ); filvindu. add ( lesfilknapp ); tekstvindu = new JTextArea (40, 60); tekstvindu. seteditable ( true ); tekstvindu. setlinewrap ( true ); tekstvindu. setwrapstyleword ( true ); lagrefilknapp = new JButton (" Lagre fil "); lagrefilknapp. addactionlistener ( new AbstractAction () { skrivfil (); ); void layoutcomponents () { Container lerret = getcontentpane (); lerret. add ( filvindu, BorderLayout. NORTH ); JScrollPane sc = new JScrollPane ( tekstvindu ); lerret. add (sc, BorderLayout. CENTER ); lerret. add ( lagrefilknapp, BorderLayout. SOUTH ); void skrivfil () { OutExp out = null ; String tmpfilnavn = filnavnfelt. gettext (); if ( tmpfilnavn. equals ( filnavn )) { int fortsett = JOptionPane. showconfirmdialog (this, " Gammel fil blir overskrevet \ nfortsett?", 7

" Skriv til fil ", JOptionPane. YES_ NO_ OPTION ); if ( fortsett == JOptionPane. NO_ OPTION ) { return ; filnavn = tmpfilnavn ; try { out = new OutExp ( filnavn ); out. outln( tekstvindu. gettext ()); catch ( IOException ioe ) { JOptionPane. showmessagedialog ( this, " Uventet feil ved skriving til fil " ); finally { if ( out!= null ) { out. close (); JOptionPane. showmessagedialog ( this, " Fil lagret." ); void lesfil () { filnavn = filnavnfelt. gettext (); InExp in = null ; try { in = new InExp ( filnavn ); tekstvindu. settext (""); while (! in. endoffile ()) { tekstvindu. append (in. inline () + "\n"); catch ( FileNotFoundException fne ) { JOptionPane. showmessagedialog (this, " Fant ikke filen" ); catch ( IOException ioe ) { JOptionPane. showmessagedialog ( this, " Uventet feil ved lesing fra fil." ); public static void main ( String [] args ) { new Editor (); A.2 Tegner.java import javax. swing.*; 8

import java. awt.*; import java. awt. event.*; import easyio.*; import java.io.*; class Tegner extends JFrame { Tegnelerret lerret ; Tegner () { super (" Tegneprogram "); lerret = new Tegnelerret (); getcontentpane (). add ( lerret, BorderLayout. CENTER ); JButton clr = new JButton (" clr " ); clr. addactionlistener ( new AbstractAction () { lerret. clear (); ); JButton rød = new JButton (" rød " ); rød. addactionlistener ( new AbstractAction () { lerret. setcolor ( Color. red ); ); JButton grønn = new JButton (" grønn "); grønn. addactionlistener ( new AbstractAction () { lerret. setcolor ( Color. green ); ); JButton sort = new JButton (" sort " ); sort. addactionlistener ( new AbstractAction () { lerret. setcolor ( Color. black ); ); JButton tykk = new JButton (" tykkere "); tykk. addactionlistener ( new AbstractAction () { lerret. tykkere (); ); JButton tynn = new JButton (" tynn " ); tynn. addactionlistener ( new AbstractAction () { lerret. tynnere (); ); JButton visk = new JButton (" viskelær "); 9

visk. addactionlistener ( new AbstractAction () { lerret. visk (); ); JButton tilfil = new JButton (" lagre "); tilfil. addactionlistener ( new AbstractAction () { tilfil (); ); JButton frafil = new JButton (" åpne "); frafil. addactionlistener ( new AbstractAction () { frafil (); ); JPanel knapper = new JPanel ( new GridLayout (0, 1)); knapper. add ( clr ); knapper. add ( visk ); knapper. add ( sort ); knapper. add ( rød ); knapper. add ( grønn ); knapper. add ( tykk ); knapper. add ( tynn ); knapper. add ( tilfil ); knapper. add ( frafil ); getcontentpane (). add ( knapper, BorderLayout. WEST ); pack (); setlocation ( 200, 200); setdefaultcloseoperation( JFrame. DISPOSE_ ON_ CLOSE ); setvisible ( true ); void tilfil () { int ant = lerret. getant (); int [] x = lerret. getxpos (); int [] y = lerret. getypos (); Color [] c = lerret. getcolor (); int [] t = lerret. gettykkelse (); String filnavn = JOptionPane. showinputdialog ( this, " filnavn : " ); OutExp fil = null ; try { fil = new OutExp ( filnavn ); 10

fil. outln( ant ); for ( int i = 0; i < ant ; i ++) { fil. outln(x[i ]); fil. outln(y[i ]); fil. outln(c[i]. getrgb ()); fil. outln(t[i ]); catch ( FileNotFoundException fn) { JOptionPane. showmessagedialog ( this, " Fant ikke filen "); catch ( IOException e) { JOptionPane. showmessagedialog ( this, " Feil ved skriving til fil "); finally { if ( fil!= null ) { fil. close (); public void frafil () { String filnavn = JOptionPane. showinputdialog ( this, " filnavn : " ); InExp fil = null ; try { fil = new InExp ( filnavn ); int ant = fil. inint (); int [] x = new int [ ant ]; int [] y = new int [ ant ]; Color [] c = new Color [ ant ]; int [] t = new int [ ant ]; for ( int i = 0; i < ant ; i ++) { x[i] = fil. inint (); y[i] = fil. inint (); c[i] = new Color ( fil. inint ()); t[i] = fil. inint (); lerret. setant ( ant ); lerret. setxpos (x); lerret. setypos (y); lerret. setcolor (c); lerret. settykkelse (t); lerret. repaint (); catch ( FileNotFoundException fn) { JOptionPane. showmessagedialog ( this, " Fant ikke filen "); catch ( IOException e) { JOptionPane. showmessagedialog ( this, " Feil ved skriving til fil "); 11

public static void main ( String [] args ) { new Tegner (); A.3 Tegnelerret.java import java. awt.*; import java. awt. event.*; import javax. swing.*; class Tegnelerret extends JPanel { final int xdim = 300, ydim =300; // Default størrelse på lerret int size = 1024; int [] xpos, ypos ; int ant = 0; Color [] farge ; int [] tykk ; Color color = Color. black ; int tykkelse = 0; int gmltykkelse = 0; boolean visk = false; Tegnelerret () { super ( true ); // DubbelBufferet, gjør tegningen mer effektiv. doinit (); dolayout (xdim, ydim ); * Indre lytteklasse, fanger opp to hendelser : 1) Musa " dras ", og * at knappen slippes. class Lytter extends MouseAdapter implements MouseMotionListener { // MouseAdapter public void mousereleased ( MouseEvent e) { if ( ant == xpos. length ) { doublesize (); xpos [ ant ] = Integer. MIN_VALUE ; ypos [ ant ] = Integer. MIN_VALUE ; tykk [ ant ] = tykkelse ; farge [ ant ] = color ; ant ++; 12

// MouseMotionListener public void mousedragged ( MouseEvent e) { if ( ant == xpos. length ) { doublesize (); xpos [ ant ]= e. getx (); ypos [ ant ]= e. gety (); farge [ ant ] = color ; tykk [ ant ] = tykkelse ; ant ++; repaint (); // MouseMotionListener ( bryr meg ikke om denne hendelsen ) public void mousemoved ( MouseEvent e) {; /* * Initierer arrayene void doinit () { xpos = new int [ size ]; ypos = new int [ size ]; farge = new Color[ size ]; tykk = new int [ size ]; Lytter l = new Lytter (); // indre klasse. addmousemotionlistener( l); addmouselistener ( l ); * Setter størrelsen på lerretet void dolayout ( int xdim, int ydim ) { setpreferredsize ( new Dimension ( xdim, ydim )); * Sletter tegninen void clear () { ant = 0; repaint (); * Setter fargen som det skal tegnes med void setcolor ( Color c) { if ( visk ) { 13

tykkelse = gmltykkelse ; visk = false; color = c; * Øker tykkelsen på streken void tykkere () { tykkelse ++; * Minsker tykkelsen på streken void tynnere () { if ( tykkelse > 0) tykkelse --; * Setter tykkelsen opp, og setter fargen til den samme som * bakgrunnsfargen. Resultatet er at det blir et viskelær. void visk () { visk = true ; color = getbackground (); gmltykkelse = tykkelse ; tykkelse = 16; * Tegner opp strekene mellom koordinatene. Blir kalt av systemet * når det er behov for å tegne komponenten på nytt. Det skjer * enten når systemet finner ut at komponenten trenger å tegnes * opp ( for eksmpel etter at vinduet har blitt flyttet ), eller * etter at metoden repaint har blitt kalt. public void paintcomponent ( Graphics g) { super. paintcomponent ( g); Graphics2D g2d = ( Graphics2D ) g. create (); // Henter ut et // Graphics2D - objekt, // som inneholder // litt fler // metoder enn det // " trauste " // Graphics - objektet // ( bl.a. metoden // for å sette // tykkelsen på // streken. for ( int i =1; i< ant ; i ++) { if ( xpos [i] > Integer. MIN_VALUE ) { g2d. setcolor ( farge [i ]); 14

tegn (g2d, i); else { i ++; g2d. dispose (); // Dokumentasjonen anbefaler at man kaller // denne metoden til slutt for å frigjøre // resurser. * Metoden som tegner strek mellom to punkter. void tegn ( Graphics2D g, int i) { float tykkelse = tykk [ i] + 1; // minste mulige tykkelse på en // strek er 1. g. setstroke ( new BasicStroke ( tykkelse )); // setter tykkelsen int x1 = xpos [i -1], x2 = xpos [i], y1 = ypos [i -1], y2 = ypos [i ]; g. drawline (x1, y1, x2, y2 ); * Returnerer antall punkter int getant () { return ant ; * Setter antall punkter void setant ( int ant ) { this. ant = ant ; * Returnerer alle x- koordinatene int [] getxpos () { return xpos ; * Setter alle x- koordinatene void setxpos ( int [] x) { xpos = x; * Returnerer alle y- koordinatene 15

int [] getypos () { return ypos ; * Setter alle y- koordinatene void setypos ( int [] y) { ypos = y; * Returnerer alle farger som brukes for hvert punkt Color [] getcolor () { return farge ; * Setter alle farger som skal brukes for hvert punkt void setcolor ( Color [] c) { farge = c; * Returnerer tykkelsen for hvert punkt int [] gettykkelse () { return tykk ; * Setter tykkelsen for hvert punkt void settykkelse ( int [] t) { tykk = t; * Hjelpemetode som dobler størrelsen på arrayene void doublesize () { int nsize = 2 * xpos. length ; int [] nx = new int [ nsize ]; int [] ny = new int [ nsize ]; Color [] nf = new Color [ nsize ]; int [] nt = new int [ nsize ]; System. arraycopy ( xpos, 0, nx, 0, xpos. length ); System. arraycopy ( ypos, 0, ny, 0, ypos. length ); System. arraycopy ( farge, 0, nf, 0, farge. length ); System. arraycopy ( tykk, 0, nt, 0, tykk. length ); 16

xpos = nx ; ypos = ny ; farge = nf ; tykk = nt ; size = nsize ; 17