DOA GUI-del 1 Grafik och Interaktionsprogrammering Skapa fönster, rita och ta hand om inmatning i Java Java och enkla grafiska gränssnitt Då man konstruerar enkla grafiska gränssnitt kan man med fördel använda Swing Eller det äldre, men mindre generella/eleganta, AWT Vi börjar med att på ett pragmatiskt sätt diskutera hur enkla grafiska komponenter som inmatningsfält, knappar, mus och 2D-grafik kan hanteras Björn Eiderbäck bjorne@nada.kth.se Först fokuserar vi på grunderna i Swing, med exemplifiering av hur fönster, knappar, inmatningsfält och andra enkla komponenter (widgets) kan konstrueras och hanteras. Vid nästa föreläsning fokuserar vi på modeller, men återkommer också med flera exempel. previous next previous next 2 Fönster JFrame Kodexempel Vi tittar på Java/Swing genom att steg för steg (pragmatiskt!) konstruera en tillämpning med några textinmatningsfält med rubriker, ett fält att rita på, och en knapp. Vi kommer konstruera en tillämpning som ser ut i stil med följande figur Rubrik JLabel Inmatningsfält JTextField Rityta (i detta fall en) JPanel På vilken en text ritats ut Knapp JButton Dessa objekt Grupperade via en JPanel previous next 3 Steg för steg 1. Skapa fönster 2. Skapa knapp Lägg den på fönsterytan 3. Skapa inmatningsfält för text som ska visas Koppla knappbeteende så att det man skrivit in i fältet visas på terminalen vid knapptryck 4. Skapa utritningsyta Koppla ihop knappens beteende så att den ritar texten från fältet på ytan istället 5. Ge koordinater för utritning via inmatningsfält Ordna layouten med inre panel Ta hand om eventuella fel 6. Kompilera och kör previous next 4 1. Skapa fönster Koden skrivs på föreläsningen 2. Skapa knapp Lägg den på fönsterytan previous next 5 previous next 6
3. Skapa inmatningsfält för text som ska visas 4. Skapa utritningsyta Koppla knappbeteende så att det man skrivit in i fältet visas på terminalen vid knapptryck Koppla ihop knappens beteende så att den ritar texten från fältet på ytan istället previous next 7 previous next 8 5. Ge koordinater för utritning via inmatningsfält Styr var utritningen ska hamna via koordinater i givna i fält 6. Kompilera och kör Ordna layouten med inre panel Ta hand om eventuella fel previous next 9 previous next 10 Hela kodexemplet i main För överskådlighetens skull skriver vi första versionen av exemplet helt i en main-metod. En sak man då speciellt måste tänka på är att final-deklarera variabler som man vill skicka meddelanden till i inre anonyma klasser package doa1; Om vi ska göra det snyggt så definierar vi ett eget paket (fast man kan klara sig utan paket) Vi behöver använda oss av en del klasser i dessa paket så vi importerar dem (för enkelhets skull hela paketen) previous next 11 public class MyTest1 { fönster public static void main(string[] args) { Dess container knapp inmatningsfält Panel att lägga saker på Panel att rita på Dess storlek Placera i mitten JFrame f = new JFrame("Test"); Container container = f.getcontentpane(); JButton button = new JButton("Rita"); final JTextField text = new JTextField(15); final JTextField xfield = new JTextField(3); final JTextField yfield = new JTextField(3); JPanel panel = new JPanel(); panel.add(new JLabel("Text: ")); panel.add(text); panel.add(new JLabel("x: ")); panel.add(xfield); panel.add(new JLabel("y: ")); panel.add(yfield); final JPanel component = new JPanel(); component.setpreferredsize(new Dimension(200, 200)); container.add(component, BorderLayout.CENTER); container.add(panel, BorderLayout.NORTH); container.add(button, BorderLayout.SOUTH); Vi måste final-deklarera om vi ska accessa variablerna från inre anonyma klasser Vi grupperar vissa objekt genom att lägga dom i en egen panel först Lägg komponenterna i fönstrets container, därmed kommer dom synas då vi öppnar fönstret previous next 12
Ta tag i en komponentens grafiska rityta Läs x- och y-koordinater från inmatningsfälten Rita ut texten på komponenten Beskriv vad som ska hända om man trycker på knappen button.addactionlistener(new ActionListener(){ public void actionperformed(actionevent arg0) { Graphics g = component.getgraphics(); int x, y; x = getcoordinate(xfield, 0); y = getcoordinate(yfield, 20); g.drawstring(text.gettext(), x, y); f.setsize(200, 300); f.pack(); f.setvisible(true); Öppna fönstret Fönsterstorlek Se till att komponenterna (layoutmässigt)ordnas efter sina beskrivningar Hjälpmetod private int getcoordinate(final JTextField field, int defaultint) { int intval = defaultint; try { intval = Integer.parseInt(field.getText()); catch (NumberFormatException e1) { ; ; return intval; ); previous next 13 previous next 14 Kodexemplet som klass package doa1; public class MyTest1 { static final String ButtonText = "Rita"; static final int FieldWidth = 3; static final int TextWidth = 15; static final Dimension ComponentDimension = new Dimension(200, 200); static final Point FieldPosition = new Point(0, 20); Om vi aldrig ändrar dessa värden i koden kan vi tydliggöra detta genom att finaldeklarera dessa konstanter. Om dom dessutom inte ska ändras eller anpassas på instansnivå kan vi deklarera dom som klassvariablet (static) public static void main(string[] args) { JFrame f = new JFrame("Test"); new MyTest1(f); f.setsize(200, 300); f.pack(); f.setvisible(true); protected Container container; protected JButton button; protected JTextField text; protected JTextField xfield; protected JTextField yfield; protected JPanel panel; protected JPanel component; Vi definierar komponenterna som instansvariabler previous next 15 previous next 16 public MyTest1(JFrame f) { container = f.getcontentpane(); createbasicwidgets(); populatepanel(); createdrawingcomponent(); populatecontainer(); definebuttonaction(); protected void createbasicwidgets() { button = new JButton("Rita"); text = new JTextField(15); xfield = new JTextField(3); yfield = new JTextField(3); panel = new JPanel(); protected void populatepanel() { panel.add(new JLabel("Text: ")); panel.add(text); panel.add(new JLabel("x: ")); panel.add(xfield); panel.add(new JLabel("y: ")); panel.add(yfield); protected void createdrawingcomponent() { component = new JPanel(); component.setpreferredsize(componentdimension); protected void populatecontainer() { container.add(component, BorderLayout.CENTER); container.add(panel, BorderLayout.NORTH); container.add(button, BorderLayout.SOUTH); previous next 17 previous next 18
protected void definebuttonaction() { button.addactionlistener(new ActionListener() { public void actionperformed(actionevent arg0) { Graphics g = component.getgraphics(); int x, y; x = getcoordinate(xfield, (int) FieldPosition.getX()); y = getcoordinate(yfield, (int) FieldPosition.getY()); g.drawstring(text.gettext(), x, y); private int getcoordinate(jtextfield field, int defaultint) { int intval = defaultint; try { intval = Integer.parseInt(field.getText()); catch (NumberFormatException e1) { ; ; return intval; ); previous next 19 Java 1.1: definiera utritning Använd "subklasstsrategin" Skriv över metoden paint(graphics g) Dvs skriv public void paint(graphics g) { // använd g för att rita metoden anropas automatiskt då fönstret behöver ritas om Med Med Swing bör bör man man använda metoden paintcomponent(graphics g) g) för för flertalet komponenter istället previous next 20 Java 1.1: rita text på fönstret Använd metoden drawstring(string str, int x, int y) i klassen Graphics public void paint(graphics g) { // vi skriver ut fönstrets höjd System.out.println(getHeight()); g.drawstring("här kommer en sträng halvägs ner i y-led", 20, //x-koordinat getheight() / 2); //y-koordinat Java I Java 1.1 är ritrutinerna ganska primitiva Man kan endast rita objekt med tjocklek 1 (ett) rita enklare typer av primitiva objekt hantera pixelkartor på ett begränsat sätt Man kan också använda tex färg och sätta klipprektangel I Java2D har vi fler möjligheter som tex rita splines och andra kurvor ange tjocklek på kanter ange typ av linje (tex rita streckad linjer mm) ange transformationer som skalning, translation och rotation rita genomskinligt eller ange att antialiasing skall användas previous next 21 previous next 22 Java 1.1: rita ickefyllda grafiska objekt Några exempel linje gc.drawline(int x1, int y1, int x2, int y2); oval gc.drawoval(int x, int y, int width, int height); rektangel gc. drawrect(int x, int y, int width, int height); polygon gc. drawpolyline(int xpoints[], int ypoints[], int npoints); alt gc. drawpolygon(polygon p); Java 1.1: rita fyllda grafiska objekt oval gc.filloval(int x, int y, int width, int height); rektangel gc.fillrect(int x, int y, int width, int height); polygon gc.fillpolygon(int[] xpoints, int[] ypoints, int npoints) eller gc.fillpolygon(polygon p) previous next 23 previous next 24
Java 1.1: rita med olika färg ändra färg gc.setcolor(color c) Java 1.1: rita bilder Hämta bild från fil (i ett Frame-program) Image image = gettoolkit().getimage(imagefile); rita med XOR-mod, dvs alternera mellan den grafiska kontextens färg och den givna gc.setxormode(color c1) Rita bilden på grafiska kontexten (skalad att passa in i given rektangel) gc.drawimage(image, posx, posy, width, height, bgcol, this); previous next 25 previous next 26 Enkelt exempel public class LiteGrafikTest extends JFrame { public void paint(graphics g) { //Rita sträng g.drawstring("hallå", 10, 50); //Ändra aktuell färg g.setcolor(color.red); g.drawstring("igen", 15, 70); //Byt font Font f = new Font("Times",Font.BOLD,24); g.setfont(f); g.drawstring("ny font", 15, 100); previous next 27 //Rita oval (med ny färg) g.setcolor(new Color(120, 240, 90)); g.drawoval(100, 200, 100, 75); // och en fylld polygon int x = 20; int y = 120; Polygon fillpol = new Polygon(); fillpol.addpoint(x,y); fillpol.addpoint(x+15,y+60); fillpol.addpoint(x+5,y+70); fillpol.addpoint(x+115,y+80); g.fillpolygon(fillpol); public static void main(string[] args) { LiteGrafikTest f = new LiteGrafikTest(); f.settitle("lite test av grafik"); f.setsize(300, 500); f.setlocation(100, 100); f.setvisible(true); previous next 28 Java2D: hur http://java.sun.com/docs/books/tutorial/2d/index.html Kör vi JDK1.2 eller senare används egentligen Graphics2D och inte Graphics Graphics2D är definierad som en direkt subklass till Graphics därför kan vi om vi vill använda den som en Graphics För att komma åt Graphics2D:s rutiner måste vi dock göra en cast (i tex paint-metoden) public void paint(graphics g) { Graphics2D g2 = (Graphics2D) g; // Nu kan vi använda rutiner i Graphics2D utan att // komplikatorn klagar previous next 29 Java2D: några primitiver och enkla ritrutiner linjetjocklek float width = 10; BasicStroke bs = new BasicStroke(width); gc2.setstroke(bs); gc2.drawline(10, 10, 100, 200); streckad linje float [] dash = {10; BasicStroke b = new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f); g2.setstroke(b); previous next 30
Polygon (beskriv först rita sedan) GeneralPath p = new GeneralPath(); p.moveto(0, 0); p.lineto(w/12, h/10); p.lineto(0,h/5); p.closepath(); g2.draw(p); //Rita ut det hela nu Java2D: ange typ av linje och hörn I många grafikpaket kan man ange om ändor av linjer skall vara räta, rundade eller projicerade CAP_BUTT, CAP_ROUND, CAP_SQUARE Motsvarande gäller för hörn i polygoner BasicStroke.JOIN_MITER, BasicStroke.JOIN_ROUND, BasicStroke.JOIN_BEVEL BasicStroke bs = new BasicStroke(20.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND); Antialiasing g2.setrenderinghint(renderinghints.key_antialiasing, RenderingHints.VALUE_ANTIALIAS_ON); Rita sen som vanligt previous next 31 previous next 32 Java2D, Några exempel Följande två exempel inspirerade av och till stora delar lika med ett par exempel i den utmärkta Javaexempelsamlingen Java Examples in a Nutshell, A Tutorial Companion to Java in a Nutshell, av David Flanagan, O Reilly 3ed 2004, http://www.oreilly.com/catalog/jenut3/ Exempel 1: olika figurer import java.awt.geom.*; import java.awt.font.*; /** A demonstration of Java2D shapes */ public class Shapes extends JComponent{ static final int WIDTH = 725, HEIGHT = 300; public String getname() {return "Shapes"; public int getwidth() { return WIDTH; public int getheight() { return HEIGHT; // Size of our example previous next 33 previous next 34 Shape[] shapes = new Shape[] { // A straight line segment new Line2D.Float(0, 0, 100, 100), // A quadratic bezier curve. Two end points and one control point new QuadCurve2D.Float(0, 0, 80, 15, 100, 100), // A cubic bezier curve. Two end points and two control points new CubicCurve2D.Float(0, 0, 80, 15, 10, 90, 100, 100), // A 120 degree portion of an ellipse new Arc2D.Float(-30, 0, 100, 100, 60, -120, Arc2D.OPEN), // A 120 degree portion of an ellipse, closed with a chord new Arc2D.Float(-30, 0, 100, 100, 60, -120, Arc2D.CHORD), // A 120 degree pie slice of an ellipse new Arc2D.Float(-30, 0, 100, 100, 60, -120, Arc2D.PIE), // An ellipse new Ellipse2D.Float(0, 20, 100, 60), // A rectangle new Rectangle2D.Float(0, 20, 100, 60), // A rectangle with rounded corners new RoundRectangle2D.Float(0, 20, 100, 60, 15, 15), // A triangle new Polygon(new int[] { 0, 0, 100, new int[] {20, 80, 80, 3), ; // These are the labels for each of the shapes String[] labels = new String[] { "Line2D", "QuadCurve2D", "CubicCurve2D", "Arc2D (OPEN)", "Arc2D (CHORD)", "Arc2D (PIE)", "Ellipse2D", "Rectangle2D", "RoundRectangle2D", "Polygon", "Polygon (random)", "Spiral" ; /** Draw the example */ public void paintcomponent(graphics g) { super.paintcomponent(g); Graphics2D g2 = (Graphics2D) g; g2.setfont(new Font("SansSerif", Font.PLAIN, 10)); g2.setstroke(new BasicStroke(2.0f)); g2.setrenderinghint(renderinghints.key_antialiasing, RenderingHints.VALUE_ANTIALIAS_ON); g2.translate(10, 10); previous next 35 previous next 36
// Loop through each shape for(int i = 0; i < shapes.length; i++) { g2.setcolor(color.yellow); // Set a color g2.fill(shapes[i]); // Fill the shape with it g2.setcolor(color.black); // Switch to black g2.draw(shapes[i]); // Outline the shape with it g2.drawstring(labels[i], 0, 110); // Label the shape g2.translate(120, 0); // Move over for next shape if (i % 6 == 5) g2.translate(-6*120, 120); // Move down after 6 JFrame f = new JFrame(); Shapes s = new Shapes(); f.getcontentpane().add(s); f.setsize(s.getwidth(), s.getheight()); f.settitle(s.getname()); f.setvisible(true); Exempel 2: Transformationer import java.awt.geom.*; /** A demonstration of Java2D transformations */ public class Transforms extends JComponent{ public String getname() { return "Transforms"; public int getwidth() { return 750; public int getheight() { return 300; Shape shape; // The shape to draw AffineTransform[] transforms; // The ways to transform it String[] transformlabels; // Labels for each transform previous next 37 previous next 38 public Transforms() { GeneralPath path = new GeneralPath(); // Create a shape to draw path.append(new Line2D.Float(0.0f, 0.0f, 0.0f, 100.0f), false); path.append(new Line2D.Float(-10.0f, 50.0f, 10.0f, 50.0f), false); path.append(new Polygon(new int[] { -5, 0, 5, new int[] { 5, 0, 5, 3), false); this.shape = path; // Remember this shape // Set up some transforms to alter the shape this.transforms = new AffineTransform[6]; // 1) the identity transform transforms[0] = new AffineTransform(); // 2) A scale tranform: 3/4 size transforms[1] = AffineTransform.getScaleInstance(0.75, 0.75); // 3) A shearing transform transforms[2] = AffineTransform.getShearInstance(-0.4, 0.0); // 4) A 30 degree clockwise rotation about the origin of the shape transforms[3] = AffineTransform.getRotateInstance(Math.PI*2/12); // 5) A 180 degree rotation about the midpoint of the shape transforms[4] = AffineTransform.getRotateInstance(Math.PI, 0.0, 50.0); // 6) A combination transform transforms[5] = AffineTransform.getScaleInstance(0.5, 1.5); transforms[5].shear(0.0, 0.4); transforms[5].rotate(math.pi/2, 0.0, 50.0); // 90 degrees previous next 39 // Define names for the transforms transformlabels = new String[] { "identity", "scale", "shear", "rotate", "rotate", "combo" ; /** Draw the defined shape and label, using each transform */ public void paintcomponent(graphics g) { super.paintcomponent(g); Graphics2D g2 = (Graphics2D) g; g2.setcolor(color.black); // black g2.setstroke(new BasicStroke(2.0f, BasicStroke.CAP_SQUARE, // 2-pixel BasicStroke.JOIN_BEVEL)); g2.setrenderinghint(renderinghints.key_antialiasing, // antialias RenderingHints.VALUE_ANTIALIAS_ON); previous next 40 // Now draw the shape once using each of the transforms we've defined for(int i = 0; i < transforms.length; i++) { AffineTransform save = g2.gettransform(); // save current state g2.translate(i*125 + 50, 50); // move origin g2.transform(transforms[i]); // apply transform g2.draw(shape); // draw shape g2.drawstring(transformlabels[i], -25, 125); // draw label g2.drawrect(-40, -10, 80, 150); // draw box g2.settransform(save); // restore transform Swing Ett par av SUNs Java-tutorials som handlar om Swing http://java.sun.com/docs/books/tutorial/uiswing/mini/index.html http://developer.java.sun.com/developer/codesamples/swing.html JFrame f = new JFrame(); Transforms s = new Transforms(); f.getcontentpane().add(s); f.setsize(s.getwidth(), s.getheight()); f.settitle(s.getname()); f.setvisible(true); previous next 41 previous next 42
Java Eventmodell 1.1 Java 1.1 och senare har en modell där man definierar objekt som tar omhand om händelser som sker i komponenter i gränssnitten I princip sätter man upp en händelselyssnare per typ (tangentbord, mus, fokus, etc.) av händelse man är intresserad av att applikationen ska reagera på Varje komponent (knapp, fält, mfl) kan också hanteras av sin egen händelselyssnare buttonx.addactionlistener(mylistenerforbuttonx) Med fördel används anonyma klasser för att definiera lyssnare för olika objekt Händelselyssnare Händelser till ett fönster eller komponent tas omhand av händelselyssnare påminner mycket om mönstret Observer, och i grafiska sammanhang om MVC, fast dom "beroende" objekten, dvs lyssnarna, måste implementera ett mer varierat utbud av metoder beroende av typ av lyssnare måste olika API:er implementeras Olika typer av lyssnare tar hand om olika typer av händelser, MouseListener, WindowListener, FocusListener, ActionListener, osv Namnet är uppbyggt på följande sätt: HändelsetypListener Till varje lyssnare finns ett speciellt interface som beskriver vilka metoder som lyssnaren implementerar Lyssnarna och deras interface tillhör ett gemensamt package nämligen: java.awt.event previous next 43 previous next 44 Händelselyssnare, några typiska KeyListener ActionListener ComponentListener FocusListener WindowListener EventListener TextListener MouseListener MouseMotionListener ItemListener AdjustmentListener Exempel: implementation av lyssnarfunktionalitet direkt i den egna klassen public class MyFrame1 extends Frame implements WindowListener{ public void windowopened(windowevent e) { public void windowclosed(windowevent e) { public void windowiconified(windowevent e) { public void windowdeiconified(windowevent e) { public void windowactivated(windowevent e) { public void windowdeactivated(windowevent e) { ContainerListener previous next 45 previous next 46 MyFrame1 frame = new MyFrame1(); frame.settitle("fönster som lyssnar efter fönsterhändelser v1 (fönstret gör det själv)"); frame.setsize(400, 300); frame.addwindowlistener(frame); frame.setvisible(true); Exempel: lyssnare som inre klass class MyWindowListener implements WindowListener { public void windowopened(windowevent e) { public void windowclosed(windowevent e) { public void windowiconified(windowevent e) { public void windowdeiconified(windowevent e) { public void windowactivated(windowevent e) { public void windowdeactivated(windowevent e) { previous next 47 previous next 48
public class MyFrame2 extends Frame { Frame frame = new MyFrame2(); frame.settitle("fönster som lyssnar efter fönsterhändelser v2 (med inre klass)"); frame.setsize(400, 300); frame.addwindowlistener(new MyWindowListener()); frame.setvisible(true); Adaptorer och händelselyssnare För att förenkla användningen av händelselyssnare finns ett antal fördefinierade adaptorer Dessa adaptorer implementerar alla metoder deklarerade i den aktuella lyssnarens gränssnitt En adaptor implemeneterar endast tomma metoder Genom att subklassa en adaptor och använda den som lyssnare så räcker det att endast skriva om dom metoder som verkligen gör något, så slipper man som i föregående exempel implementera massa metoder utan metodkropp Dessa adaptorer är speciellt enkla att använda tillsammans med anonyma inre klasser previous next 49 previous next 50 Object Object Klasser Adaptorer ComponentAdapter ContainerAdapter FocusAdapter KeyAdapter MouseAdapter MouseMotionAdapter WindowAdapter WindowListener WindowListener ActionListener ActionListener AdjustmentListener AdjustmentListener ComponentListener ComponentListener ContainerListener ContainerListener FocusListener FocusListener ItemListener ItemListener KeyListener KeyListener MouseListener MouseListener MouseMotionListener MouseMotionListener TextListener TextListener Gränssnitt Gränssnitt Exempel: lyssnare via adapter class MyWindowAdapter extends WindowAdapter { public class MyFrame3 extends Frame { Frame frame = new MyFrame3(); frame.settitle("fönster som lyssnar efter fönsterhändelser v3 (med egen adapter)"); frame.setsize(400, 300); frame.addwindowlistener(new MyWindowAdapter()); frame.setvisible(true); previous next 51 previous next 52 Exempel: lyssnare via anonym subklass public class MyFrame4 extends Frame { Frame frame = new MyFrame4(); frame.settitle("fönster som lyssnar efter fönsterhändelser v4 (med anonym subklass till adapter)"); frame.setsize(400, 300); frame.addwindowlistener(new WindowAdapter (){ ); frame.setvisible(true); Exempel: RitProgram1 public class RitProgram1 extends JFrame implements WindowListener, MouseListener, MouseMotionListener { protected int last_x, last_y; public RitProgram1(String s) { super(s); this.init(); previous next 53 previous next 54
public void init() { // Använd MouseListener och MouseMotionListener // addxxxlistener anger att vi ar intresserade av den aktuella typen av händelser. this.addwindowlistener(this); this.addmouselistener(this); this.addmousemotionlistener(this); this.setsize(300, 300); // En metod beskriven i MouseListener. // Anropas då vid tryck på musknapp. public void mousepressed(mouseevent e) { last_x = e.getx(); last_y = e.gety(); // Metoder deklarerade i MouseListener måste implementeras // även om vi inte gör något i dem public void mousereleased(mouseevent e) { public void mouseclicked(mouseevent e) { public void mouseentered(mouseevent e) { public void mouseexited(mouseevent e) { // och samma sak för metoder från MouseMotionListener. public void mousemoved(mouseevent e) { // En metod beskriven i MouseMotionListener. // Anropas då musen rörs med knapp nertryckt. public void mousedragged(mouseevent e) { Graphics g = this.getgraphics(); int x = e.getx(), y = e.gety(); g.drawline(last_x, last_y, x, y); last_x = x; last_y = y; previous next 55 previous next 56 public void windowopened(windowevent e) { public void windowclosed(windowevent e) { public void windowiconified(windowevent e) { public void windowdeiconified(windowevent e) { public void windowactivated(windowevent e) { public void windowdeactivated(windowevent e) { Exempel: RitProgram2 class MinRityta extends JComponent { protected int last_x, last_y; public MinRityta() { super(); this.init(); public static void main(string args []) { RitProgram1 ritprog = new RitProgram1("Enkelt ritprogram"); ritprog.setvisible(true); previous next 57 previous next 58 public void init() { this.addmouselistener(new MouseAdapter() { public void mousepressed(mouseevent e) { last_x = e.getx(); last_y = e.gety(); ); this.addmousemotionlistener(new MouseMotionAdapter() { public void mousedragged(mouseevent e) { Graphics g = getgraphics(); int x = e.getx(), y = e.gety(); g.drawline(last_x, last_y, x, y); last_x = x; last_y = y; ); public class RitProgram2 { public static void main(string args []) { JFrame ritprog = new JFrame("Ritprogram 2"); ritprog.getcontentpane().add(new MinRityta()); ritprog.addwindowlistener(new WindowAdapter () { ); ritprog.setsize(300, 300); ritprog.setvisible(true); previous next 59 previous next 60
Exempel: RitProgram3 (dubbelbuffring) class MinRityta extends JComponent { Image image = null; Graphics img = null; protected int last_x, last_y; public MinRityta() { super(); this.init(); protected Graphics getimgraphics() { if(image == null) { Dimension dim = getsize(); image = createimage(dim.width, dim.height); img = image.getgraphics(); return img; public void paintcomponent(graphics g) { super.paintcomponent(g); if(!(image == null)) g.drawimage(image, 0, 0, this); previous next 61 previous next 62 public void init() { this.addmouselistener(new MouseAdapter() { public void mousepressed(mouseevent e) { last_x = e.getx(); last_y = e.gety(); ); this.addmousemotionlistener(new MouseMotionAdapter() { public void mousedragged(mouseevent e) { Graphics g = getimgraphics(); int x = e.getx(), y = e.gety(); g.drawline(last_x, last_y, x, y); repaint(); last_x = x; last_y = y; ); previous next 63 public class RitProgram3 { public static void main(string args []) { JFrame ritprog = new JFrame("Ritprogram 3"); ritprog.getcontentpane().add(new MinRityta()); ritprog.addwindowlistener(new WindowAdapter () { ); ritprog.setsize(300, 300); ritprog.setvisible(true); previous next 64