13.02.04 JLabel und JTextfield

In den letzten Kapiteln haben Sie gelernt, mit dem JFrame und dem JDialog umzugehen. Außerdem haben Sie erfahren wie JButtons funktionieren, und wie man Komponenten ohne viel Aufwand auf Fenster setzt. Doch mit Fenstern und Buttons können Sie schwer eine benutzerfreundliche Oberfläche basteln. Deshalb widmen wir uns in diesem Kapitel den Textfeldern und deren Beschriftung, den Labels.

Wozu sind Textfelder und Labels gut?

Diese Frage mag vielleicht banal klingen, trotzdem sollten wir uns darüber Gedanken machen. Textfelder sind dafür zuständig, komplexere Eingaben wie Text vom Benutzer entgegen zu nehmen. Für Ja/Nein-Fragen sind sie also nicht geeignet. Außerdem müssen Textfelder manchmal in der Lage sein, gewisse Eingaben zu verbieten, beispielsweise stören Buchstaben in einem Feld, das für die Eingabe eines Datums gedacht ist.
Damit wäre geklärt, was Textfelder sind, aber nicht, was Labels sind. Labels sind nichts anderes als Beschriftungen und Hinweise an den Benutzer. Sie stehen oft neben Steuerelementen, können aber auch alleine stehen.
Swing bietet mehrere Klassen für die Eingabe von Texten an, die einfachste und verbreiteste Klasse ist die Klasse JTextField, mit der wir uns in diesem Kapitel beschäftigen. Für Beschriftungen wird die Klasse JLabel genommen.

Die Grundlagen des JTextfield

Die Klasse JTextField besitzt mehrere Konstruktoren:

  • JTextField(): Erzeugt ein neues Textfeld.
  • JTextField(String text): Erzeugt ein Textfeld mit einem Text
  • JTextField(int columns): Erzeugt ein Textfeld mit einer Angabe an Zeichen. Diese wird nur dazu verwendet, um die preferredSize zu errechnen und gibt nicht die maximale Anzahl an Zeichen an.
  • JTextField(String text, int columns): Erzeugt ein Textfeld mit einem Text und einer Zeichenanzahl.
  • JTextField(Document doc, String text, int columns): Erzeugt ein Textfeld mit einem bestimmten Document (dazu weiter unten mehr), einem Text und der Zeichenanzahl.

Ein einfaches JTextField erzeugen Sie demnach auf diese Art:

package de.jbb.jtextfieldtut;

import javax.swing.*;

public class JTextFieldDemo{
  
  public static class Main(String[] args){
    
    JFrame frame = new JFrame("Frame mit einem JTextField");
    frame.setBounds(300,300,400,400);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    JTextField field = new JTextfield();
    frame.add(field);
    frame.setVisible(true);

}

Der eingebene Text kann durch die Methode getText() ermittelt werden. Meistens wird diese Methode beim Klicken eines Buttons oder bei einem anderen Event aufgerufen.

Bekannte Methoden auch beim JTextfield

Das JTextField erbt von der Superklasse JComponent. Das bedeutet, dass das JTextField fast alle Methoden hat, die auch der Button und andere Komponenten hat. Dazu gehören die Methoden setColor(Color c), setSize(int width, int height), setBounds(int x, int y, int width, int height) usw. Da diese Methoden schon in den vorherigen Kapiteln behandelt wurden, werden sie hier nicht wieder näher erklärt.
Obwohl das JTextfield kein Button ist, hat es die Methode addActionListener(ActionListener listener). Der (bzw. die) über diese Methode registrierte ActionListener reagiert auf Betätigung der Taste Enter im JTextField.

Bestimmte Zeichen verbieten

Hin und wieder kann es sinnvoll sein, bestimmte Zeichen in einem Textfeld von vornherein zu verbieten, anstatt die verbotenen Zeichen später wieder zu löschen.
Zwar bringt Java dafür nichts fertiges wie eine Methode setForbiddenChar(Char c) oder so ähnlich mit, es ist aber auch nicht sonderlich schwer, sich so etwas selbst zu bauen.
Ein wesentlicher Aspekt der Objektorientierten Programmierung ist die Trennung von Grafik und Daten, bzw. Inhalten. In Swing ist dieser Grundsatz größtenteils umgestzt. Die Klasse JTextField kümmert sich genau genommen nur um das Aussehen der Komponente. Der Inhalt, also der Text, die Eingabe, wird von einem Document verarbeitet. Wenn Sie das JTextField wie oben beschrieben verwenden, werden Sie vom Document selten etwas mitbekommen, es wird einfach ein Standarddokument, das PlainDocument verwendet. Wenn Sie aber Zeichen verbieten wollen gehört das zum Inhalt und muss deswegen über ein Document implementiert werden.

Zuerst müssen Sie eine Klasse schreiben, die die Schnittstelle Document implementiert. Da Sie aber nur eine Methode ändern wollen, nämlich die, die sich um das Einfügen von Zeichen kümmert, ist es sinnvoller, einfach von der Klasse PlainDocument aus dem Paket javax.swing.text zu erben.
Danach müssen Sie noch die Methode insertString(int offs, String s, AttributeSet a) entsprechend überschreiben, um bestimmte Zeichen zu verbieten. Diese Methode ist für das Verändern des Textes zuständig. offs gibt die Cursorposition an (und damit die Stelle, an der das Zeichen/die Zeichenkette eingefügt werden soll), s die einzufügende Zeichenkette und das AttributeSet a hält Informationen über die grafische Ausgabe bereit.
Das Vorgehen dabei ist einfach: Sie prüfen, ob der String s, der eingefügt werden soll, Ihren Anforderungen entpricht. Ist dies der Fall, rufen Sie einfach die Super-Methode auf, ansonsten können Sie einen Beep-Ton, eine Fehlermeldung oder gar nichts ausgeben. Beispielhaft wird hier gezeigt, wie Sie die Eingabe von Buchstaben und mehrzeichige Eingaben verbieten:

package de.jbb.jtextfieldtut

import javax.swing.text.PlainDocument;

public Class NoLettersDocument extends PlainDocument{

  @Override
  public void insertString(int offs, String s, AttributeSet a)
    
    if(Character.isDigit(s.charAt(0))&& s.length == 1){
      super.insertString(offs, s, a);
    }
}

Damit Ihr JTextField das Document verwenden kann, müssen Sie eine Instanz des NoLettersDocuments mithilfe des Konstruktors oder mit der Methode setDocument(Document document) einsetzen.

Markierungen

Oft kommt es vor, dass Eingaben in einem Formular wieder geändert werden müssen. Dabei ist es hilfreich, wenn sich automatisch der gesamte Text markiert, sodass er bei der nächsten Eingabe automatisch gelöscht wird. Um dies zu realisieren ist es notwendig, auf das Event „Focus gained“ zu hören. Mit anderen Worten: Sie benötigen einen Listener. Nur eben keinen ActionListener, wie Sie ihn vom JButton kennen, sondern einen FocusListener. Das Problem ist allerdings, dass es sich beim FocusListener um eine Schnittstelle mit vielen Methoden handelt, die Sie alle implementieren müssten, obwohl Sie ja nur ein Event möchten. Doch hier haben Ihnen die Java-Entwickler Arbeit abgenommen und eine Klasse FocusAdapter entwickelt, die FocusListener implementiert, aber die Methoden dennoch leer lässt. So können Sie von FocusAdapter erben und nur die für Sie interessante Methode überschreiben und den Code, der das gesamte Textfeld markiert, implementieren. In unserem Fall wäre das schlicht die Methode selectAll(). In der Praxis sieht das dann so aus:

...
import java.awt.event.*;
import javax.swing.*;
...
textField.addFocusListener(new FocusAdapter() {

  @Overide public void focusGained(FocusEvent evt){
    textField.selectAll();
  }
});

Passwörter eingeben und verarbeiten

Eine erwähnenswerte Unterklasse von JTextField ist das JPasswordField, welches sich vom JTextField dadurch unterscheidet, dass alle Eingaben mit einem Char maskiert werden, wie es bei Passworteingeben normalerweise immer der Fall ist. Das JPasswordField verhält sich sonst wie es das JTextField auch tut. Zwei Methoden möchte ich aber dennoch hervorheben:

  • setEchoChar(Char c): Repräsentiert das Zeichen, welches anstatt des Passwortes angezeigt wird. Wird kein Zeichen festgelegt, wird ein Sternchen (*) verwendet.
  • getPassword(): Gibt das Password in einem Array aus Chars zurück. Mit String pass = new String(charArray) lässt sich dieses Array in einen String umwandeln.

Das JPasswordField verfügt zwar über die Methode getText(), diese ist aber depraced und sollte durch getPassword() ersetzt werden. Das gleiche gilt für die entsprechenden set-Methoden.

Das JLabel

Die Klasse JLabel ist sehr simpel aufgebaut. Der Text wird mit der Methode setText(String text) oder gleich im Konstrukor JLabel(String text) gesetzt.
Wie alle anderen Komponenten, hat auch das JLabel die bekannten Methoden setSize(int width, int height), setLocation(int x, int y), setBounds(int x, int y, int width, int height) usw. und die dazu passenden get-Methoden. Für mehr Informationen lesen Sie bitte hier nach: Kapitel 13.02.02

Mnemonics

Da ein JTextField keinen festen Text hat, macht es wenig Sinn, mit Mnemonics darauf zugreifen zu wollen, da der Nutzer nicht weiß welche Alt-X-Kombination er verwenden soll. In Verbindung mit einem JLabel können Sie aber über eine Alt-Kombination darauf zugreifen. Dazu bietet das JLabel zwei Methoden an. setDisplayedMnemonic(Char c), über welche Sie festlegen können, mit welcher das Taste man auf das Textfeld zugreifen kann. Anschließend müssen Sie mit der Methode setLabelFor(Component c) dem JLabel mitteilen, welche Komponente beim Betätigen der Tastenkombination aktiviert werden soll. Folgender Quellcode verdeutlicht die Vorgehensweise:

public static void main(String[] args){

  JFrame frame = new JFrame("Label-Demo");
  frame.setBounds(400,400,500,500);
  frame.setLayout(new GridLayout(0,1));
  frame.setDefaultCloseOperation(JFRAME.EXIT_ON_CLOSE);

  JTextfield userNameField = new JTextField();

  JLabel userNameLabel = new JLabel("Benutzername");
  userNameField.setDisplayedMnemonic('B');
  userNameLabel.setLabelFor(userNameField);

  frame.add(userNameLabel);
  frame.add(userNameField);
  frame.setVisible(true);
}

Die Methode setDisplayedMnemonic(Char c) unterstreicht immer den ersten Buchstaben, der zum Char passt. Wenn Sie beispielsweise in obigen Beispiel das „B“ schon vergeben hätten und stattdessen das „n“ nehmen, wird das erste „n“ unterstrichen, was sehr gewöhnungsbedürftig ausschaut, da man erwartet, dass „name“ unterstrichen wird. Hier kann Ihnen die Methode setDisplayedMnemonicIndex(int i) helfen, mit der Sie angeben können, welche Position im Wort unterstrichen werden soll. Davor müssen Sie aber trotzdem mit setDisplayedMnemonic(Char c) das Mnemonic setzen.

Ihre Anwendung wächst

Die Grundzüge von Swing haben Sie jetzt erlernt, darunter, wie man Komponenten anordnet, Buttons verwendet und Textfelder konfiguriert. Im nächsten Kapitel lernen Sie Schalftflächen kennen, die Ihnen Arbeit ersparen und Ihre Oberfläche benutzerfreundlicher gestalten können.

6 Replies to “13.02.04 JLabel und JTextfield”

  1. abdollah

    sehr gut gemacht! Nur manchmal gibt’s Schreibfehler(z.B.: lenght statt length). und bei Textfelder der Code funktioniert nicht wegen getChar(0)-Methode; ich weiss nicht warum

  2. Sebastian

    Hallo,

    bin froh, dass der User abdollah auch schon gepostet hat. Es ist mir ja etwas peinlich, dass ich heute nur auf kleiner Tippfehler aufmerksam mache, statt programmieren zu üben.

    Jedenfalls sind zwei-drei kleine Vertipper in „prefferedSize zu errechen“. Das steht beim dritten Beispiel zu den JTextField-Konstruktoren. also „preferredSize“ und errechnen mit noch einem n.

    Ich hoffe ich werde mehr als Hilfe denn als Plage wahrgenommen.

    MfG Sebastian

  3. Sebastian

    In der Zeile…

    if(Character.istDigit(s.charAt(0) && s.length == 1){

    …werden drei runde Klammern geöffnet, aber nur zwei geschlossen. Ich glaube es müsste so lauten:

    if(Character.istDigit(s.charAt(0) && s.length == 1)){

  4. Stefan Kiesel

    Hallo Sebastian,

    ja das stimmt. Es müsste außerdem

    if(Character.isDigit(s.charAt(0)) && s.length == 1){

    , also isDigit und nicht istDigit heißen. Danke für den Hinweis.

    Grüße
    Stefan

  5. Fabian Feitsch

    Hallo Sebastian,

    du hast recht, in dieser Zeile ist ein Fehler, aber du hast ihn nicht korrekt verbessert 🙂 . Es muss natürlich lauten:


    if(Character.isDigit(s.charAt(0)) && s.length == 1){

    Ist ausgebessert.

    Und es kein Problem, mich auf meine Tippfehler hinzuweisen, ich proviziere das ja auch, indem ich einfach zu faul bein, meine Kapitel angemessen korrekturzulesen 😉 .

    Grüße,
    Fabian

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.