ADDITIONAL SYSTEM INFORMATION :
Should occur on all systems and with all recent OpenJFX versions.
Tested with:
Win10
openjdk 17.0.1
Linux asl754 5.14.0-362.13.1.el9_3.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Dec 13 14:07:45 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
openjdk 17.0.9 2023-10-17 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.9.0.9-1) (build 17.0.9+9-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.9.0.9-1) (build 17.0.9+9-LTS, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
When binding the promptTextProperty of a TextInputControl (TextField or TextArea) to a text that contains linebreaks/newlines ("\n"), the "bind" call causes a RuntimeException to be thrown.
This is due to special handling in "TextInputControl.promptText.invalidated" that strips out newlines.
https://github.com/openjdk/jfx/blob/ca04c87d307c36591162af8cd6298ede17812834/modules/javafx.controls/src/main/java/javafx/scene/control/TextInputControl.java#L323
java.lang.RuntimeException: TextArea.promptText : A bound value cannot be set.
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:141) // throws when observable is set
at javafx.scene.control.TextInputControl$3.invalidated(TextInputControl.java:286) // strips out newlines, calls .set
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.bind(StringPropertyBase.java:172) // stores the observable
The exceptions is only triggered when binding the prompt text (setting is fine), and when the text contains newlines (text without newlines can be bound without any problem).
(Sidenote: I question whether stripping out the newlines makes sense for the multi-line TextArea, but I will create a separate issue for this.)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Bind the promptTextProperty of a TextInputControl (TextField or TextArea) to a text that contains linebreaks/newlines ("\n").
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The prompt text is bound to the specified text (possibly with stripped newlines).
ACTUAL -
RuntimeException, e.g.
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: TextField.promptText : A bound value cannot be set.
---------- BEGIN SOURCE ----------
package bugdemos;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputControl;
import javafx.stage.Stage;
public class BoundPromptWithLineBreaksBugSimpleDemoApp extends Application {
private static final String PROMPT_NO_LINEBREAKS = "Prompt w/o linebreaks";
private static final String PROMPT_WITH_LINEBREAKS = "Prompt" + "\n" + "with" + "\n" + "linebreaks";
public static void main(final String[] args) {
launch(args);
}
@Override
public void start(final Stage stage) throws Exception {
final TextField textField = new TextField();
final TextArea textArea = new TextArea();
final StringProperty promptProperty = new SimpleStringProperty();
System.out.println("\n---Setting a prompt without linebreaks: OK for both textfield and textarea");
setPromptAndReadBack(textField, PROMPT_NO_LINEBREAKS);
setPromptAndReadBack(textArea, PROMPT_NO_LINEBREAKS);
System.out.println(
"\n---Setting a prompt with linebreaks: OK for both textfield and textarea, linebreaks are stripped");
setPromptAndReadBack(textField, PROMPT_WITH_LINEBREAKS);
setPromptAndReadBack(textArea, PROMPT_WITH_LINEBREAKS);
System.out.println("\n---Binding a prompt without linebreaks: OK for both textfield and textarea");
bindPromptAndReadBack(textField, promptProperty, PROMPT_NO_LINEBREAKS);
bindPromptAndReadBack(textArea, promptProperty, PROMPT_NO_LINEBREAKS);
System.out.println(
"\n---Binding a prompt with linebreaks: BROKEN for both textfield and textarea, causes exceptions");
bindPromptAndReadBack(textField, promptProperty, PROMPT_WITH_LINEBREAKS);
bindPromptAndReadBack(textArea, promptProperty, PROMPT_WITH_LINEBREAKS);
System.exit(0);
}
private static void setPromptAndReadBack(final TextInputControl textInput, final String prompt) {
textInput.setPromptText(prompt);
System.out.println(
textInput.getClass().getSimpleName() //
+ " SET: \"" + prompt + "\" READ BACK: \"" + textInput.getPromptText() + "\"");
}
private static void bindPromptAndReadBack(
final TextInputControl textInput,
final StringProperty promptProperty,
final String prompt) {
textInput.promptTextProperty().unbind();
promptProperty.setValue(prompt);
try {
textInput.promptTextProperty().bind(promptProperty);
System.out.println(textInput.getClass().getSimpleName() + //
" BOUND TO: \"" + prompt + "\" READ BACK: \"" + textInput.getPromptText() + "\"");
} catch (final RuntimeException ex) {
// Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: TextField.promptText : A bound value cannot be set.
// Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: TextArea.promptText : A bound value cannot be set.
System.err.println(
textInput.getClass().getSimpleName() //
+ " Failed to bind prompt \"" + prompt + "\"");
ex.printStackTrace();
} finally {
// undo binding for next test
textInput.promptTextProperty().unbind();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None that allows newlines in bound prompt texts.
Option A: Remove newlines
Option B: Do not use prompt text, use normal text property instead
FREQUENCY : always
Should occur on all systems and with all recent OpenJFX versions.
Tested with:
Win10
openjdk 17.0.1
Linux asl754 5.14.0-362.13.1.el9_3.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Dec 13 14:07:45 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
openjdk 17.0.9 2023-10-17 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.9.0.9-1) (build 17.0.9+9-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.9.0.9-1) (build 17.0.9+9-LTS, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
When binding the promptTextProperty of a TextInputControl (TextField or TextArea) to a text that contains linebreaks/newlines ("\n"), the "bind" call causes a RuntimeException to be thrown.
This is due to special handling in "TextInputControl.promptText.invalidated" that strips out newlines.
https://github.com/openjdk/jfx/blob/ca04c87d307c36591162af8cd6298ede17812834/modules/javafx.controls/src/main/java/javafx/scene/control/TextInputControl.java#L323
java.lang.RuntimeException: TextArea.promptText : A bound value cannot be set.
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:141) // throws when observable is set
at javafx.scene.control.TextInputControl$3.invalidated(TextInputControl.java:286) // strips out newlines, calls .set
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.bind(StringPropertyBase.java:172) // stores the observable
The exceptions is only triggered when binding the prompt text (setting is fine), and when the text contains newlines (text without newlines can be bound without any problem).
(Sidenote: I question whether stripping out the newlines makes sense for the multi-line TextArea, but I will create a separate issue for this.)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Bind the promptTextProperty of a TextInputControl (TextField or TextArea) to a text that contains linebreaks/newlines ("\n").
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The prompt text is bound to the specified text (possibly with stripped newlines).
ACTUAL -
RuntimeException, e.g.
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: TextField.promptText : A bound value cannot be set.
---------- BEGIN SOURCE ----------
package bugdemos;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputControl;
import javafx.stage.Stage;
public class BoundPromptWithLineBreaksBugSimpleDemoApp extends Application {
private static final String PROMPT_NO_LINEBREAKS = "Prompt w/o linebreaks";
private static final String PROMPT_WITH_LINEBREAKS = "Prompt" + "\n" + "with" + "\n" + "linebreaks";
public static void main(final String[] args) {
launch(args);
}
@Override
public void start(final Stage stage) throws Exception {
final TextField textField = new TextField();
final TextArea textArea = new TextArea();
final StringProperty promptProperty = new SimpleStringProperty();
System.out.println("\n---Setting a prompt without linebreaks: OK for both textfield and textarea");
setPromptAndReadBack(textField, PROMPT_NO_LINEBREAKS);
setPromptAndReadBack(textArea, PROMPT_NO_LINEBREAKS);
System.out.println(
"\n---Setting a prompt with linebreaks: OK for both textfield and textarea, linebreaks are stripped");
setPromptAndReadBack(textField, PROMPT_WITH_LINEBREAKS);
setPromptAndReadBack(textArea, PROMPT_WITH_LINEBREAKS);
System.out.println("\n---Binding a prompt without linebreaks: OK for both textfield and textarea");
bindPromptAndReadBack(textField, promptProperty, PROMPT_NO_LINEBREAKS);
bindPromptAndReadBack(textArea, promptProperty, PROMPT_NO_LINEBREAKS);
System.out.println(
"\n---Binding a prompt with linebreaks: BROKEN for both textfield and textarea, causes exceptions");
bindPromptAndReadBack(textField, promptProperty, PROMPT_WITH_LINEBREAKS);
bindPromptAndReadBack(textArea, promptProperty, PROMPT_WITH_LINEBREAKS);
System.exit(0);
}
private static void setPromptAndReadBack(final TextInputControl textInput, final String prompt) {
textInput.setPromptText(prompt);
System.out.println(
textInput.getClass().getSimpleName() //
+ " SET: \"" + prompt + "\" READ BACK: \"" + textInput.getPromptText() + "\"");
}
private static void bindPromptAndReadBack(
final TextInputControl textInput,
final StringProperty promptProperty,
final String prompt) {
textInput.promptTextProperty().unbind();
promptProperty.setValue(prompt);
try {
textInput.promptTextProperty().bind(promptProperty);
System.out.println(textInput.getClass().getSimpleName() + //
" BOUND TO: \"" + prompt + "\" READ BACK: \"" + textInput.getPromptText() + "\"");
} catch (final RuntimeException ex) {
// Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: TextField.promptText : A bound value cannot be set.
// Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: TextArea.promptText : A bound value cannot be set.
System.err.println(
textInput.getClass().getSimpleName() //
+ " Failed to bind prompt \"" + prompt + "\"");
ex.printStackTrace();
} finally {
// undo binding for next test
textInput.promptTextProperty().unbind();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None that allows newlines in bound prompt texts.
Option A: Remove newlines
Option B: Do not use prompt text, use normal text property instead
FREQUENCY : always
- relates to
-
JDK-8335547 Support multi-line prompt text for TextArea
- Open