Issue
I'm trying to set the width of a JavaFX Dialog to fit my Text.
I know how to do it, but there is a "Fudge Factor" of 32 that I would like to understand.
Can anyone explain how I can determine the value empirically?
I'm using the Zulu OpenJDK 17 with bundled JavaFX under Windows 10.
Here's some example code:
import static javafx.scene.control.Alert.AlertType.INFORMATION;
import javafx.application.Application;
import javafx.scene.control.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class AlertWide extends Application {
private static final String INFO_TEXT = """
A couple of lines...
1) Line 1 is quite short
2) Line 2 is too wide to fit in the standard Alert Label, so it needs to be widened manually, that is to say, once a year
3) the last line
""";
public static void main(final String[] args) {
launch(args);
}
@Override
public void start(final Stage primaryStage) throws Exception {
final var infoWidth = new Text(INFO_TEXT).getBoundsInLocal().getWidth();
final var alert = new Alert(INFORMATION);
; alert.setContentText(INFO_TEXT);
; alert.showAndWait();
setLabelWidth(alert, infoWidth ); alert.showAndWait();
setLabelWidth(alert, infoWidth + 32); alert.showAndWait(); // TODO why 32?
}
private void setLabelWidth(final Alert alert, final double preferredLabelWidth) {
alert.getDialogPane().getChildren().forEach(node -> {
if (node instanceof Label nodeLabel) {
nodeLabel.setPrefWidth(preferredLabelWidth);
}
});
}
}
Solution
Having delved into the depths of Dialog
, I found a very simple solution.
Rather than iterating through the DialogPane
's children, I simply replaced the Label
with a new Instance.
P.S. "replaced" is not strictly speaking correct: the built-in DialogPane Label is set to unmanaged & invisible & so takes no part in the rendering.
The following was just fine for my purposes:
import static javafx.scene.control.Alert.AlertType.INFORMATION;
import javafx.application.Application;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class AlertWideSetContent extends Application {
private static final String INFO_TEXT = """
A couple of lines...
1) Line 1 is quite short
2) Line 2 is too wide to fit in the standard Alert Label, so it needs to be widened manually, that is to say, once a year
3) the last line
""";
public static void main(final String[] args) {
launch(args);
}
@Override
public void start(final Stage primaryStage) throws Exception {
final var alert = new Alert(INFORMATION);
; alert.getDialogPane().setContent(new Label(INFO_TEXT));
; alert.showAndWait();
}
}
But, as @kleopatra observed, setting the Preferred Width to -1 (USE_COMPUTED_SIZE
) does it too:
import static javafx.scene.control.Alert.AlertType.INFORMATION;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class AlertWideUseComputedSize extends Application {
private static final String INFO_TEXT = """
A couple of lines...
1) Line 1 is quite short
2) Line 2 is too wide to fit in the standard Alert Label, so it needs to be widened manually, that is to say, once a year
3) the last line
""";
public static void main(final String[] args) {
launch(args);
}
@Override
public void start(final Stage primaryStage) throws Exception {
final var alert = new Alert (INFORMATION);
; alert.setContentText(INFO_TEXT );
for (final Node node : alert.getDialogPane().getChildren()) {
if (node instanceof Label nodeLabel) {
nodeLabel.setPrefWidth(Label.USE_COMPUTED_SIZE);
}
}
alert.showAndWait();
}
}
Answered By - Dave The Dane
Answer Checked By - Clifford M. (JavaFixing Volunteer)