Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5 (Tiger-Release)
Buch: Java ist auch eine Insel
gp Kapitel 15 Komponenten, Container und Ereignisse
  gp 15.1 Es tut sich was – Ereignisse beim AWT
    gp 15.1.1 Was ist ein Ereignis?
    gp 15.1.2 Die Klasse AWTEvent
    gp 15.1.3 Events auf verschiedenen Ebenen
    gp 15.1.4 Ereignisquellen, -senken und Horcher (Listener)
    gp 15.1.5 Listener implementieren
    gp 15.1.6 Listener bei Ereignisauslöser anmelden/abmelden
    gp 15.1.7 Aufrufen der Listener
  gp 15.2 Varianten, das Fenster zu schließen
    gp 15.2.1 Eine Klasse implementiert die Schnittstelle WindowListener
    gp 15.2.2 Adapterklassen nutzen
    gp 15.2.3 Innere Mitgliedsklassen und innere anonyme Klassen
    gp 15.2.4 Generic Listener
  gp 15.3 Komponenten im AWT und in Swing
    gp 15.3.1 Peer-Klassen und Lightweight-Komponenten
    gp 15.3.2 Die Basis aller Komponenten: Component und JComponent
    gp 15.3.3 Proportionales Vergrößern eines Fensters
    gp 15.3.4 Dynamisches Layout während einer Größenänderung
    gp 15.3.5 Hinzufügen von Komponenten
  gp 15.4 Das Swing-Fenster JFrame
    gp 15.4.1 Kinder auf einem Swing-Fenster
    gp 15.4.2 Schließen eines Swing-Fensters
    gp 15.4.3 JWindow und JDialog
  gp 15.5 Informationstext über die Klasse JLabel
    gp 15.5.1 Mehrzeiliger Text, HTML in der Darstellung
  gp 15.6 Die Klasse ImageIcon
    gp 15.6.1 Die Schnittstelle Icon
    gp 15.6.2 Was Icon und Image verbindet
  gp 15.7 Eine Schaltfläche (JButton)
    gp 15.7.1 Der aufmerksame ActionListener
    gp 15.7.2 Generic Listener für Schaltflächen-Ereignisse verwenden
    gp 15.7.3 AbstractButton
    gp 15.7.4 JToggleButton
  gp 15.8 Tooltips
  gp 15.9 Der Container JPanel
  gp 15.10 Alles Auslegungssache: die Layoutmanager
    gp 15.10.1 FlowLayout
    gp 15.10.2 BorderLayout
    gp 15.10.3 GridLayout
    gp 15.10.4 Der GridBagLayout-Manager
    gp 15.10.5 Null-Layout
    gp 15.10.6 Weitere Layoutmanager
  gp 15.11 Horizontale und vertikale Schieberegler
    gp 15.11.1 Der AdjustmentListener, der auf Änderungen hört
  gp 15.12 JSlider
  gp 15.13 Ein Auswahlmenü – Choice, JComboBox
    gp 15.13.1 ItemListener
    gp 15.13.2 Zuordnung einer Taste mit einem Eintrag
    gp 15.13.3 DateComboBox
  gp 15.14 Eines aus vielen – Kontrollfelder (JCheckBox)
    gp 15.14.1 Ereignisse über ItemListener
  gp 15.15 Kontrollfeldgruppen, Optionsfelder und JRadioButton
  gp 15.16 Der Fortschrittsbalken JProgressBar
  gp 15.17 Rahmen (Borders)
  gp 15.18 Symbolleisten alias Toolbars
  gp 15.19 Menüs
    gp 15.19.1 Die Menüleisten und die Einträge
    gp 15.19.2 Menüeinträge definieren
    gp 15.19.3 Mnemonics und Shortcuts (Accelerator)
    gp 15.19.4 Beispiel für ein Programm mit Menüleisten
    gp 15.19.5 Popup-Menüs
  gp 15.20 Das Konzept des Model-View-Controllers
  gp 15.21 List-Boxen
  gp 15.22 JSpinner
  gp 15.23 Texteingabefelder
    gp 15.23.1 Text in einer Eingabezeile
    gp 15.23.2 Die Oberklasse der JText-Komponenten: JTextComponent
    gp 15.23.3 JPasswordField
    gp 15.23.4 Validierende Eingabefelder
    gp 15.23.5 Mehrzeilige Textfelder
    gp 15.23.6 Die Editor-Klasse JEditorPane
  gp 15.24 Bäume mit JTree-Objekten
    gp 15.24.1 Selektionen bemerken
  gp 15.25 Tabellen mit JTable
    gp 15.25.1 Ein eigenes Tabellen-Model
    gp 15.25.2 AbstractTableModel
    gp 15.25.3 DefaultTableModel
    gp 15.25.4 Ein eigener Renderer für Tabellen
    gp 15.25.5 Zell-Editoren
    gp 15.25.6 Größe und Umrandung der Zellen
    gp 15.25.7 Spalteninformationen
    gp 15.25.8 Tabellenkopf von Swing-Tabellen
    gp 15.25.9 Selektionen einer Tabelle
    gp 15.25.10 Ein professionelles Tabellenlayout mit JGrid
  gp 15.26 JRootPane, JLayeredPane und JDesktopPane
    gp 15.26.1 JRootPane und JLayeredPane
    gp 15.26.2 JDesktopPane und die Kinder JInternalFrame
    gp 15.26.3 Der Farbauswahldialog JColorChooser
    gp 15.26.4 Der Dateiauswahldialog
  gp 15.27 Flexibles Java-Look&Feel
  gp 15.28 Swing-Beschriftungen einer anderen Sprache geben
  gp 15.29 Die Zwischenablage (Clipboard)
  gp 15.30 Undo durchführen
  gp 15.31 Ereignisverarbeitung auf unterster Ebene
  gp 15.32 AWT, Swing und die Threads
    gp 15.32.1 Warum Swing nicht Thread-sicher ist
    gp 15.32.2 Swing-Elemente bedienen mit invokeLater() und invokeAndWait()
  gp 15.33 Selbst definierte Cursor
    gp 15.33.1 Flackern des Mauszeigers bei Animationen vermeiden
  gp 15.34 Mausrad-Unterstützung
  gp 15.35 Benutzerinteraktionen automatisieren
    gp 15.35.1 Automatisch in die Tasten hauen
    gp 15.35.2 Mausoperationen
    gp 15.35.3 Methoden zur Zeitsteuerung
    gp 15.35.4 Screenshots
    gp 15.35.5 Funktionsweise und Beschränkungen
    gp 15.35.6 Zeitliches Ausführen mit dem javax.swing.Timer
    gp 15.35.7 MouseInfo und PointerInfo
  gp 15.36 Alternativen zu AWT und Swing
    gp 15.36.1 XML-Beschreibungen der Oberfläche: Swixml, XUL/Luxor
    gp 15.36.2 SWT


Galileo Computing

15.3 Komponenten im AWT und in Swindowntop

Obwohl das Abstract Window Toolkit das Problem einer einheitlichen Benutzeroberfläche lösen sollte, ist dies bei Sun nicht ganz gelungen. Das AWT war von Anfang an zusammengepfuscht. So meint auch James Gosling: »The AWT was something we put together in six weeks to run on as many platforms as we could, and its goal was really just to work. So we came out with this very simple, lowest-common-denominator thing that actually worked quite well. But we knew at the time we were doing it that it was really limited. After that was out, we started doing the Swing thing, and that involved working with Netscape and IBM and folks from all over the place.«

Doch Sun machte sich mit dem AWT noch mehr Probleme. Da es von Anfang an ungenügend durchdacht war, führten die Entwickler von AWT 1.02 auf AWT 1.1 ein anderes Ereignismodell ein. So kostete die Anpassung von komplexen Programmen an das neue Modell einen erheblichen Programmieraufwand – und nicht alle Firmen gingen darauf ein.

Da Sun das AWT einfach gehalten hat, aber Entwickler von Oberflächen einen nicht zu stillenden Hunger nach Komponenten haben, konzipierte Netscape kurzerhand die Internet Foundation Classes (IFC), die das AWT in wesentlichen Punkten ergänzen. Auch Microsoft mischt durch Erweiterungen mit. Die Firma bietet die Application Foundation Class (AFC) an, die aber heute keine Rolle mehr spielt.

Im April des Jahres 1997 haben sich Sun, Netscape und IBM auf eine GUI-Bibliothek geeinigt, die auf Netscapes IFC aufbaut und das AWT in der Java-Version 1.2 erweitert. (Für 1.1.x lässt sich die Bibliothek von den Sun-Seiten laden.) Der Name des Toolkits ist JFC (Java Foundation Classes). Ein Teil der JFC sind neue Komponenten, die so genannten Swing-Komponenten. Obwohl Swing mehr ist als die neuen grafischen Elemente, ist Swing zu einem Synonym für die JFC geworden. Als 1997 in San Francisco auf der JavaOne die neuen Komponenten vorgestellt wurden, entschied sich Georges Saab, ein Mitglied des JFC-Teams, für Musik parallel zur Präsentation. Dies war gerade Swing-Musik, denn der Entwickler glaubte, dass sie wieder in Mode käme. So wurden auch die neuen grafischen Elemente im Paket mit dem Namen Swing abgelegt. Obwohl der Name offiziell dem Kürzel JFC weichen musste, war er doch so populär, dass er weiter bestehen blieb.


Galileo Computing

15.3.1 Peer-Klassen und Lightweight-Komponenten  downtop

Die ursprüngliche AWT-Implementierung benötigt so genannte Peer-Klassen, die als native Funktionen auf der speziellen Benutzeroberfläche implementiert sind. Unter X11 sehen wir auf Motif 2.0 basierende Komponenten und auf Windows entsprechend andere. Eine Schaltfläche unter AWT kennt dann einen Partner auf der Betriebssystemseite, der die Visualisierung vornimmt. Die Partner haben Vor- und Nachteile:

gp  Der Vorteil ist, dass durch die nativen Peer-Klassen die Oberfläche schnell wird und der Speicherverbrauch sich im Rahmen hält.
gp  Leider zeigen die Programme unter den verschiedenen Betriebssystemen bisweilen merkwürdige Seiteneffekte. So kann ein Textfeld unter Windows weniger als 64K Zeichen aufnehmen, bei anderen Oberflächen ist dies egal. Da das AWT auch nur Komponenten anbietet, die auf jeder Plattform verfügbar sind, ist das Angebot an Widgets sehr beschränkt. Moderne grafische Elemente, sei es auch nur ein Icon auf einer Schaltfläche, sind vom AWT nicht vorgesehen.

Tipp   Entwickle eine Oberfläche nach den Wünschen der Benutzer, nicht nach der Schwierigkeit der Umsetzung oder Begrenzung der Hardware.

Eine Leichtgewicht-Komponente (engl. lightweight component) besitzt keinen Peer, also keine direkte Repräsentation im Fenstersystem. Somit gibt es keine speziellen Implementierungen des Systems auf beispielsweise Windows, MacOS oder X11. Dieser Weg ist also plattformunabhängiger, aber leider auch langsamer. Alle Komponenten werden mit primitiven Zeichenoperationen gemalt, so etwa eine Schaltfläche aus einem Rechteck mit Schatten und einem Text in der Mitte. Der Vorteil: Eine Leichtgewicht-Komponente kann durchsichtig sein und muss nicht mehr in einen rechteckigen Bereich passen. Da alle Komponenten nun gemalt werden, lässt sich alles ohne Rücksicht auf das unterliegende grafische System zeichnen.


Galileo Computing

15.3.2 Die Basis aller Komponenten: Component und JComponent  downtop

Die Klasse Component bildet die Basisklasse der Objekte, die als grafische AWT-Komponenten auf den Schirm kommen. Sie wird für Swing-Komponenten noch einmal zu JComponent erweitert. Allerdings leitet JComponent nicht direkt von Component ab, sondern erst von Container (und Container dann direkt von Component). Das hat die Konsequenz, dass jedes JComponent automatisch auch ein Container ist.

Ein Component- und JComponent-Objekt verarbeitet schon eine ganze Reihe von Ereignissen, die allen anderen Komponenten zugute kommen. Mit anderen Worten: An alle Komponenten können Listener für die in der folgenden Tabelle aufgeführten Ereignisse angehängt werden.


Komponente Erzeugte Ereignisse Grund
Component ComponentEvent Komponente wird bewegt, angezeigt, verdeckt oder verschoben.
  FocusEvent Bekommt oder verliert Fokus.
  KeyEvent Tastendruck
  MouseEvent Maus betritt oder verlässt Komponente. Benutzer drückt Maustaste oder bewegt Mauszeiger.
  InputMethodEvent Text- oder Cursor-Veränderung
  HierarchyEvent Hierarchie, zu der die Komponente gehört, verändert sich.
  PropertyChangeEvent Gebundene Eigenschaft ändert sich.
Container ContainerEvent Komponenten werden dem Container hinzugefügt oder gelöscht.
JComponent PropertyChangeEvent Gebundene Eigenschaft ändert sich.
  AncestorEvent Vorgänger wurde modifiziert

Auf Tastendrücke hören: KeyListener und KeyEvent

Jeder java.awt.Component (und somit auch Swing-Komponenten) lässt sich mit addKeyListener() ein KeyListener hinzufügen. Dieser erwartet drei implementierte Methoden:



interface java.awt.event.  KeyListener  
extends EventListener

gp  void keyTyped( KeyEvent e )
Aufruf bei einem eingegebenen Zeichen. Das System löst mehrere Tastendrücke, die ein Zeichen ergeben, zu einem Unicode-Zeichen auf, etwa Shift + a zum Unicode-Buchstaben »A«. Das gedrückte Zeichen lässt sich über getKeyChar() vom KeyEvent erfragen. Es ist möglich, dass das Zeichen kein gültiges Unicode-Zeichen ist und dann ist die Rückgabe CHAR_UNDEFINED (65535).
gp  void keyPressed( KeyEvent e )
gp  void keyReleased( KeyEvent e )

Die letzten beiden Funktion sind systemabhänig und bekommen auch Metatasten mit, also etwa ein Druck auf die Entfernentasten, die Funktionstaste F1, Num Lock oder Caps Lock. Für diese Tasten ist ein virtueller Code (engl. virtuel key code) als Konstante in KeyEvent definiert, der mit VK_ beginnt. Das sind fast 200 Konstanten. Einige Beispiele: VK_BACK_SPACE, VK_BEGIN, VK_CONTROL, VK_DELETE.

Aufklärung über den Zusammenhang schafft ein Stückchen Quellcode, der an eine Komponente gehängt wird. Beachte den Unterschied zwischen getKeyChar() (das Unicode-Zeichen oder CHAR_UNDEFINED) und getKeyCode() (VK-Code).


t.addKeyListener( new KeyListener()
{
 public void keyTyped( KeyEvent e ) {
 System.out.println( "typed " + e.getKeyChar() );
 System.out.println( "typed " + e.getKeyCode() );
 }

 public void keyPressed( KeyEvent e ) {
 System.out.println( "pressed " + e.getKeyChar() );
 System.out.println( "pressed " + e.getKeyCode() );
 }

 public void keyReleased( KeyEvent e ) {
 System.out.println( "released " + e.getKeyChar() );
 System.out.println( "released " + e.getKeyCode() );
 }
});

Aktivert der Benutzer die Taste »a« ist das Ergebnis:


pressed a
pressed 65
typed a
typed 0
released a
released 65

Aktiviert er Shift + a ist das Resultat:


pressed ?
pressed 16
pressed A
pressed 65
typed A
typed 0
released A
released 65
released ?
released 16

Die Tatsache, dass zweimal ein pressed auftaucht, ist dadruch erklärt, dass pressed und release Low-Level-Ereignisse sind, die den Druck auf die Shift-Taste registieren. Das Fragezeichen bei getKeyChar() ist nichts anderes als CHAR_UNDEFINED.

Soll unser Programm erkennen, ob der Nutzer die F1-Taste drückt, schreiben wir in keyPressed():


if ( keyEvent.getKeyChar() == KeyEvent.CHAR_UNDEFINED )
{
  if ( keyEvent.getKeyCode() == KeyEvent.VK_F1 )
    ...
}

Die Position der Komponente

Der Klasse Component gehört eine ganz nützliche Funktion an, um die absolute Position der Komponente auf dem Bildschirm zu ermitteln. Diese Funktion ist besonders dann praktisch, wenn die Position eines Fensters gefragt ist.



abstract class java.awt.  Component  
implements ImageObserver, MenuContainer, Serializable

gp  Point getLocationOnScreen()
Liefert die Position der linken oberen Ecke der Komponente als Punkt-Objekt.

Die Arbeitsweise von getLocationOnScreen() ist einfach: Gehe mit der getParent()-Methode so lange zurück, bis wir zu einem Exemplar von Frame kommen.


Beispiel   Wir wollen den gleichen Trick verwenden, um die absoluten Koordinaten des Cursors am Bildschirm zu bestimmen. Normalerweise bekommen wir sie ja relativ zum Fenster. Hangeln wir uns von der aktuellen Komponente bis zum aktuellen Fenster durch, so können wir die Koordinaten bezüglich des Bildschirms und nicht bezüglich des Fensters der Applikation berechnen, indem vom Frame-Objekt die Methode getLocation() benutzt wird. Nehmen wir an, wir haben bereits die relativen Koordinaten des Cursors in x und y. Dann ergibt sich Folgendes:

Component c = this;

while ( (c = c.getParent()) != null )
  if ( c instanceof JFrame )
    break;

if ( c != null )
{
   Point p = (Frame)c.getLocation();
   x += p.x;
   y += p.y;
}
Haben wir den Vater gefunden, addieren wir die Fenster-Koordinaten zu den relativen Komponenten-Koordinaten, um die absoluten Koordinaten zu erhalten.

Fokus

In einem Gui-System hat nur eine Komponente den Fokus. Das bedeutet, dass diese Komponente in einer besonderen Empfangsbereitschaft steht, und diese auch hervorhebt, etwa durch einen Rahmen, andere Farben oder im Textfeld durch einen blinkenden Cursor.

Der Fokuswechsel wird im Allgemeinen durch einen Mausklick auf die Komponenten durchgeführt, oder durch das Drücken der Tabulator-Taste, was die nächste Komponente in der Reihenfolge auswählt. Shift + Tabulator wählt im Allgemeinen die vorangehende Komponente. Wer der Nachfolger und Vorgänger ist, bestimmt der Fokus-Manager, in Java durch die Zentrale KeyboardFocusManager repräsentiert.

Es ist nicht selbstverständlich, dass ein Fokuswechsel immer möglich ist. Wenn eine Textkomponente etwas fehlerhafte Eingaben registriert, kann die Komponente den Fokuswechsel untersagen und folglich erzwingen, dass der Benutzer eine gültige Eingabe macht. Der Fokuswechsel kann auch programmiert werden, so dass beim Start zum Beispiel die OK-Schaltfläche aktiviert ist.


Hinweis   Falls ein Textfeld nach dem Aufbau und Darstellung den Fokus besitzen soll, lässt sich die für alle Komponenten definierte Methode requestFocus() aus java.awt.Component nutzen. Sei tf eine Textkomponente:

tf.requestFocus();                     // Textkomponente aktivieren


Galileo Computing

15.3.3 Proportionales Vergrößern eines Fensters  downtop

Die Schnittstelle ComponentListener ist Basis für alle Komponenten, die Ereignisse empfangen. Sie definiert vier Methoden, die in der Klasse ComponentAdapter wieder mit leerem Programmblock gefüllt sind.

Abbildung
Hier klicken, um das Bild zu Vergrößern



interface java.awt.event.  ComponentListener  
extends EventListener

gp  void componentHidden( ComponentEvent e )
Wenn die Komponente versteckt wurde.
gp  void componentMoved( ComponentEvent e )
Wenn die Komponente bewegt wurde.
gp  void componentResized( ComponentEvent e )
Wenn die Komponente in der Größe verändert wurde.
gp  void componentShown( ComponentEvent e )
Wenn die Komponente gezeigt wurde.

Wenn wir auf die Größenveränderung eines Fensters achten wollen, so müssen wir mit addComponentListener() einen Listener an das Fenster hängen, der auf die Veränderung reagiert. Wir implementieren eine Klasse, die sich von ComponentAdapter ableitet – die restlichen drei Methoden müssen auf diese Weise nicht mit leeren Rümpfen gefüllt werden – und überschreiben componentResized(). Wenn wir nur das Frame-Objekt als Ereignishorcher mit dem ComponentListener verbinden, ist klar, wer der Auslöser war. Mit getComponent() auf dem Ereignisobjekt bekommen wir genau diesen Frame. Nun ist es Sache des Algorithmus, wie mit der Größenveränderung zu verfahren ist. Eine Möglichkeit ist, die aktuelle Größe mittels getSize() auszulesen und dann das Minimum aus Höhe und Breite wieder mit setSize() zu setzen. Folgendes Programm macht genau dies:

Listing 15.5   ResizeTheFrame.java


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ResizeTheFrame extends JFrame
{
  public ResizeTheFrame()
  {
    setSize( 200, 200 );
    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    setVisible( true );
  }
  public static void main( String args[] )
  {
    new ResizeTheFrame().addComponentListener( new ResizeEvent() );
  }

  static class ResizeEvent extends ComponentAdapter
  {
    public void componentResized( ComponentEvent event )
    {
      if ( event.getID() == ComponentEvent.COMPONENT_RESIZED )
      {
        JFrame f = (JFrame) event.getComponent();

        Dimension d = f.getSize();
        int size = Math.min( d.width, d.height );

        f.setSize( size, size );
      }
    }
  }
}

Wenn die Größenveränderung beginnt, haben wir keinen Einfluss mehr auf den Prozess. Hier unterscheiden sich die Betriebssysteme. Unter Windows wird nicht bei jeder Pixeländerung ein Ereignis ausgelöst, sondern nur am Ende einer Größenänderung. Bei Linux werden während der Bewegung Ereignisse ausgelöst, so dass eine flüssige Bewegung entsteht.


Galileo Computing

15.3.4 Dynamisches Layout während einer Größenänderundowntop

Wird ein Fenster vergrößert, dann kann während der Größenänderung der Inhalt sofort neu ausgerichtet und gezeichnet werden oder auch nicht. Wird er nicht dynamisch angepasst, dann sieht der Benutzer diese Anpassung erst nach dem Loslassen der Maus, wenn die Größenänderung abgeschlossen wurde. Dieses dynamische Vergrößern lässt sich seit 1.4 im Toolkit-Objekt einstellen. Dazu dient die Methode setDynamicLayout(boolean dynamic). Abfragen lassen sich mit isDynamicLayoutSet() und isDynamicLayoutActive() vornehmen.


Galileo Computing

15.3.5 Hinzufügen von Komponenten  toptop

Ein Container nimmt Komponenten auf und setzt sie mit Hilfe eines Layoutmanagers in die richtige Position. Die Container werden in Java über die Klasse Container verwaltet. Ein Container, den wir schon kennen gelernt haben, ist Frame. Komponenten werden mit Hilfe der add()-Methode einem Container hinzugefügt.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 15.1   AWT-Container

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 15.2   Ein Container kann sich selbst aufnehmen.


Hinweis   AWT- und Swing-Komponenten sollten nicht gemischt werden. Da AWT-Komponenten schwergewichtig sind und vom Betriebssystem gezeichnet werden, werden sie immer über allen anderen Komponenten gezeichnet.

Da Container selbst ein Component ist, können auch Container wiederum Container aufnehmen. Das ist ein bekanntes Design-Pattern und nennt sich Composite Pattern.






1   So lässt sich das im Interview vom 24. März 1998 unter http://java.sun.com/javaone/javaone98/keynotes/gosling/transcript_gosling.html nachlesen.

2   Wir haben uns in den vorangegangenen Abschnitten auch gar nicht mit dem älteren Ereignismodell beschäftigt. Damals wurden alle Ereignisse eines Fensters an einer Stelle gesammelt und ausgewertet. Das führte zu einer Riesenmethode, die die Typen der Ereignisse testete und dann weitervermittelte.





Copyright © Galileo Press GmbH 2004
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.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de