Rheinwerk Computing < openbook >


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


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 19 Einführung in grafische Oberflächen
Pfeil 19.1 GUI-Frameworks
Pfeil 19.1.1 Kommandozeile
Pfeil 19.1.2 Grafische Benutzeroberfläche
Pfeil 19.1.3 Abstract Window Toolkit (AWT)
Pfeil 19.1.4 Java Foundation Classes und Swing
Pfeil 19.1.5 JavaFX
Pfeil 19.1.6 SWT (Standard Widget Toolkit) *
Pfeil 19.2 Deklarative und programmierte Oberflächen
Pfeil 19.2.1 GUI-Beschreibungen in JavaFX
Pfeil 19.2.2 Deklarative GUI-Beschreibungen für Swing?
Pfeil 19.3 GUI-Builder
Pfeil 19.3.1 GUI-Builder für JavaFX
Pfeil 19.3.2 GUI-Builder für Swing
Pfeil 19.4 Mit dem Eclipse WindowBuilder zur ersten Swing-Oberfläche
Pfeil 19.4.1 WindowBuilder installieren
Pfeil 19.4.2 Mit WindowBuilder eine GUI-Klasse hinzufügen
Pfeil 19.4.3 Das Layoutprogramm starten
Pfeil 19.4.4 Grafische Oberfläche aufbauen
Pfeil 19.4.5 Swing-Komponenten-Klassen
Pfeil 19.4.6 Funktionalität geben
Pfeil 19.5 Grundlegendes zum Zeichnen
Pfeil 19.5.1 Die paint(Graphics)-Methode für den AWT-Frame
Pfeil 19.5.2 Die ereignisorientierte Programmierung ändert Fensterinhalte
Pfeil 19.5.3 Zeichnen von Inhalten auf einen JFrame
Pfeil 19.5.4 Auffordern zum Neuzeichnen mit repaint(…)
Pfeil 19.5.5 Java 2D-API
Pfeil 19.6 Zum Weiterlesen
 

Zum Seitenanfang

19.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

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

Als einleitendes Beispiel soll uns genügen, einen Text zu platzieren (siehe Abbildung 19.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 19.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 19.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

19.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 Objektvariablen 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

19.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 19.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 an 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 19.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

19.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

19.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 paint*(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 paint*(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: Algorithmen in Java

Algorithmen in Java




Zum Rheinwerk-Shop: Spring Boot 3 und Spring Framework 6

Spring Boot 3 und Spring Framework 6




Zum Rheinwerk-Shop: Java SE 9 Standard-Bibliothek

Java SE 9 Standard-Bibliothek




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

InfoInfo



 

 


Copyright © Rheinwerk Verlag GmbH 2024

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