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 TextJTextField(int columns)
: Erzeugt ein Textfeld mit einer Angabe an Zeichen. Diese wird nur dazu verwendet, um diepreferredSize
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 bestimmtenDocument
(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. MitString 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.
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
Hallo abdollah,
habe die beiden kleinen Fehler im Code ausgebessert. Danke für den Hinweis!
Gruß
Stefan
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
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)){
Hallo Sebastian,
ja das stimmt. Es müsste außerdem
, also isDigit und nicht istDigit heißen. Danke für den Hinweis.
Grüße
Stefan
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