Tutorial: Eine einfache Java GUI

Zurück

Im Folgenden wird gezeigt, wie man eine einfache Java-GUI (Graphical User Interface) mit Swing erstellen kann, z.B. um Werte an ein Rechenprogramm zu übergeben o.ä.

Das Fenster

Eine neue Klasse erstellen

Um die GUI zu implementieren, erstellt man erstmal eine neue Klasse, die von JFrame ableitet. Eclipse ist ja so freundlich einem dabei zu helfen, rauskommen sollte sowas hier:

import javax.swing.JFrame;


public class AppWindow extends JFrame {

}

Das Layout

Swing bietet einem diverse sog. Layout-Manager, die dabei helfen, die Elemente der GUI sinnvoll anzuordnen und es ermöglichen, dass Fenster auch dann noch gut benutzbar sind, wenn die Größe verändert wird.

Darauf gehe ich hier nicht ein, da das hier zu weit führt. Wir benutzen hier keinen Layout-Manager, sondern geben die Positionen der Elemente im Quellcode an.

Also geben wir im Constructor das Layout "null" (also nix) an und rufen noch eine zu erstellende Funktion auf, die dafür zuständig sein wird, die Elemente des Fensters zu instanzieren und zu initialisieren:

public AppWindow() {
	this.getContentPane().setLayout(null);

	this.initWindow();

}	

Die Elemente

Für die einfache GUI des Programms "DM2Euro" brauchen wir: ein Texteingabefeld, in das der DM-Wert eingegeben werden soll und ein Texteingabefeld, das hier zur Ausgabe genutzt wird und das Ergebnis (also den Euro-Wert) aufnimmt.

Die Texteingabefelder sind Objekte der Klasse JTextField, der Button ist ein Objekt der Klasse JButton.

Frisch ans Werk:

Als Klassenvariablen, also direkt unter

public class AppWindow extends JFrame { 
definieren wir die Objekte:

	JTextField 	textfield_dm;
	JTextField 	textfield_euro;

	JButton		button;

In der Methode initWindow() werden diese Objekte instanziert und die Positionen festgelegt.

	protected void initWindow() 
	{
		// Instanzieren:
		textfield_dm = new JTextField();
		textfield_euro = new JTextField();
		
		// Hier auch gleich die Beschriftung des Buttons mit angeben:
		button = new JButton("DM in Euro");
			

Die Methode setBounds(...) nimmt vier int-Parameter entgegen: x-Position, y-Postition, Breite und Höhe:

				
		// Positionen festlegen
		textfield_dm.setBounds(5,10,400,25);
		textfield_euro.setBounds(5,80,400,25);
		
		button.setBounds(300,110,100,30);
		
		

Dann müssen wir die Elemente nur noch dem Fenster hinzufügen ...

		
		
		// Elemente dem Fenster hinzufügen:
		// (this ist ein Zeiger auf dieses Objekt, also das Fenster)
		this.getContentPane().add(textfield_dm);
		this.getContentPane().add(textfield_euro);
		this.getContentPane().add(button);
		
		// Das kommt ganz am Ende:
		this.pack();
	}

Nun haben wir die Elemente dem Fenster hinzugefügt. Das bringt uns aber noch nicht so viel, ein Klick auf den Button würde nichts bewirken. Wir brauchen einen sog. ActionListener, den wir auch in initWindow() einbauen.

Der ActionListener ist dafür zuständig sog. ActionEvents zu empfangen. Wir möchten natürlich mitbekommen, wenn der Benutzer den Button anklickt. Würden wir den ActionListener nicht hinzufügen, könnte der Nutzer solange auf den Knopf drücken wie er wollte, es würde nichts passieren. Wenn wir aber den ActionListener hinzufügen, dann wird die Methode actionPerformed(...) immer dann ausgeführt, wenn der User auf den Button klickt.

Anmerkung: es gibt verschiedene "Listener", die man einem Objekt hinzufügen kann, z.B. den WindowListener, den wir weiter unten diesem Fenster hinzufügen. Der sorgt dafür, dass sich das Programm beendet sobald das Fenster geschlossen wird. Mit anderen Worten: er horcht ("Listener") und wenn der Nutzer das Fenster schließt wird die entsprechende Funktion ausgeführt - windowClosing(...). Weitere Infos findet Ihr hier: Learning Swing by Example

	button.addActionListener(new ActionListener() {

		public void actionPerformed(ActionEvent arg0) {
			buttonBerechneClicked();
		}
		
	});

Dies fügt dem Button einen neuen ActionListener hinzu. Die Methode actionPerformed() wird aufgerufen, wenn der Benutzer den Button anklickt. actionPerformed() wiederrum tut nichts anderes, als die Methode buttonBerechneClicked() aufzurufen, die wir der Einfachheit halber auch direkt in der Klasse implementieren (würde man bei "richtigen" Projekten meist anders machen, hier ist das aber zu vertreten).

	public void buttonBerechneClicked()
	{
		double dm = 0;

Hier haben wir einen Try-Catch-Block, der Fehleingaben abfängt, falls z.B. textfield_dm.getText() einen String liefert, der sich nicht in eine Zahl übersetzen lässt. Wenn die Umwandlung fehlschlägt (also das "try" eine Exception auslöst), wird der Code im "catch"-Block ausgeführt. In diesem Fall wird dm einfach auf -1 gesetzt. Da negative Geldbeträge nicht vorgesehen sind, können wir so später eine Fehlerausgabe machen, wenn dm negativ ist:

		
		// Hole Zahl aus Textfeld:
		try {
			dm = Double.parseDouble(textfield_dm.getText());
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			dm = -1;
		}

Dann eine Fallunterscheidung, nur wenn dm > oder = 0 ist, wird das Ergebnis berechnet, ansonsten eine Fehlermeldung ausgegeben:

    
		// Falls das n Okay ist:
    
		if (dm>=0) {
			// Rechne:
			double euro = this.dm2euro(dm);

		

Die Berechnungsfunktion dm2euro(...) findet sich im Komplett-Quelltext weiter unten.


			// Packe a in Ausgabefeld, und zwar formatiert:
			
			// Dies ist nur für die Formatierung (x.xx) zuständig:
			NumberFormat nf = NumberFormat.getInstance();
			nf.setMaximumFractionDigits(2);

			

Die Formatierung sorgt nur dafür, dass man sinnvolle Euro-Beträge herausbekommt, also mit zwei Stellen hinter dem Komma. nf.format(...) gibt einen String zurück.

				
			
			String ausgabe = nf.format(euro);
   			
			// Der String wird hier ins Feld geschrieben:
			textfield_euro.setText(ausgabe);
			
		} else {
			
			textfield_euro.setText("Eingabe ist nicht in Ordnung.");
		
		}
	}

Das war's eigentlich schon.

Der Vollständigkeit halber fügen wir im Constructor des Fensters noch einen WindowListener hinzu, der die Anwendung beendet, sobald das Fenster geschlossen wird.

		this.addWindowListener(new WindowListener() {

					// ... (einige Methoden hier weggelassen, sie Quellcode unten)

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

					// ...


				});		
	

Nun müssen wir in der Hauptklasse (dort wo die Methode static void main ist) noch das Fenster aufrufen:

public class Tutorial_1 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		AppWindow theAppWindow = new AppWindow();
		theAppWindow.setBounds(10, 10, 420, 180);
		theAppWindow.show();
	}

}
	
	

Wer mag, kann ja das Programm ein wenig schöner machen und z.B. Überschriften für die Eingabefelder einbauen
(Tip: JLabel).

Erscheint jetzt vielleicht recht umfangreich, aber man kann sowas ja wiederverwenden und von Fall zu Fall anpassen. Es gibt auch GUI-Builder, die einem da viel Arbeit abnehmen, z.B. Netbeans oder auch Plugins für Eclipse.

Quellcode komplett

Tutorial_1.java

public class Tutorial_1 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		AppWindow theAppWindow = new AppWindow();
		theAppWindow.setBounds(10, 10, 420, 180);
		theAppWindow.show();
	}

}
	

AppWindow.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.text.NumberFormat;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

import com.apple.eawt.Application;


public class AppWindow extends JFrame {

	JTextField 	textfield_dm;
	JTextField 	textfield_euro;

	JButton		button;


	public AppWindow() {
		this.getContentPane().setLayout(null);

		this.initWindow();

		this.addWindowListener(new WindowListener() {

			public void windowClosed(WindowEvent arg0) {


			}

			public void windowActivated(WindowEvent e) {


			}

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

			public void windowDeactivated(WindowEvent e) {


			}

			public void windowDeiconified(WindowEvent e) {


			}

			public void windowIconified(WindowEvent e) {


			}

			public void windowOpened(WindowEvent e) {


			}



		});

	}

	protected void initWindow() 
	{
		// Instanzieren:
		textfield_dm = new JTextField();
		textfield_euro = new JTextField();

		button = new JButton("DM in Euro");

		button.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				buttonBerechneClicked();
			}

		});

		// Positionen festlegen
		textfield_dm.setBounds(5,10,400,25);
		textfield_euro.setBounds(5,80,400,25);

		button.setBounds(300,110,100,30);

		// Elemente dem Fenster hinzufügen:
		this.getContentPane().add(textfield_dm);
		this.getContentPane().add(textfield_euro);
		this.getContentPane().add(button);


		this.pack();
	}

	public void buttonBerechneClicked()
	{
		// Hole Zahl aus Textfeld:
		double dm = 0;
		try {
			dm = Double.parseDouble(textfield_dm.getText());
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			dm = -1;
		}

		// Falls das n Okay ist:

		if (dm>=0) {
		// Rechne:
			double euro = this.dm2euro(dm);

			// Packe a in Ausgabefeld:
			NumberFormat nf = NumberFormat.getInstance();

			nf.setMaximumFractionDigits(2);

			String ausgabe = nf.format(euro);



			textfield_euro.setText(ausgabe);
		} else {
			textfield_euro.setText("Eingabe ist nicht in Ordnung.");
		}
	}

	public double dm2euro(double dm)
	{
		double euro = (dm / 1.95583);



		return euro;
	}
}

	

Download

Zip mit beiden Java-Dateien

Anregungen, Fragen, Kritik: greulich@uni-koblenz.de

Impressum · Datenschutz