Rheinwerk Computing < openbook >


 
Inhaltsverzeichnis
Materialien
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Arrays und ihre Anwendungen
5 Der Umgang mit Zeichenketten
6 Eigene Klassen schreiben
7 Objektorientierte Beziehungsfragen
8 Ausnahmen müssen sein
9 Geschachtelte Typen
10 Besondere Typen der Java SE
11 Generics<T>
12 Lambda-Ausdrücke und funktionale Programmierung
13 Architektur, Design und angewandte Objektorientierung
14 Java Platform Module System
15 Die Klassenbibliothek
16 Einführung in die nebenläufige Programmierung
17 Einführung in Datenstrukturen und Algorithmen
18 Einführung in grafische Oberflächen
19 Einführung in Dateien und Datenströme
20 Einführung ins Datenbankmanagement mit JDBC
21 Bits und Bytes, Mathematisches und Geld
22 Testen mit JUnit
23 Die Werkzeuge des JDK
A Java SE-Module und Paketübersicht
Stichwortverzeichnis


Download:

- Listings, ca. 2,7 MB


Buch bestellen
Ihre Meinung?



Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom

Einführung, Ausbildung, Praxis
Buch: Java ist auch eine Insel


Java ist auch eine Insel

Pfeil 18 Einführung in grafische Oberflächen
Pfeil 18.1 GUI-Frameworks
Pfeil 18.1.1 Kommandozeile
Pfeil 18.1.2 Grafische Benutzeroberfläche
Pfeil 18.1.3 Abstract Window Toolkit (AWT)
Pfeil 18.1.4 Java Foundation Classes und Swing
Pfeil 18.1.5 JavaFX
Pfeil 18.1.6 SWT (Standard Widget Toolkit) *
Pfeil 18.2 Deklarative und programmierte Oberflächen
Pfeil 18.2.1 GUI-Beschreibungen in JavaFX
Pfeil 18.2.2 Deklarative GUI-Beschreibungen für Swing?
Pfeil 18.3 GUI-Builder
Pfeil 18.3.1 GUI-Builder für JavaFX
Pfeil 18.3.2 GUI-Builder für Swing
Pfeil 18.4 Mit dem Eclipse WindowBuilder zur ersten Swing-Oberfläche
Pfeil 18.4.1 WindowBuilder installieren
Pfeil 18.4.2 Mit WindowBuilder eine GUI-Klasse hinzufügen
Pfeil 18.4.3 Das Layoutprogramm starten
Pfeil 18.4.4 Grafische Oberfläche aufbauen
Pfeil 18.4.5 Swing-Komponenten-Klassen
Pfeil 18.4.6 Funktionalität geben
Pfeil 18.5 Grundlegendes zum Zeichnen
Pfeil 18.5.1 Die paint(Graphics)-Methode für das AWT-Frame
Pfeil 18.5.2 Die ereignisorientierte Programmierung ändert Fensterinhalte
Pfeil 18.5.3 Zeichnen von Inhalten auf einen JFrame
Pfeil 18.5.4 Auffordern zum Neuzeichnen mit repaint(…)
Pfeil 18.5.5 Java 2D-API
Pfeil 18.6 Zum Weiterlesen
 

Zum Seitenanfang

18.5    Grundlegendes zum Zeichnen Zur vorigen ÜberschriftZur nächsten Überschrift

Ist das Fenster geöffnet, lässt sich etwas in dem Fenster zeichnen. Da sich die Wege zwischen AWT und Swing trennen, wollen wir mit dem AWT beginnen und dann alle weiteren Beispiele mit Swing bestreiten.

 

Zum Seitenanfang

18.5.1    Die paint(Graphics)-Methode für das AWT-Frame Zur vorigen ÜberschriftZur nächsten Überschrift

Als einleitendes Beispiel soll uns genügen, einen Text zu platzieren (siehe Abbildung 18.18). Dafür überschreiben wir die Methode paint(Graphics) der Klasse Frame und setzen dort alles hinein, was gezeichnet werden soll, etwa Linien, Texte oder gefüllte Polygone. Der gewünschte Inhalt wird immer dann gezeichnet, wenn das Fenster neu aufgebaut wird oder wenn wir von außen repaint(…) aufrufen, denn genau in diesem Fall wird das Grafiksystem paint(Graphics) aufrufen und das Zeichnen anstoßen:

Listing 18.1    src/main/java/com/tutego/insel/ui/graphics/Bee.java

package com.tutego.insel.ui.graphics;



import java.awt.*;

import java.awt.event.*;



public class Bee extends Frame {



private static final long serialVersionUID = -3800165321162121122L;



public Bee() {

setSize( 500, 100 );



addWindowListener( new WindowAdapter() {

@Override

public void windowClosing ( WindowEvent e ) { System.exit( 0 ); }

} );

}



@Override

public void paint( Graphics g ) {

g.drawString( "\"Maja, wo bist du?\" (Mittermeier)", 120, 60 );

}



public static void main( String[] args ) {

new Bee().setVisible( true );

}

}
Ein Fenster mit gezeichnetem Inhalt

Abbildung 18.18    Ein Fenster mit gezeichnetem Inhalt

Der Grafikkontext Graphics

Das Grafiksystem ruft von unserem Programm die paint(Graphics)-Methode auf und übergibt ein Objekt vom Typ Graphics – bzw. Graphics2D, wie wir später sehen werden. Dieser Grafikkontext bietet verschiedene Methoden zum Setzen von Zeichenzuständen und zum Zeichnen selbst, etwa von Linien, Kreisen, Ovalen, Rechtecken, Zeichenfolgen oder Bildern. Dies funktioniert auch dann, wenn die Zeichenfläche nicht direkt sichtbar ist, wie bei Hintergrundgrafiken.

Das Graphics-Objekt führt Buch über mehrere Dinge:

  • die Komponente, auf der gezeichnet wird (Hier ist das erst einmal das rohe Fenster.)

  • Koordinaten des Bildbereichs und des Clipping-Bereichs. Die Zeichenoperationen außerhalb des Clipping-Bereichs werden nicht angezeigt. Daher wird ein Clipping-Bereich auch Beschnittbereich genannt.

  • die aktuelle Schriftart (java.awt.Font) und die aktuelle Farbe (java.awt.Color)

  • die Pixeloperation (XOR[ 261 ](Um den Grafik-Cursor zu bewegen, wird gern eine XOR-Operation eingesetzt. Obwohl dies absolut einfach erscheint, ist die Realisierungsidee in den USA patentiert. ) oder Paint)

  • die Translation – eine Verschiebung vom Nullpunkt

Wir können nur in der paint(Graphics)-Methode auf das Graphics-Objekt zugreifen. Diese Methode wird immer dann aufgerufen, wenn die Komponente neu gezeichnet werden muss. Dies nutzen wir, um einen Text zu schreiben. Dem Bee-Beispiel ist zu entnehmen, dass die Methode drawString(String text, int x, int y) einen Text in den Zeichenbereich des Grafikkontextes schreibt. Im Folgenden werden wir noch weitere Methoden kennenlernen.

[»]  Hinweis

Etwas ungewöhnlich ist die Tatsache, dass der Nullpunkt nicht oben links in den freien sichtbaren Bereich fällt, sondern dass die Titelleiste den Nullpunkt überdeckt. Um an die Höhe der Titelleiste zu kommen und die Zeichenoperationen so zu verschieben, dass sie in den sichtbaren Bereich fallen, wird ein java.awt.Insets-Objekt benötigt. Ist f ein Frame-Objekt, liefert f.getInsets().top die Höhe der Titelleiste.

 

Zum Seitenanfang

18.5.2    Die ereignisorientierte Programmierung ändert Fensterinhalte Zur vorigen ÜberschriftZur nächsten Überschrift

Der Einstieg in die Welt der Grafikprogrammierung mag etwas seltsam erscheinen, weil in der prozeduralen, nicht ereignisgesteuerten Welt die Programmierung anders verlief. Es gab einige Funktionen, mit denen sich direkt sichtbar auf dem Bildschirm operieren ließ. Hier ein Beispiel[ 262 ](Commodore 128 System Guide, Commodore Business Machines, Inc. 1985, online zugänglich unter http://rvbelzen.tripod.com/c128sg/toc.htm) aus der C128-Zeit:

10 COLOR 0,1                                       :REM SELECT BACKGROUND COLOR

20 COLOR 1,3 :REM SELECT FOREGROUND COLOR

30 COLOR 4,1 :REM SELECT BORDER COLOR

40 GRAPHIC 1,1 :REM SELECT BIT MAP MODE

60 CIRCLE 1,160,100,40,40 :REM DRAW A CIRCLE

70 COLOR 1,6 :REM CHANGE FOREGROUND COLOR

80 BOX 1,20,60,100,140,0,1 :REM DRAW A BLOCK

90 COLOR 1,9 :REM CHANGE FOREGROUND COLOR

100 BOX 1,220,62,300,140,0,0 :REM DRAW A BOX

110 COLOR 1,9 :REM CHANGE FOREGROUND COLOR

120 DRAW 1,20,180 TO 300,180 :REM DRAW A LINE

130 DRAW 1,250,0 TO 30,0 TO 40,40 TO 250,0 :REM DRAW A TRIANGLE

140 COLOR 1,15 :REM CHANGE FOREGROUND COLOR

150 DRAW 1,160,160 :REM DRAW A POINT

160 PAINT 1,150,97 :REM PAINT IN CIRCLE

170 COLOR 1,5 :REM CHANGE FOREGROUND COLOR

180 PAINT 1,50,25 :REM PAINT IN TRIANGLE

190 COLOR 1,7 :REM CHANGE FOREGROUND COLOR

200 PAINT 1,225,125 :REM PAINT IN EMPTY BOX

210 COLOR 1,11 :REM CHANGE FOREGROUND COLOR

220 CHAR 1,11,24,"GRAPHIC EXAMPLE" :REM DISPLAY TEXT

230 FOR I=1 TO 5000:NEXT:GRAPHIC 0,1:COLOR 1,2

Diese Vorgehensweise funktioniert in Java (und auch in vielen modernen Grafiksystemen) nicht mehr. Auch mit Objektorientierung hat sie nicht viel zu tun!

In Java führt ein Repaint-Ereignis zum Aufruf der paint(Graphics)-Methode. Dieses Ereignis kann ausgelöst werden, wenn der Bildschirm zum ersten Mal gezeichnet wird, aber auch, wenn Teile des Bildschirms verdeckt werden. Falls das Repaint-Ereignis eintritt, springt das Java-System in die paint(Graphics)-Methode, in der der Bildschirm aufgebaut werden kann. Nur dort finden die Zeichenoperationen statt. Wenn wir nun selbst etwas zeichnen wollen, kann das nur in der paint(Graphics)-Methode geschehen bzw. in Methoden, die von paint(Graphics) aufgerufen werden. Wenn wir aber selbst etwas zeichnen wollen, wie lässt sich paint(Graphics) dann parametrisieren?

Um mit diesem Problem umzugehen, müssen wir der paint(Graphics)-Methode Informationen mitgeben. Diese Informationen kann die Methode aus den Objektattributen beziehen. Daher implementieren wir eine Unterklasse einer Komponente, die eine paint(Graphics)-Methode besitzt. Anschließend können wir Objektzustände ändern, sodass paint(Graphics) neue Werte bekommt und somit gewünschte Inhalte zeichnen kann.

 

Zum Seitenanfang

18.5.3    Zeichnen von Inhalten auf einen JFrame Zur vorigen ÜberschriftZur nächsten Überschrift

Wenn Swing eine Komponente zeichnet, ruft es automatisch die Methode paint(Graphics) auf. Um eine Grafik selbst in ein Fenster zu zeichnen, ließe sich von JFrame eine Unterklasse bilden und paint(Graphics) überschreiben – das ist jedoch nicht der übliche Weg.

Stattdessen wählen wir einen anderen Ansatz, der sogar unter AWT eine gute Lösung ist: Wir bilden eine eigene Komponente, eine Unterklasse von JPanel (unter AWT Panel, was wir aber nicht mehr weiterverfolgen wollen), und setzen diese auf das Fenster. Wird das Fenster neu gezeichnet, gibt das Grafiksystem den Zeichenauftrag an die Kinder weiter, also an unser spezielles JPanel, und ruft die überschriebene paint(Graphics)-Methode auf. Allerdings überschreiben eigene Unterklassen von Swing-Komponenten im Regelfall nicht paint(Graphics), sondern paintComponent(Graphics). Das liegt daran, dass Swing in paint(Graphics) zum Beispiel noch Rahmen zeichnet und sich um eine Pufferung des Bildschirminhalts zur Optimierung kümmert. So ruft paint(Graphics) die drei Methoden paintComponent(Graphics), paintBorder(Graphics) und paintChildren(Graphics) auf, und bei einer Neudarstellung kümmert sich ein RepaintManager um eine zügige Darstellung mithilfe der gepufferten Inhalte, was bei normalen Swing-Interaktionskomponenten wie Schaltflächen wichtig ist.

Damit ist die Darstellung von Inhalten in einem JFrame einfach. Wir importieren drei Klassen, JPanel und JFrame aus javax.swing sowie Graphics aus java.awt. Dann bilden wir eine Unterklasse von JPanel und überschreiben paintComponent(Graphics):

Listing 18.2    src/main/java/com/tutego/insel/ui/graphics/DrawFirstLine.java, Ausschnitt Teil 1

package com.tutego.insel.ui.graphics;



import java.awt.Graphics;

import javax.swing.*;



class DrawPanel extends JPanel {



@Override protected void paintComponent( Graphics g ) {

super.paintComponent( g );

g.drawLine( 10, 10, 100, 50 );

}

}

Die Methode paintComponent(Graphics) besitzt in der Oberklasse die Sichtbarkeit protected, was wir beibehalten sollten. Die Methode wird nicht von uns von anderer Stelle aufgerufen, daher muss eine Unterklasse die Sichtbarkeit nicht zu public erweitern. Der Aufruf von super.paintComponent(…) ist immer dann angebracht, wenn die Oberklasse ihre Inhalte zeichnen soll. Bei vollständig eigenem Inhalt ist das nicht notwendig.

Der letzte Schritt ist ein Testprogramm, das ein Exemplar des spezialisierten JPanel bildet und auf den JFrame setzt:

Listing 18.3    src/main/java/com/tutego/insel/ui/graphics/DrawFirstLine.java, Ausschnitt Teil 2

public class DrawFirstLine {

public static void main( String[] args ) {

JFrame f = new JFrame();

f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

f.setSize( 100, 100 );

f.add( new DrawPanel() );

f.setVisible( true );

}

}

Die Lösung mit dem JPanel muss nicht die Höhe der Titelleiste berücksichtigen; die Komponente JPanel, die auf das Fenster gesetzt wird, befindet sich korrekt unterhalb der Titelleiste, und die Zeichenfläche liegt nicht verdeckt unter der Titelleiste.

[+]  Tipp

Für einfache Tests lässt sich auch JOptionPane.showMessageDialog(null, new DrawPanel()); einsetzen.

 

Zum Seitenanfang

18.5.4    Auffordern zum Neuzeichnen mit repaint(…) Zur vorigen ÜberschriftZur nächsten Überschrift

Die Methode repaint(…) kann von außen aufgerufen werden, um ein Neuzeichnen zu erzwingen. Wenn die Komponente wie unsere Unterklasse von JPanel eine Swing-Komponente ist, dann wird die paint(Graphics)-Methode der Komponente aufgerufen. Im Fall einer AWT-Komponente, wie Frame, wird update(Graphics) aufgerufen, das ja automatisch paint(Graphics) aufruft.

abstract class java.awt.Component

implements ImageObserver, MenuContainer, Serializable
  • void repaint()

    Erbittet sofortiges Neuzeichnen der Komponente. Entspricht repaint(0, 0, 0, width, height).

  • void repaint(long tm)

    Erbittet ein Neuzeichnen in höchstens tm Millisekunden. Entspricht repaint(tm, 0, 0, width, height).

  • void repaint(int x, int y, int width, int height)

    Erbittet ein Neuzeichnen der Komponente im angegebenen Bereich.

  • void repaint(long tm, int x, int y, int width, int height)

    Erbittet ein Neuzeichnen der Komponente nach höchstens tm Millisekunden im angegebenen Bereich. Die Zeitbeschränkung wird in Swing nicht wirklich verwendet.

 

Zum Seitenanfang

18.5.5    Java 2D-API Zur vorigen ÜberschriftZur nächsten Überschrift

Seit dem JDK 1.2 – und das ist nun schon etwas her – hat sich beim Zeichnen einiges getan. So wird der paint(Graphics)-Methode (und paintComponent(Graphics) ebenso) nicht mehr nur ein Graphics-Objekt übergeben, sondern eine Unterklasse von Graphics, nämlich Graphics2D. Diese Klasse wurde im Rahmen der Java 2D-API aus den Java Foundation Classes (JFC) eingeführt und bietet erweiterte Zeichenmöglichkeiten, die mit der Sprache PostScript vergleichbar sind. Als wichtige Ergänzung sind Transformationen auf beliebig geformten Objekten sowie Füllmustern und Kompositionen zu nennen. Die gezeichneten Objekte sind optional weichgezeichnet.

Da die Java-Entwickler die Signatur der paintXXX(Graphics)-Methoden nicht ändern wollten, blieb Graphics als Parametertyp stehen, und wir müssen es, um die erweiterte Funktionalität nutzen zu können, im Rumpf wie folgt auf Graphics2D anpassen:

@Override protected void paintComponent( Graphics g ) {

Graphics2D g2 = (Graphics2D) g;



}

Obwohl Graphics2D selbst im java.awt-Paket untergebracht ist, befinden sich viele der 2D-Klassen im Paket java.awt.geom.

[»]  Hinweis

Das Grafiksystem übergibt uns in der paintXXX(Graphics)-Methode zwar immer ein Objekt vom Typ Graphics2D, aber wir werden in den Beispielprogrammen nur dann eine Typumwandlung vornehmen, wenn wir wirklich die Erweiterungen von Graphics2D nutzen.

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java ist auch eine Insel Java ist auch eine Insel

Jetzt Buch bestellen


 Buchempfehlungen
Zum Rheinwerk-Shop: Captain CiaoCiao erobert Java

Captain CiaoCiao erobert Java




Zum Rheinwerk-Shop: Java SE 9 Standard-Bibliothek

Java SE 9 Standard-Bibliothek




Zum Rheinwerk-Shop: Algorithmen in Java

Algorithmen in Java




Zum Rheinwerk-Shop: Objektorientierte Programmierung

Objektorientierte Programmierung




 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz

InfoInfo



 

 


Copyright © Rheinwerk Verlag GmbH 2021

Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.

Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 

[Rheinwerk Computing]



Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de



Cookie-Einstellungen ändern