GUIs mit Swing • Swing setzt auf AWT auf • leichtgewichtige Komponenten Swing und Java2D • Realisiert die MVC (Model-View-Controller) Architektur • Komponenten: siehe Index http://java.sun.com/docs/books/tutorial/ uiswing/components/components_pics.html • Komponenten, die von Container abgeleitet werden, können Albert Weichselbraun andere Komponenten enthalten (z.B. JPanel, JFrame, . . . ) J AVA 2D Vorgangsweise 28. O KTOBER 2008 Layout festlegen 1. Layout festlegen • Position der Komponenten • Anordnung von JPanels / Wahl des Layoutmanagers 1 package at.ac.wuwien.examples.swingdemo; 3 import javax.swing.*; 5 public class SimpleGUI extends JFrame { 2. Grafische Komponenten festlegen 7 3. Eventhandling definieren 8 9 10 12 13 14 J AVA 2D -1- -2- 28. O KTOBER 2008 J AVA 2D // optional public SimpleGUI(String title) { super(title); } // main program public static void main(String[] args) { SimpleGUI sg = new SimpleGUI("Swing Example"); -3- 28. O KTOBER 2008 15 16 17 18 } } Elemente hinzufügen sg.pack(); sg.setVisible(true); 1 2 3 5 package at.ac.wuwien.examples.swingdemo; import java.awt.BorderLayout; import javax.swing.*; public class SimpleGUI2 extends JFrame { private JTextArea textoutput; private JTextField textinput; private JButton addButton, clearButton; 7 8 9 public SimpleGUI2(String title) { super(title); // create Text input/output fields textoutput = new JTextArea("Output",3,10); 11 12 13 14 J AVA 2D -4- textinput 15 18 19 20 23 24 26 27 28 30 J AVA 2D 32 33 34 35 36 37 // add buttons to the controlPanel controlPanel.add(addButton); controlPanel.add(clearButton); 22 } J AVA 2D = new JTextField("Input"); // Create Buttons JPanel controlPanel = new JPanel(); addButton = new JButton("Add"); clearButton = new JButton("Clear"); 17 29 28. O KTOBER 2008 38 } -5- 28. O KTOBER 2008 // main program public static void main(String[] args) { SimpleGUI2 sg = new SimpleGUI2("Swing Example"); sg.pack(); sg.setVisible(true); } // add everything to the layout add(controlPanel, BorderLayout.NORTH); add(textinput, BorderLayout.CENTER); add(textoutput, BorderLayout.SOUTH); -6- 28. O KTOBER 2008 J AVA 2D -7- 28. O KTOBER 2008 Eventhandling definieren 1 2 public class MyGUI extends JFrame implements ActionListener { 4 6 7 20 21 public MyGUI(String title) { super(title); 22 23 24 ... 11 12 14 18 19 ... 9 13 } // eventhandling addButton.addActionListener( this ); clearButton.addActionListener( this ); J AVA 2D -8- 28. O KTOBER 2008 Erweiterung - scrollbares Textfeld 1 ... 5 // scrolling JScrollPane sp = new JScrollPane(textoutput); this.add(sp, BorderLayout.SOUTH); 7 ... 3 4 public void actionPerformed(ActionEvent e) { if (e.getSource() == clearButton) { textoutput.setText(’’); } if (e.getSource() == addButton) { textoutput.setText( textoutput.getText( + ’\n’ + textinput.getText( ); } } 16 17 J AVA 2D -9- 28. O KTOBER 2008 Übung: Wechselkursrechner Schreiben Sie eine Applikation, die einen Betrag entgegennimmt und zwischen den folgenden Währungen umrechnet: • USD (1 EUR = 1.32 USD) • AUD (1 EUR = 1.689 AUD) • JPY (1 EUR = 154.85 JPY) Hinweis: getText() liefert Ihnen immer einen String. Dieser kann mittels Double.parseDouble() in einen double konvertiert werden (siehe nächste Folie). J AVA 2D - 10 - 28. O KTOBER 2008 J AVA 2D - 11 - 28. O KTOBER 2008 Java2D Exkurs: String, Double, double • String: Zeichenkette → "12.1"+ "13" = "12.113" • Erlaubt es dem Programmierer Komponenten selbst zu zeichnen. • double: Primitive → 12.1 + 13 = 25.1 • Überschreiben der Methode paintComponent() der Superklasse JComponent • Double: Wrapper-Objekt für den Datentyp double. - paintCompontent() der Superklasse ausführen Bis inklusive Java 1.4 ist es nicht möglich, mit diesem direkt zu rechnen (ab Java 5.0: Autoboxing). - anschließend eigenen Erweiterungen - wird nach Aufruf von repaint() ausgeführt • Konvertierung: String s → double d: 1 • Koordinatensystem double d = Double.parseDouble(s); • Verwendung eines Buffers: • Konvertierung: double d → String s: 1 BufferedImage buffer=new BufferedImage(x_size, y_size, BufferedImage.TYPE_INT_RGB) String s = new Double(d).toString(); J AVA 2D - 12 - 28. O KTOBER 2008 Eigene grafische Komponenten • Vorgangsweise J AVA 2D - 13 - 28. O KTOBER 2008 Zeichnen mit Java2D • Vorgangsweise 1. Klasse von JComponent ableiten 1. Graphics2D Objekt erstellen 2. BufferedImage Buffer mit der Größe der Komponente erstellen → alle Zeichenoperation im Buffer durchführen 2. Formen (Ellipse2D.Double, Rectangle2D.Double, ...), Linien erstellen (unterstützte Formen1) 3. paintComponent() überschreiben, sodass es den Buffer ausgibt 3. Elemente draw(element) zeichnen oder mit fill(element) ausfüllen mit 4. nach Änderungen in der Darstellung repaint ausführen! 1 J AVA 2D - 14 - 28. O KTOBER 2008 http://java.sun.com/docs/books/tutorial/2d/display/strokeandfill.html J AVA 2D - 15 - 28. O KTOBER 2008 Bilder einfügen 1 3 • Vorgangsweise 4 5 1. java.awt.image.* importieren .jar-Dateien mittels getClass().getResource(fname) 3. Image-Objekt mit ImageIO.read( url ) initialisieren 4. Ausgabe mittels drawImage() 2. Zugriff auf Objekte in 7 8 package at.ac.wuwien.examples.java2d; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Java2DDemo extends JFrame implements ActionListener{ 10 11 12 14 15 16 J AVA 2D 18 19 - 16 - 28 30 this.add(auswahl, BorderLayout.SOUTH); 22 23 24 25 26 27 J AVA 2D 33 public Java2DDemo(String title) { super(title); // Auswahlfelder darstellen JPanel auswahl = new JPanel(); formen = new JButton("Formen"); formen.addActionListener(this); bild = new JButton("Bild"); bild.addActionListener(this); auswahl.add(formen); auswahl.add(bild); 21 28. O KTOBER 2008 34 35 36 38 39 41 42 43 44 45 46 47 48 J AVA 2D - 18 - 28. O KTOBER 2008 J AVA 2D private static enum Demos { FORMEN_DEMO, BILD_DEMO }; private Demos zeigeDemo = Demos.FORMEN_DEMO; private Zeichenflaeche z; private JButton formen; private JButton bild; private JButton nord,sued,west,ost; - 17 - 28. O KTOBER 2008 // Cursorsteuerung darstellen JPanel cursor = new JPanel(); nord = new JButton("N"); nord.addActionListener(this); sued= new JButton("S"); sued.addActionListener(this); west = new JButton("<-"); west.addActionListener(this); ost = new JButton("->"); ost.addActionListener(this); cursor.add(west); cursor.add(nord); cursor.add(sued); cursor.add(ost); - 19 - 28. O KTOBER 2008 this.add(cursor, BorderLayout.CENTER); 49 51 52 53 54 } 55 58 59 60 61 62 63 64 J AVA 2D - 20 - 80 81 82 83 84 // Zeichenflaeche darstellen z = new Zeichenflaeche(320, 200); this.add(z, BorderLayout.NORTH); z.zeichneKreis(); 67 } } } 69 28. O KTOBER 2008 Java2DDemo demo = new Java2DDemo("Java2D Demo"); demo.pack(); demo.setVisible( true ); 71 72 73 74 75 76 } 79 public static void main(String[] args) { J AVA 2D 1 3 4 5 7 9 10 12 import import import import import 28. O KTOBER 2008 javax.swing.*; java.awt.*; java.awt.geom.*; java.awt.image.*; // BufferImage java.net.URL; import javax.imageio.*; import java.io.*; public class Zeichenflaeche extends JComponent { 15 28. O KTOBER 2008 - 21 - package at.ac.wuwien.examples.java2d; 14 - 22 - // Demo darstellen System.out.println(zeigeDemo); switch (zeigeDemo) { case FORMEN_DEMO: z.zeichneKreis(); break; case BILD_DEMO: z.zeichneBild(); break; } 77 6 J AVA 2D else if (e.getSource()==nord) { z.bewegeNord(); } else if (e.getSource()==sued) { z.bewegeSued(); } 68 // Reaktion auf Eingabeevents und Implementierung // von ActionListener public void actionPerformed(ActionEvent e) { if (e.getSource()==formen) { zeigeDemo = Demos.FORMEN_DEMO; } else if (e.getSource()==bild) { zeigeDemo = Demos.BILD_DEMO; 57 } else if (e.getSource()==west) { z.bewegeWest(); } else if (e.getSource()==ost ) { z.bewegeOst(); 65 66 J AVA 2D private BufferedImage buffer; private Image img; - 23 - 28. O KTOBER 2008 17 18 20 21 22 23 private int x_size, y_size; private int x_pos, y_pos; public Zeichenflaeche(int x_size, int y_size) { // Groesse der Zeichenflaeche setzen this.x_size = x_size; this.y_size = y_size; // Startposition der Objekte setzen this.x_pos = 0; this.y_pos = 0; this.setPreferredSize( new Dimension(x_size, y_size)); this.setMaximumSize( new Dimension(x_size, y_size)); this.setMinimumSize( 25 26 27 28 29 30 31 32 J AVA 2D - 24 - 50 51 52 53 54 55 33 34 } 36 37 38 39 41 42 43 44 45 46 47 28. O KTOBER 2008 66 67 68 69 71 72 73 58 59 60 61 62 63 J AVA 2D // Bild laden try { // retrieve the image from the web // URL bildUrl = new URL("http://www.bugzilla.org/img // or from the filesystem/jar file URL bildUrl = getClass(). getResource("/at/ac/wuwien/examples/java2d/buggie.p img = ImageIO.read( bildUrl ); } catch (IOException e) { System.err.println(e); } J AVA 2D 65 // Buffer Image erstellen this.buffer = new BufferedImage(x_size, y_size, BufferedImage.TYPE_INT_RGB); this.setBackground(Color.GRAY); new Dimension(x_size, y_size)); this.setDoubleBuffered(true); - 25 - // Bewegung public void public void public void public void der Objekte steuern bewegeNord() { y_pos bewegeSued() { y_pos bewegeOst() { x_pos bewegeWest() { x_pos 28. O KTOBER 2008 -=5; +=5; +=5; -=5; } } } } // Objekte zeichnen public void zeichneKreis() { Graphics2D g2d = this.buffer.createGraphics(); g2d.clearRect( 0, 0, x_size, y_size); protected void paintComponent(Graphics g) { 74 super.paintComponent(g); Graphics2D g2d = (Graphics2D)g.create(); 76 Ellipse2D.Double ellipse = g2d.drawImage(this.buffer, 0, 0, this); 77 new Ellipse2D.Double(x_pos, y_pos, 80, 80); g2d.dispose(); // Handle verwerfen (eigentlich nicht notwendig) 78 g2d.draw( ellipse ); } 80 Rectangle2D.Double box = - 26 - 28. O KTOBER 2008 J AVA 2D - 27 - 28. O KTOBER 2008 81 82 83 } 84 public void zeichneBild() { Graphics2D g2d = this.buffer.createGraphics(); g2d.clearRect( 0, 0, x_size, y_size); 86 87 88 90 91 } 92 94 new Rectangle2D.Double(x_pos+100, y_pos, 100, 80); g2d.fill( box ); repaint(); g2d.drawImage( img, x_pos, y_pos, null); repaint(); } J AVA 2D - 28 - 28. O KTOBER 2008 Übung: Würfel 1 Schreiben Sie eine Applikation, die einen Würfel zeichnet und mit einem Würfel-Button versehen ist. Bei jedem Druck auf den Button soll eine neue Zahl zwischen eins und sechs angezeigt (gezeichnet) werden. Hinweis: Zufallszahlen können Sie in Java (wie auf der nächsten Folie demonstriert) durch Import der Klasse java.util.Random mittels eines Random() Objektes berechnen. J AVA 2D J AVA 2D - 30 - 28. O KTOBER 2008 3 4 28. O KTOBER 2008 import java.util.Random; class Zufallszahl { private Random rnd = new Random(); 6 7 8 9 - 29 - } J AVA 2D public int neueZahl() { return rnd.nextInt(6)+1; } - 31 - 28. O KTOBER 2008