Hallo Leute
in meinem Programm hab ich ein JTextField, in dem ich gerne Text anzeigen lassen würde wenn der "eigentliche Text" leer ist (also "") und der dann natürlich verschwindet, wenn das JTextField den Focus bekommt. Hab dafür aber irgendwie keine Methode gefunden. Muss ich das selber programmieren, oder gibt es dafür eine nette vorgefertigte Methode. Hab schon nach gegoogelt aber irgendwie fehlen mir da die richtigen Schlagwörter. Wenn ich nach "JTextField Background Text" suche spuckt die Suchmaschine nichts brauchbares aus.
Danke für jeden Tipp wo ich suche könnte, oder einen kleinen Verweis auf die entsprechende Stelle in den JavaDocs
JTextField "Hintergrundtext"
-
Nicholas1991 -
7. April 2010 um 23:01 -
Unerledigt
-
-
Bin mir ziemlich sicher dass es da nichts vorgefertigtes im jdk gibt. Dürfte allerdings nicht so schwer zu implementieren sein: setText(defaultValue), addFocusListener(this), FOCUS_GAINED abfangen, setText("") auf getComponent() ausführen (da am besten vorher prüfen obs eh ein Textfield ist). Dann kannst natürlich auch FocusLost abfangen und prüfen ob die Eingabe leer war...
So hätte ich mir das jetzt gedacht, aber Swing ist ja oft etwas seltsam... -
Jop so hab ich das auch schon gemacht, dachte nur ich könnte meinen Code aufräumen damit. Denn wenn jemand den dazugehörigen Button benutzt muss ich immer überprüfen was für ein Text darin steht. Wenn jetzt der "Hintergrundtext" darin steht soll er das nicht abschicken. Das ist natürlich etwas unsauber, da es ja jemanden geben könnte der diesen Text da verschicken will (unwahrscheinlich ich weiß aber ich hasse unsaubere Lösungen).
Ob ich da was in der PaintComponent-Methode machen kann? -
Überprüfen was im Text steht solltest du sowieso immer, bzw. den Inhalt jedes Eingabefelds validieren.
Natürlich kannst du intern Protokoll darüber führen, ob was eingetragen wurde (z.B. ob das Feld jemals Focus hatte oder so). Das wird sicher kein hübsch anzusehender Code für so ein kleines Feature, aber das ist eben Swing...
Ob du mit paintComponent was machen kannst...naja, da bin ich am Ende meiner Swing-Kenntnisse angelangt - aber eigentlich kann man mit Graphics-Objekten so ziemlich alles anstellen. Das würde ich aber mal als ein ziemliches "advanced Topic" bezeichnen. Ob es dir das Wert ist musst selbst entscheiden.
Überleg ob das Feature nun so wichtig ist dass du es wiklich haben musst. Den User könnte ein vorbefülltes Eingabefeld auch verwirren. Wenn du dort also irgendwelche Hinweise über einen gültigen Input hinterlegen willst, dann führ vlt lieber eine zusätzliche Spalte ein und setz den Text in ein JLabel. -
Du leerst den Inhalt des Textfeldes, wenn es den Fokus bekommt. Wenn es beim Verlieren des Fokus einen Text != Länge 0 drin stehen hat, dann wurde was eingegeben, und du behaltest es bei. Nur wenn das Textfeld leer ist, setzt du wieder deinen Text ein. Du kannst natürlich auch die Schriftfarbe umschalten, um das deutlicher zu zeigen. Wenn du's öfter verwendest macht's sicher sinn eine eigene Subklasse zu machen. Mit dem Überschreiben der paint-Methode würds evtl. auch gehn, aber da wär ich sehr sehr vorsichtig, was is, wenn die Schriftgröße umgestellt wird? Die Komponente nicht mehr so hoch, wie gedacht? Glaub da kannst mehr falsch als richtig machen mit überschreiben ..
-
Aber wenn ich das TextField einfach leere wenn das den Focus bekommt könnte es ja passieren, dass eigentlich schon was eingetragen war und der Benutzer die Eingabe nur unterbrochen hat.
-
Beim Focus-entern checkst du, ob der Text im Textfeld gleich deinem Platzhalter-Text ist, wenn ja, dann weg damit. Beim Focus-leaven checkst du, ob der Text leer (oder ungültig) ist, wenn ja, dann kommt dein Platzhalter-Text rein.
Die Methode zum Text auslesen würd ich auch überschreiben. die sollt dann, wenn der Platzhalter-Text drinsteht, nen Defaultwert zurückliefern. -
Hmm, das hatte ich mir auch überlegt. Aber ich fand es irgendwie unsauber, dass ein beliebiger Text der als Platzhalter definiert wurde nicht mehr gesendet werden darf.
Ich hab mal folgendes gebastelt (wäre für Ideen zur Vereinfachung oder andere Verbesserungsvorschläge sehr dankbar):PHP
Alles anzeigenimport javax.swing.event.DocumentListener; import javax.swing.event.DocumentEvent; import javax.swing.JTextField; import java.awt.Color; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; public class ChatTextField extends JTextField { private boolean textEingegeben = false; private Color foregroundTMP; private DocumentListener myDL; private String platzhalter = "Eingabe"; private Color platzhalterFarbe = Color.GRAY; public ChatTextField() { super(); foregroundTMP = getForeground(); setForeground(platzhalterFarbe); super.setText(platzhalter); addListeners(); } public ChatTextField(String platzhalter, Color platzhalterFarbe) { super(); this.platzhalter = platzhalter; this.platzhalterFarbe = platzhalterFarbe; foregroundTMP = getForeground(); setForeground(platzhalterFarbe); super.setText(platzhalter); addListeners(); } private void addListeners() { myDL = new DocumentListener() { public void changedUpdate(DocumentEvent e) { textEingegeben = true; } public void insertUpdate(DocumentEvent e) { textEingegeben = true; } public void removeUpdate(DocumentEvent e) { if(getText().length()!=0) { textEingegeben = true; } else { textEingegeben = false; } } }; addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { if(textEingegeben==false) { setSuperText(""); } setForeground(foregroundTMP); getDocument().addDocumentListener(myDL); } public void focusLost(FocusEvent e) { getDocument().removeDocumentListener(myDL); if(!textEingegeben) { setForeground(platzhalterFarbe); setSuperText(platzhalter); } } }); } private void setSuperText(String text) { super.setText(text); } public void setPlatzhalter(String platzhalter) { this.platzhalter = platzhalter; if(!textEingegeben && !this.hasFocus()) { super.setText(platzhalter); } } public void setPlatzhalterFarbe(Color platzhalterFarbe) { this.platzhalterFarbe = platzhalterFarbe; if(!textEingegeben && !this.hasFocus()) { setForeground(platzhalterFarbe); } } public void setText(String text) { super.setText(text); if(text.equals("")) { textEingegeben = false; if(!hasFocus()) { super.setText(platzhalter); setForeground(platzhalterFarbe); } } else { textEingegeben = true; setForeground(foregroundTMP); } } public String getText() { if(textEingegeben) { return super.getText(); } else { return ""; } } }
-
Ich hab das hier mal etwas anders gemacht, weil ich es unnötig fand eine Methode nur für den Super-Aufruf zu haben:
PHP
Alles anzeigenimport javax.swing.event.DocumentListener; import javax.swing.event.DocumentEvent; import javax.swing.JTextField; import java.awt.Color; import java.awt.event.FocusListener; import java.awt.event.FocusEvent; public class ChatTextField extends JTextField implements DocumentListener, FocusListener { private boolean textEingegeben = false; private Color hasFocusForeground; private String platzhalter = "Eingabe"; private Color platzhalterFarbe = Color.GRAY; public ChatTextField() { super(); hasFocusForeground = getForeground(); super.setForeground(platzhalterFarbe); super.setText(platzhalter); addFocusListener(this); } public ChatTextField(String platzhalter, Color platzhalterFarbe) { super(); this.platzhalter = platzhalter; this.platzhalterFarbe = platzhalterFarbe; hasFocusForeground = getForeground(); super.setForeground(platzhalterFarbe); super.setText(platzhalter); addFocusListener(this); } public void changedUpdate(DocumentEvent e) { textEingegeben = true; } public void insertUpdate(DocumentEvent e) { textEingegeben = true; } public void removeUpdate(DocumentEvent e) { if(getText().length()!=0) { textEingegeben = true; } else { textEingegeben = false; } } public void focusGained(FocusEvent e) { if(textEingegeben==false) { super.setText(""); } super.setForeground(hasFocusForeground); getDocument().addDocumentListener(this); } public void focusLost(FocusEvent e) { getDocument().removeDocumentListener(this); if(!textEingegeben) { super.setForeground(platzhalterFarbe); super.setText(platzhalter); } } public void setPlatzhalter(String platzhalter) { this.platzhalter = platzhalter; if(!textEingegeben && !this.hasFocus()) { super.setText(platzhalter); } } public void setPlatzhalterFarbe(Color platzhalterFarbe) { this.platzhalterFarbe = platzhalterFarbe; if(!textEingegeben && !this.hasFocus()) { super.setForeground(platzhalterFarbe); } } public void setText(String text) { super.setText(text); if(text.equals("")) { textEingegeben = false; if(!hasFocus()) { super.setText(platzhalter); super.setForeground(platzhalterFarbe); } } else { textEingegeben = true; super.setForeground(hasFocusForeground); } } public void setForeground(Color foreground) { hasFocusForeground = foreground; if(hasFocus()) { super.setForeground(foreground); } } public String getText() { if(textEingegeben) { return super.getText(); } else { return ""; } } }
-
Hat denn hier keiner eine Meinung ;). Kann ja nicht sein, dass das der Weisheit letzter Schluss ist...
-
Hat denn hier keiner eine Meinung ;). Kann ja nicht sein, dass das der Weisheit letzter Schluss ist...
Konnte keine Probleme durch die Vererbung erkennen. Du wiederholst dich halt nur gern im Code, das könntest du etwas reduzieren durch gegenseitigen Aufruf von Methoden/Konstruktoren oder Auslagerung von Code in eigene Methoden. Finde also höchstens stilistische Mängel, aber Code sieht ok aus.
-
Gut, guck ich nochmal. Natürlich ist auch stilistisches Verbessern wichtig.
Hat jemand Verbesserungen für die Attribute und Variablen (bzw. benennung). Gibt es da irgendwelche Worte, die man häufig verwendet (ENG/DEU). -
Gibt es da irgendwelche Worte, die man häufig verwendet (ENG/DEU).
Probier mal foo, bar, spam und eggs. Solche Variablennamen steigern die Lesbarkeit um 1337%.
-
Konnte keine Probleme durch die Vererbung erkennen. Du wiederholst dich halt nur gern im Code, das könntest du etwas reduzieren durch gegenseitigen Aufruf von Methoden/Konstruktoren oder Auslagerung von Code in eigene Methoden. Finde also höchstens stilistische Mängel, aber Code sieht ok aus.
Schadet sicher nicht, wenn du bei der Namenswahl durchgehend englische Namen verwendest (hier z. B. "placeholder"), das fügt sich besser in den bestehenden Java-Code ein. Auch abgesehen davon gibt's nur Kleinigkeiten die man evtl. ändern könnte:
- Die Klasse ist serialisierbar und sollte eine serialVersionUID deklarieren.
- Ein expliziter Aufruf des parameterlosen Superkonstruktors super() ist nicht nötig, da er ohnehin eingefügt wird, wenn nicht vorhanden.
- Vermutlich kann der parameterlose Konstruktor den Konstruktor mit Parametern mit this() aufrufen und wiederholt so Code nicht.
- Zur Überprüfung, ob ein String leer ist, gibt es seit einiger Zeit getText().isEmpty(). Damit kannst du Überprüfungen wie text.equals("") oder text.length() == 0 ersetzen.
- Code wie
lässt sich auch knapper als
formulieren.
Auch "textEingegeben==false" kann man auf "!textEingegeben" umformulieren. Die explizite Verwendung von true und false - Ist es nicht etwas übertrieben, bei Verlust/Erlangung des Fokus jedes Mal den Listener zu entfernen oder hinzuzufügen?
- Evtl. kannst du das setzen und zurücksetzen von Text und Farbe in eine Methode auslagern, du scheinst den Vorgang oft zu wiederholen. Was ist, wenn du auch die Hintergrundfarbe ersetzen möchtest? In diesem Fall müsstest du den Code an mehreren Stellen einfügen. Versuche eine Lösung zu finden, bei der du das nur an einer Stelle machen müsstest.
Insgesamt aber nette Idee schön umgesetzt. -
Hier mal die Überarbeitete Version.
Meintest du das so mit dem Hintergrund?
das mit dem this()-Aufruf ging beim zweien Konstruktor nicht, weil ich da schon Methoden der Superklasse aufrufe. Und da muss dann erst der Super-Konstruktor aufgerufen werden. Dann kann aber nicht mehr der this() aufruf folgen ^^. Also muss ich da etwas mehr tippen.
PHP
Alles anzeigenimport javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.JTextField; import java.awt.Color; import java.awt.event.FocusListener; import java.awt.event.FocusEvent; import java.awt.Font; public class ChatTextField extends JTextField implements DocumentListener, FocusListener { private static final long serialVersionUID = 1l; private boolean textIsEmpty = true; private Color hasFocusForeground; private Color hasFocusBackground; private Font hasFocusFont; private String emptyStringReplacement; private Color emptyStringForeground; private Color emptyStringBackground; private Font emptyStringFont; public ChatTextField() { this("Eingabe", Color.GRAY); } public ChatTextField(String emptyStringReplacement, Color emptyStringForeground) { this.emptyStringReplacement = emptyStringReplacement; this.emptyStringForeground = emptyStringForeground; this.emptyStringBackground = getBackground(); this.emptyStringFont = getFont(); hasFocusForeground = getForeground(); hasFocusBackground = getBackground(); hasFocusFont = getFont(); setFormat(); addFocusListener(this); } public ChatTextField(String emptyStringReplacement, Color emptyStringForeground, Color emptyStringBackground, Font emptyStringFont) { this.emptyStringReplacement = emptyStringReplacement; this.emptyStringForeground = emptyStringForeground; this.emptyStringBackground = emptyStringBackground; this.emptyStringFont = emptyStringFont; hasFocusForeground = getForeground(); hasFocusBackground = getBackground(); hasFocusFont = getFont(); setFormat(); addFocusListener(this); } private void setFormat() { if(!hasFocus()) { if(textIsEmpty) { super.setText(emptyStringReplacement); super.setForeground(emptyStringForeground); super.setBackground(emptyStringBackground); super.setFont(emptyStringFont); } else { super.setForeground(hasFocusForeground); super.setBackground(hasFocusBackground); super.setFont(hasFocusFont); } } else { if(textIsEmpty) { super.setForeground(hasFocusForeground); super.setBackground(hasFocusBackground); super.setFont(hasFocusFont); super.setText(""); } } } public void changedUpdate(DocumentEvent e) { textIsEmpty = false; } public void insertUpdate(DocumentEvent e) { textIsEmpty = false; } public void removeUpdate(DocumentEvent e) { textIsEmpty = super.getText().isEmpty() ? true : false; } public void focusGained(FocusEvent e) { setFormat(); getDocument().addDocumentListener(this); } public void focusLost(FocusEvent e) { getDocument().removeDocumentListener(this); setFormat(); } public void setEmptyStringReplacement(String emptyStringReplacement) { this.emptyStringReplacement = emptyStringReplacement; setFormat(); } public void setEmptyStringForeground(Color emptyStringForeground) { this.emptyStringForeground = emptyStringForeground; setFormat(); } public void setEmptyStringBackground(Color emptyStringBackground) { this.emptyStringBackground = emptyStringBackground; setFormat(); } public void setEmtpyStringFont(Font emptyStringFont) { this.emptyStringFont = emptyStringFont; setFormat(); } public void setForeground(Color foreground) { hasFocusForeground = foreground; setFormat(); } public void setBackground(Color background) { hasFocusBackground = background; setFormat(); } public void setFont(Font font) { hasFocusFont = font; setFormat(); } public void setText(String text) { if(text.isEmpty()) { textIsEmpty = true; setFormat(); } else { super.setText(text); textIsEmpty = false; setFormat(); } } public String getText() { return !textIsEmpty ? super.getText() : ""; } }
-
Ich bezweifle, dass das so funktionieren wird. Der 2. Konstruktor weist sich seine eigenen Objektvariablen zu.
-
Oh der funktioniert ganz ausgezeichnet kann ich dir sagen ^^.
-
Oh der funktioniert ganz ausgezeichnet kann ich dir sagen ^^.
Aja, falsch gschaut xD
-
Eigentlich war ich ja ganz zufrieden mit meiner Klasse
ABER irgendwie ist das nicht ganz so geschickt gelöst, wenn die ganzen UI Werte in der Klasse sind. Wenn jetzt jemand die Klasse verwenden wollen würde aber sein GUI nur eigene UIs verwendet, dann ist das ja ziemlich unsauber, wenn er jetzt trotzdem bei jedem erstellten ChatTextField die Farbwerte angeben muss. Also muss ja wohl irgendwie eine UI Klasse her. Das Problem ist: Ich habe keine Ahnung wie ich das realisieren kann. Ob mir da jemand helfen möchte? Ich hab auch den SourceCode vom JTextField und JTextFieldUI aber irgendwie blick ich nicht ganz durch, weil da anscheinend so viel vererbt wurde, dass die Klassen halb leer sind und ich keine Methoden finde, die irgendwas mit Hintergrundfarbe oder so zu tun haben. -
Eine Komponente von Grund auf zu entwickeln wäre ein aufwändiges Projekt, bei dem du sehr viel falsch machen könntest. Unter anderem müsstest du verschiedene Look & Feels unterstützten. Ich hab's zwar noch nicht gemacht, aber wenn man sich näher ansieht, was eine Komponente alles können muss, dann wäre die Entwicklung einer sich korrekt verhaltenden eigenen Komponente für deinen Anspruch völlig übertrieben - vor allem, wenn du eh nur ein JTextField leicht modifizieren möchtest, was sich mit dem Überschreiben der Methoden bereits wunderbar erledigen lässt.
-
Jetzt mitmachen!
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!