Das Java Codebook Probekapitel ISBN

Document Sample
Das Java Codebook Probekapitel ISBN Powered By Docstoc
					Multimedia                                                                              Core


                                                                                        I/O

84      Wie kann ich einfache Strukturen zeichnen?                                      GUI
Seit Java2 (JDK 1.2) steht das Java2D-API zur Verfügung. Mit dieser Einführung
sind viele erweiterte Grafikmöglichkeiten zur Verfügung gestellt worden, obgleich       Multi-
                                                                                        media
die Kompatibilität zu den früheren Funktionen gewahrt wurde. Es stellt viele Funk-
tionen zum Zeichnen von grundlegenden, geometrischen Figuren zur Verfügung.             Daten-
Dazu gehören Linien, Rechtecke, Kreise bzw. Ellipsen, Kreisbögen und Polygone.          bank
Die entsprechenden Klassen finden sich im Paket java.awt.geom. Sie sind alle Unter-
                                                                                        Netz-
klassen der Klasse java.awt.Shape. Damit ist es möglich, sie alle auf die gleiche Art   werk
und Weise in den Zeichenmethoden der Klasse Graphics2D zu behandeln.
                                                                                        XML
In der Klasse SimpleDraw werden einige grundlegende Figuren gezeichnet, die mit
dem Java2D-API sehr einfach zu erstellen sind.
                                                                                        RegEx


                                                                                        Daten


                                                                                        Threads


                                                                                        Web-
                                                                                        Server


                                                                                        Applets


Abbildung 67: Grundlegende Zeichenfunktionen                                            Sonsti-
                                                                                        ges


 package javacodebook.media.draw.simple;
 import java.awt.*;
 import java.awt.geom.*;
 import javax.swing.*;

 public class SimpleDraw extends JPanel{

   //In Swing immer die Methode paintComponent überschreiben
   public void paintComponent(Graphics graphics) {

Listing 139: SimpleDraw
330                                                                         Multimedia




         super.paintComponent(graphics);
         //Graphics-Objekt ist in Wahrheit ein Graphics2D-Objekt
         Graphics2D g = (Graphics2D) graphics;
         //Aktuelle Zeichenfarbe setzen
         g.setColor(Color.black);
         //Eine Linie zeichnen
         g.draw(new Line2D.Double(0,100,319,100));
         //Ein Rechteck zeichnen
         g.draw(new Rectangle2D.Double(10, 10, 80, 60));
         //Einen Kreis gefüllt zeichnen
         g.draw(new Ellipse2D.Double(130,10,60,60));
         //Eine Ellipse mit Farbverlauf gefüllt zeichnen
         g.draw(new Ellipse2D.Double(230, 10, 80, 60));
         //Ein Rechteck mit abgerundeten Ecken zeichnen
         g.draw(new RoundRectangle2D.Double(10, 110, 80, 60, 15, 15));
         //Einen Kreisbogen zeichnen
         g.draw(new Arc2D.Double(120, 110, 80, 70, 90, 135, Arc2D.OPEN));
         //Ein Tortenstück zeichnen
         g.draw(new Arc2D.Double(240, 110, 80, 80, 90, 45, Arc2D.PIE));
     }

     //Größe des Panels festlegen
     public Dimension getPreferredSize() {
       return new Dimension(320, 200);
     }

     //Frame erzeugen Panel anzeigen
     public static void main(String[] args) {
       JFrame f = new JFrame();
       f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       f.getContentPane().setLayout(new BorderLayout());
       f.getContentPane().add(new SimpleDraw(), BorderLayout.CENTER);
       f.pack();
       f.show();
     }
 }

Listing 139: SimpleDraw (Forts.)


85         Wie zeichne ich verschiedene Rahmen?
Wenn Sie keinen Standard-Rahmen um eine geometrische Figur zeichnen wollen,
sondern beispielsweise einen gestrichelten Rahmen, oder einen Rahmen in einer
anderen Strichstärke verwenden wollen, so können Sie die Methode setStroke() der
Klasse Graphics2D verwenden. In Verbindung mit der Klasse java.awt.BasicStroke
Wie zeichne ich verschiedene Rahmen?                                           331



lassen sich sehr viele Einstellungen für den zu zeichnenden Rahmen vornehmen. Mit
ihrer Hilfe können Strichstärke, Linienenden, Linienverbindungen und unterbro-         Core
chene Linien erzeugt werden. Sie stellt einige Konstanten bereit, über die das Ende
und die Verbindung von Linien definiert werden können. Die Werte CAP_BUTT,             I/O
CAP_ROUND und CAP_SQUARE bestimmen den Stil, in dem ein Linienende gezeichnet
wird (gerade, abgerundet oder mit geradem Anhang).
                                                                                       GUI
Die Werte JOIN_BEVEL, JOIN_MITER und JOIN_ROUND legen fest, wie das Zusammentref-
fen von zwei Linienenden behandelt wird. Es kann ohne Effekt (BEVEL), mit spitzem      Multi-
                                                                                       media
Ende (MITER) oder abgerundet (ROUND) gezeichnet werden.
                                                                                       Daten-
Die Klasse BasicStroke bietet verschiedene Konstruktoren an, um die gewünschten        bank
Effekte zu erzielen. Die meisten sind sehr einfach zu benutzen. Der Konstruktor für
das Erzeugen von gestrichelten Linien ist etwas komplexer. Er hat die Form public      Netz-
                                                                                       werk
BasicStroke(float width, int cap, int join, float miterlimit, float[] dash,
float dash_phase). Die Parameter width, cap, join sind leicht erkennbar (Strich-
                                                                                       XML
stärke und die oben genannten Stile). Miterlimit beschreibt, wie lang zwei Linien
am Ende verbunden werden. Das wird wichtig, wenn zwei Linien in sehr spitzem
Winkel aufeinander treffen. Wird eine Spitze gezeichnet, so kann diese sehr lang       RegEx
werden. Dies wird durch das miterlimit begrenzt (würde die Spitze länger als der
Wert miterlimit, wird stattdessen mit der BEVEL-Funktion gezeichnet). Die Parame-      Daten
ter dash und dash_phase beschreiben gestrichelte Linien. Im Array dash werden die
Längen der einzelnen Strichabschnitte angegeben. Dabei wird alternierend zwischen
                                                                                       Threads
gezeichnetem und nicht gezeichnetem Strich gewechselt. Ein Array in der Form
{5,5} macht dasselbe wie {5}, da abwechselnd 5 Punkte gezeichnet werden und die
                                                                                       Web-
nächsten 5 nicht. Der Wert dash_phase dient als Offset für das Zeichnen der Striche-   Server
lung, d.h. die ersten x Punkte werden übersprungen.
                                                                                       Applets
Die Klasse StrokeExamples zeigt, wie die verschiedenen Rahmenarten und Linien-
enden gezeichnet werden.
                                                                                       Sonsti-
                                                                                       ges

 package javacodebook.media.draw.stroke;
 import java.awt.*;
 import java.awt.geom.*;
 import javax.swing.*;

 public class StrokeExamples extends JPanel{

   public void paintComponent(Graphics graphics) {

Listing 140: StrokeExamples
332                                                                   Multimedia




      super.paintComponent(graphics);
      //Graphics-Objekt ist in Wahrheit ein Graphics2D-Objekt
      Graphics2D g = (Graphics2D) graphics;
      //aktuelle Zeichenfarbe setzen
      g.setColor(Color.black);
      //Ein Rechteck mit Rahmendicke 5 zeichnen
      BasicStroke fatBorder = new BasicStroke(5.0f);
      g.setStroke(fatBorder);
      g.draw(new Rectangle2D.Double(10, 10, 80, 60));

      //Ein Rechteck mit gestricheltem Rahmen zeichnen
      BasicStroke stroke =
        new BasicStroke(1.0f,
        BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL,
        1.0f, new float[] {5.0f},
        0.0f);
      g.setStroke(stroke);
      g.draw(new RoundRectangle2D.Double(110, 10, 80, 60,
                          15, 15));
      //Rahmen mit verschiedenen Strichlängen zeichnen
      stroke = new BasicStroke(1.0f,
                   BasicStroke.CAP_BUTT,
                   BasicStroke.JOIN_BEVEL,
                   1.0f, new float[] {5.0f, 5.0f,
                             2.0f, 5.0f},
                   0.0f);
      g.setStroke(stroke);
      g.draw(new RoundRectangle2D.Double(210, 10, 80, 60, 15, 15));
      //Linien überschneiden sich am Ende ohne Effekt
      stroke = new BasicStroke(10.0f,
                   BasicStroke.CAP_BUTT,
                   BasicStroke.JOIN_BEVEL);
      g.setStroke(stroke);
      int x = 25;
      g.draw(new Line2D.Double(x, 160, x+25, 135));
      g.draw(new Line2D.Double(x+25, 135, x+50, 160));
      //Linien überschneiden sich am Ende, Spitze wird gezeichnet
      stroke = new BasicStroke(10.0f,
                   BasicStroke.CAP_SQUARE,
                   BasicStroke.JOIN_MITER);
      g.setStroke(stroke);
      x = 125;
      g.draw(new Line2D.Double(x, 160, x+25, 135));
      g.draw(new Line2D.Double(x+25, 135, x+50, 160));
      //Linien überschneiden sich am Ende, Spitze wird abgerundet

Listing 140: StrokeExamples (Forts.)
Wie zeichne ich verschiedene Rahmen?                                333




         stroke = new BasicStroke(10.0f,
                                                                          Core
                      BasicStroke.CAP_ROUND,
                      BasicStroke.JOIN_ROUND);
         g.setStroke(stroke);                                             I/O
         x = 225;
         g.draw(new Line2D.Double(x, 160, x+25, 135));
         g.draw(new Line2D.Double(x+25, 135, x+50, 160));                 GUI
     }
                                                                          Multi-
     /** Die gewünschte Größe des Panels festlegen */                     media
     public Dimension getPreferredSize() {
       return new Dimension(300, 180);                                    Daten-
     }                                                                    bank

                                                                          Netz-
     /** Einen Frame erzeugen und das Panel anzeigen */                   werk
     public static void main(String[] args) {
       JFrame f = new JFrame();
       f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);         XML
       f.getContentPane().setLayout(new BorderLayout());
       f.getContentPane().add(new StrokeExamples(),                       RegEx
                    BorderLayout.CENTER);
       f.pack();
       f.show();                                                          Daten
     }
 }
                                                                          Threads
Listing 140: StrokeExamples (Forts.)
                                                                          Web-
                                                                          Server
Und so sieht das Ergebnis aus.
                                                                          Applets


                                                                          Sonsti-
                                                                          ges




Abbildung 68: Verschiedene Möglichkeiten, Rahmen zu zeichnen
334                                                                      Multimedia



Für die Definition eigener Rahmen muss das Interface java.awt.Stroke implemen-
tiert werden, dann können selbst definierte Rahmen innerhalb der Zeichenfunk-
tionen der Graphics2D-Klasse verwendet werden. Der mit Hilfe von setStroke()
festgelegte Zeichenstrich kann auf alle Zeichenobjekte angewendet werden, die eine
Unterklasse von java.awt.Shape sind.


86     Wie kann ich etwas mit Farbverläufen füllen?
Ein Farbverlauf wird mit Hilfe der Klasse java.awt.GradientPaint definiert. Er ver-
läuft von einem Startpunkt hin zu einem Endpunkt, die beide in Koordinatenform
angegeben werden. Eine Ausgangs- und eine Endfarbe müssen angegeben werden,
dazwischen wird entlang einer Geraden zwischen Start- und Endpunkt ein linearer
Farbverlauf berechnet. Mit der Methode fill(Shape shape) aus der Klasse Graphics2D
wird der Farbverlauf gezeichnet. Auch zyklisches Füllen ist möglich.
Die Klasse GradientPaint hat zwei Konstruktoren, die es in zwei Variationen gibt,
einmal mit einzelnen Koordinaten und einmal mit Point2D-Objekten als Parameter,
um die Endpunkte der Farbverläufe festzulegen. Wir beschränken uns hier auf die
Variante mit einzelnen Koordinaten:


 public GradientPaint(float x1, float y1, Color color1,
            float x2, float y2, Color color2);

 public GradientPaint(float x1, float y1, Color color1,
            float x2, float y2, Color color2,
            boolean cyclic);



Mit der ersten Variante wird ein einfacher, azyklischer Farbverlauf vom Punkt x1,y1
hin zu Punkt x2, y2 erzeugt. Die zweite Variante ermöglicht sowohl einen azykli-
schen als auch einen zyklischen Farbverlauf. Mit dem Parameter cyclic kann ange-
geben werden, ob der Farbverlauf zyklisch wiederholt werden soll. Er wird allerdings
nur dann zyklisch verlaufen, wenn der angegebene Endpunkt {x2,y2} nicht auch der
Endpunkt des zu füllenden Shapes ist. Wird der Endpunkt {x2, y2} z.B. in der Mitte
des zu füllenden Shapes angegeben, so wird der Farbverlauf einmal vom Rand bis
zur Mitte von Farbe 1 zu Farbe 2 verlaufen und dann von der Mitte zum anderen
Rand von Farbe 2 zu Farbe 1.
Das vorherige Bild zeigt die Möglichkeiten, die sich mit GradientPaint ergeben.
Wie kann ich etwas mit Farbverläufen füllen?                        335




                                                                          Core


                                                                          I/O


                                                                          GUI


                                                                          Multi-
                                                                          media

Abbildung 69: Füllen mit Farbverläufen                                    Daten-
                                                                          bank

                                                                          Netz-
   public void paintComponent(Graphics graphics) {                        werk
     super.paintComponent(graphics);
     Graphics2D g = (Graphics2D) graphics;
                                                                          XML

     float startx = 10, starty = 10;
     float width=80, height=60;                                           RegEx
     //Farbverlauf definieren und ein gefülltes Rechteck zeichnen
     //Farbverlauf von links (schwarz) nach rechts (weiß) linear
     GradientPaint gradient =                                             Daten
       new GradientPaint(startx, starty, Color.black,
                 startx + width, starty, Color.white);
                                                                          Threads
     g.setPaint(gradient);
     g.fill(new Rectangle2D.Double(startx, starty, width,
                                height));                                 Web-
                                                                          Server
     startx = 110;
     //Farbverlauf diagonal von links oben nach rechts unten              Applets
     gradient =
       new GradientPaint(startx, starty, Color.black,                     Sonsti-
                 startx + width, starty + height,                         ges
                 Color.white);
     g.setPaint(gradient);
     g.fill(new Rectangle2D.Double(startx, starty, width,
                              height));

     startx = 20;
     starty = 110;
     //Zyklischer Farbverlauf mit Zentrum in der Mitte
     gradient =
       new GradientPaint(startx, starty, Color.black,
                 startx + width, starty, Color.white, true);
336                                                                       Multimedia




       g.setPaint(gradient);
       g.fill(new Rectangle2D.Double(startx, starty, width*2,
                                height));
   }



87       Wie kann ich eine Grafik laden und anzeigen?
Eine Grafik wird in Java von der Klasse java.awt.Image repräsentiert. Java unter-
stützt von sich aus die Formate GIF und JPEG. Sie haben mehrere Möglichkeiten,
ein Bild zu laden. Innerhalb eines Applets kann die Methode getImage() verwendet
werden, in einer Anwendung die Methode getImage() der Klasse java.awt.Toolkit.
Dabei kann letztere nur über das Default-Toolkit, das von der Java Runtime bereit-
gestellt wird, verwendet werden. Das Default-Toolkit wird von der Klasse Toolkit
über die Methode getDefaultToolkit() geliefert. Somit sieht ein entsprechender
Aufruf in einer Anwendung so aus:


 Image image = Toolkit.getDefaultToolkit().getImage(dateiname);



Die Methode getImage() kehrt sofort zurück und das Laden der Grafik erfolgt im
Hintergrund. Dies hat zur Folge, dass ein Bild u.U. noch nicht vollständig geladen
ist, wenn es verwendet werden soll. Die Kontrolle über den Ladevorgang können Sie
durch den Einsatz eines MediaTrackers (java.awt.MediaTracker) behalten. Im Kapitel
über Applets wird dies gezeigt.
Wenn Sie das Bild sofort verwenden wollen, nehmen Sie die Klasse javax.swing.
ImageIcon. Sie verwendet intern einen MediaTracker und erspart so diverse Codezei-
len. Der Konstruktor erhält als Parameter eine Datei oder URL, von der das Bild
geladen wird. Mit der Methode getImage() kann das Bild anschließend genutzt wer-
den.
Um das Bild anzuzeigen, kann eine entsprechende Swing-Komponente verwendet
werden, die ImageIcons unterstützt (z.B. ein JLabel). Es ist jedoch auch sehr einfach,
eine eigene Komponente zu schreiben, die Grafiken anzeigt. Eine eigene Kompo-
nente kann oft flexibler innerhalb von GUI-Anwendungen eingesetzt werden. Die
Klasse ImagePanel ist als Komponente realisiert, die von JPanel erbt. Damit kann sie
an beliebiger Stelle verwendet werden, z.B. innerhalb einer JScrollPane. Im Kons-
truktor wird die Grafik übergeben. Das ImagePanel nimmt danach die Größe der
Grafik als seine optimale Größe an.
Wie kann ich eine Grafik laden und anzeigen?                                     337




 package javacodebook.media.graphic.load;                                                Core
 import java.awt.*;
 import javax.swing.JPanel;
                                                                                         I/O
 public class ImagePanel extends javax.swing.JPanel {
   //Die Grafik, die angezeigt werden soll
                                                                                         GUI
   private Image image;

     public ImagePanel(Image image) {                                                    Multi-
       this.image = image;                                                               media
     }
                                                                                         Daten-
                                                                                         bank
     //Grafik auf das Panel zeichnen
     public void paintComponent(Graphics g) {                                            Netz-
       super.paintComponent(g);                                                          werk
       g.drawImage(image, 0, 0,
             image.getWidth(this),
                                                                                         XML
             image.getHeight(this), this);
     }
                                                                                         RegEx
     //Größe der Grafik als PreferredSize zurückgegeben
     public Dimension getPreferredSize() {
       return new Dimension(image.getWidth(this),                                        Daten
                  image.getHeight(this));
     }
                                                                                         Threads
 }

Listing 141: ImagePanel                                                                  Web-
                                                                                         Server

Damit lässt sich ein einfacher Bildbetrachter erstellen. Die Klasse ImageViewer stellt   Applets
eine einfache Möglichkeit dar, Bilder zu laden und anzuzeigen. Dabei wird der
Frame jeweils der Größe der anzuzeigenden Grafik angepasst.                              Sonsti-
                                                                                         ges


 package javacodebook.media.graphic.load;
 import java.awt.*;
 import java.awt.event.*;
 import java.io.*;
 import javax.swing.*;

 public class ImageViewer extends JFrame {
   //das ImagePanel
   ImagePanel imagePanel = null;

Listing 142: ImageViewer
338                                                                      Multimedia




     public ImageViewer() {
       setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       getContentPane().setLayout(new BorderLayout());
       //Einen Button zum Öffnen von Dateien erstellen
       JPanel buttonPanel = new JPanel();
       getContentPane().add(buttonPanel, BorderLayout.NORTH);
       JButton openButton = new JButton("Datei öffnen");
       buttonPanel.add(openButton);
       //Einen ActionListener auf den Button legen, der einen
       //FileChooser öffnet
       openButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent evt) {
           JFileChooser chooser = new JFileChooser();
           int status = chooser.showOpenDialog(ImageViewer.this);
           if (status == JFileChooser.APPROVE_OPTION) {
             //ausgewählte Datei ermitteln und abspielen
             File file = chooser.getSelectedFile();
             try {
               ImageIcon icon = new ImageIcon(file.getAbsolutePath());
               //vorher vorhandenes ImagePanel entfernen
               if(imagePanel != null)
                 getContentPane().remove(imagePanel);
               //das ImagePanel anzeigen
               imagePanel = new ImagePanel(icon.getImage());
               getContentPane().add(imagePanel, BorderLayout.CENTER);
               //Frame auf die Bildgröße anpassen
               pack();
             } catch(Exception e) {
               e.printStackTrace(System.out);
             }
           }
         }
       });
     }

     public static void main(String[] args) {
       ImageViewer viewer = new ImageViewer();
       viewer.pack();
       viewer.show();
     }
 }

Listing 142: ImageViewer (Forts.)

				
DOCUMENT INFO
Shared By:
Categories:
Stats:
views:6
posted:3/22/2011
language:English
pages:10