JavaFX Dialogs (Official) - Code - Makery.ch

Download as pdf or txt
Download as pdf or txt
You are on page 1of 20

Su

bs
cr
ib
e
to

code.makery (/)

Up
da
te
s
Learning how to code.

Home (/)

Library (/library/)

Paths (/paths/)

Blog (/blog/)

About (/about/)

JavaFX Dialogs (of cial)


Oct 28, 2014 • Java (/blog/tag/java/), JavaFX (/blog/tag/javafx/)

JavaFX 8u40 finally includes simple Dialogs and Alerts! I’ve been waiting for this since 2012!
In the meantime I wrote about how to use Dialogs in JavaFX 2 (/blog/javafx-2-dialogs/) and
later in JavaFX 8 with ControlsFX (/blog/javafx-8-dialogs/).

Now that they are available in the official JDK, let’s learn how to use them.

Prerequisites
To use the official JavaFX Dialogs you need JDK 8u40 or later.

→ Download JDK 8u40


(http://www.oracle.com/technetwork/java/javase/downloads/index.html) or newer.

Standard Dialogs
Information Dialog
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Information Dialog");
alert.setHeaderText("Look, an Information Dialog");
alert.setContentText("I have a great message for you!");

alert.showAndWait();

Without Header Text

Alert alert = new Alert(AlertType.INFORMATION);


alert.setTitle("Information Dialog");
alert.setHeaderText(null);
alert.setContentText("I have a great message for you!");

alert.showAndWait();

Warning Dialog
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Warning Dialog");
alert.setHeaderText("Look, a Warning Dialog");
alert.setContentText("Careful with the next step!");

alert.showAndWait();

Error Dialog

Alert alert = new Alert(AlertType.ERROR);


alert.setTitle("Error Dialog");
alert.setHeaderText("Look, an Error Dialog");
alert.setContentText("Ooops, there was an error!");

alert.showAndWait();

Exception Dialog
There is not a complete Exception Dialog out of the box. But we can easily provide TextArea
as expandable content.
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Exception Dialog");
alert.setHeaderText("Look, an Exception Dialog");
alert.setContentText("Could not find file blabla.txt!");

Exception ex = new FileNotFoundException("Could not find file blabla.txt");

// Create expandable Exception.


StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
String exceptionText = sw.toString();

Label label = new Label("The exception stacktrace was:");

TextArea textArea = new TextArea(exceptionText);


textArea.setEditable(false);
textArea.setWrapText(true);

textArea.setMaxWidth(Double.MAX_VALUE);
textArea.setMaxHeight(Double.MAX_VALUE);
GridPane.setVgrow(textArea, Priority.ALWAYS);
GridPane.setHgrow(textArea, Priority.ALWAYS);

GridPane expContent = new GridPane();


expContent.setMaxWidth(Double.MAX_VALUE);
expContent.add(label, 0, 0);
expContent.add(textArea, 0, 1);

// Set expandable Exception into the dialog pane.


alert.getDialogPane().setExpandableContent(expContent);

alert.showAndWait();

Con rmation Dialog


Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Look, a Confirmation Dialog");
alert.setContentText("Are you ok with this?");

Optional<ButtonType> result = alert.showAndWait();


if (result.get() == ButtonType.OK){
// ... user chose OK
} else {
// ... user chose CANCEL or closed the dialog
}

Con rmation Dialog with Custom Actions


Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog with Custom Actions");
alert.setHeaderText("Look, a Confirmation Dialog with Custom Actions");
alert.setContentText("Choose your option.");

ButtonType buttonTypeOne = new ButtonType("One");


ButtonType buttonTypeTwo = new ButtonType("Two");
ButtonType buttonTypeThree = new ButtonType("Three");
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);

alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree, buttonTypeCancel

Optional<ButtonType> result = alert.showAndWait();


if (result.get() == buttonTypeOne){
// ... user chose "One"
} else if (result.get() == buttonTypeTwo) {
// ... user chose "Two"
} else if (result.get() == buttonTypeThree) {
// ... user chose "Three"
} else {
// ... user chose CANCEL or closed the dialog
}

Text Input Dialog


TextInputDialog dialog = new TextInputDialog("walter");
dialog.setTitle("Text Input Dialog");
dialog.setHeaderText("Look, a Text Input Dialog");
dialog.setContentText("Please enter your name:");

// Traditional way to get the response value.


Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
System.out.println("Your name: " + result.get());
}

// The Java 8 way to get the response value (with lambda expression).
result.ifPresent(name -> System.out.println("Your name: " + name));

Note: The result.isPresent() will return false if the user cancelled the dialog.

Choice Dialog

List<String> choices = new ArrayList<>();


choices.add("a");
choices.add("b");
choices.add("c");

ChoiceDialog<String> dialog = new ChoiceDialog<>("b", choices);


dialog.setTitle("Choice Dialog");
dialog.setHeaderText("Look, a Choice Dialog");
dialog.setContentText("Choose your letter:");

// Traditional way to get the response value.


Optional<String> result = dialog.showAndWait();
if (result.isPresent()){
System.out.println("Your choice: " + result.get());
}

// The Java 8 way to get the response value (with lambda expression).
result.ifPresent(letter -> System.out.println("Your choice: " + letter));
Note: The result.isPresent() will return false if the user didn’t choose anything or
cancelled the dialog.

Custom Login Dialog


Here is an example of how to create a custom dialog with a login form:
// Create the custom dialog.
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle("Login Dialog");
dialog.setHeaderText("Look, a Custom Login Dialog");

// Set the icon (must be included in the project).


dialog.setGraphic(new ImageView(this.getClass().getResource("login.png").toString()));

// Set the button types.


ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);

// Create the username and password labels and fields.


GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));

TextField username = new TextField();


username.setPromptText("Username");
PasswordField password = new PasswordField();
password.setPromptText("Password");

grid.add(new Label("Username:"), 0, 0);


grid.add(username, 1, 0);
grid.add(new Label("Password:"), 0, 1);
grid.add(password, 1, 1);

// Enable/Disable login button depending on whether a username was entered.


Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
loginButton.setDisable(true);

// Do some validation (using the Java 8 lambda syntax).


username.textProperty().addListener((observable, oldValue, newValue) -> {
loginButton.setDisable(newValue.trim().isEmpty());
});

dialog.getDialogPane().setContent(grid);

// Request focus on the username field by default.


Platform.runLater(() -> username.requestFocus());

// Convert the result to a username-password-pair when the login button is clicked.


dialog.setResultConverter(dialogButton -> {
if (dialogButton == loginButtonType) {
return new Pair<>(username.getText(), password.getText());
}
return null;
});

Optional<Pair<String, String>> result = dialog.showAndWait();

result.ifPresent(usernamePassword -> {
System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassw
});

Styling the Dialogs


Custom Icon

In the current version it’s a bit cumbersome to get to the Dialog’s Stage to be able to set its
icon. Here is how:

// Get the Stage.


Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();

// Add a custom icon.


stage.getIcons().add(new Image(this.getClass().getResource("login.png").toString()));

According to this bug report (https://javafx-jira.kenai.com/browse/RT-38895) the final


version of the JavaFX 8u40 Dialogs should use the same icon as the application that it is
running from. In that case you would need to set its owner and the Dialog would get the
owner’s icon:

dialog.initOwner(otherStage);

Minimal Decorations
Another option is to remove the icon and use only minimal window decorations.

dialog.initStyle(StageStyle.UTILITY);
Other Options
Setting the Owner
You can specify the owner Window for a dialog. If no owner or null is specified for the owner,
it is a top-level, unowned dialog.

dialog.initOwner(parentWindow);

Setting the Modality


You can specify the modality for a dialog. The modality must be one of Modality.NONE ,
Modality.WINDOW_MODAL , or Modality.APPLICATION_MODAL .

dialog.initModality(Modality.NONE);

API Documentation
For more information on the Dialogs have a look at the JavaFX API docs:

Alert (http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Alert.html)
Dialog (http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Dialog.html)
TextInputDialog
(http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TextInputDialog.html)
ChoiceDialog
(http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ChoiceDialog.html)
DialogPane
(http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/DialogPane.html)

Comments
221 Comments code.makery 
1 Login

 Recommend 45 t Tweet f Share Sort by Oldest

Join the discussion…

LOG IN WITH
OR SIGN UP WITH DISQUS ?

Name
Perla Z 5 years ago
This is awesome! Thank you!
8△ ▽ • Reply • Share ›

Marco Jakob Mod > Perla Z • 5 years ago


Wow, you are fast with writing comments... I've just published the article.
5△ ▽ • Reply • Share ›

Perla Z > Marco Jakob • 5 years ago


I was so waiting for it
△ ▽ • Reply • Share ›

Marco Jakob Mod > Perla Z • 5 years ago

Waiting for the blog post or waiting for Oracle to finally put the dialogs in the
official JDK? :-)
△ ▽ • Reply • Share ›

Perla Z > Marco Jakob • 5 years ago


both! :D
51 △ ▽ • Reply • Share ›

Avatar This comment was deleted.

Sajib Srs > Guest • 4 years ago


Smooth. Who said coders are not romantic ;)
2△ ▽ • Reply • Share ›

Marco Jakob Mod > Sajib Srs • 4 years ago


:-)
1△ ▽ • Reply • Share ›

Aurélien • 5 years ago


Thanks for your work. Its a great post, it will help me a lot.
1△ ▽ • Reply • Share ›

Michael Ramirez • 5 years ago


If I were to create a "Save" dialog. How would I prevent the "Save" button from closing the dialog
until the save operation was completed.
△ ▽ • Reply • Share ›

Marco Jakob Mod > Michael Ramirez • 5 years ago • edited


I think they are meant for simple dialogs with only limited interaction. It might be possible
to not return immediately when the "Save" button is clicked but maybe there are better
ways:

* Why does the dialog need to stay open? If it's a long running operation you could close the
dialog and then show some progress bar.
* If you need more functionality then you might be better off by just implementing your own
Stage.
* If you still want to use the dialogs, you might need to extend the Dialog class. Have a look
at the Dialogs source here: https://bitbucket.org/contr...
1△ ▽ • Reply • Share ›

Marco Jakob Mod > Michael Ramirez • 5 years ago • edited


Actually, I found a bug report for this that also contains a workaround:
https://javafx-jira.kenai.c...

Here is the workaround from the issue tracker:

Now I found the following workaround by performing a lookup of the OK button and using
an action filter which consumes the button action event in case of validation errors:

final DialogPane dlgPane = dlg.getDialogPane();


dlgPane.getButtonTypes().add(ButtonType.OK);
dlgPane.getButtonTypes().add(ButtonType.CANCEL);

final Button btOk = (Button) dlg.getDialogPane().lookupButton(ButtonType.OK);


btOk.addEventFilter(ActionEvent.ACTION, (event) -> {
if (!validateAndStore()) {
event.consume();
}
});

dlg.showAndWait();

△ ▽ • Reply • Share ›

Nick • 5 years ago


Is there a way to be able to change the icon of the window?
like for the Stage class : getIcons().add(Image)
1△ ▽ • Reply • Share ›

Marco Jakob Mod > Nick • 5 years ago • edited


I've found a way to change the icon:

Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();


stage.getIcons().add(new Image(this.getClass().getResource("login.png").toString()));

You could also remove the icon with:

dialog.initStyle(StageStyle.UTILITY);

*****

In the final version the dialog should have the same icon as its owner. You can set the owner
window like this.

dialog.initOwner(otherStage);

I don't know if this already works now, because there was a bug report that was fixed about a
day ago. See https://javafx-jira.kenai.c...
△ ▽ • Reply • Share ›
Marco Jakob Mod > Marco Jakob • 5 years ago
I've added the styling and icon examples to the blog post above.
△ ▽ • Reply • Share ›

Nick > Marco Jakob • 5 years ago


Thank you very much! :)
△ ▽ • Reply • Share ›

Claudio Mezzasalma > Marco Jakob • 5 years ago


It seems that initModality is not working for me... I don't have a snippet right
now but simply the window below keeps receiving events regardless of the
value set... Any clue?
△ ▽ • Reply • Share ›

Marco Jakob Mod > Claudio Mezzasalma • 5 years ago


If you think it might be a bug, please report it to: https://javafx-
jira.kenai.com/
1△ ▽ • Reply • Share ›

Claudio Mezzasalma > Marco Jakob • 5 years ago


Honestly it's a quite border line scenario since I'm opening my dialog from a
drag and drop event fired inside a pane which is inside a JFXPanel and used
in NetBeans Platform... I'll do some research and try to replicate it with a
straight JavaFX App.
△ ▽ • Reply • Share ›

ilxan • 5 years ago


I'm trying to change the width and height of a TextInputDialog by using the setHeight() /
setWidth() methods. Unfortunately its not working. Here is a snippet, what am i doing wrong?

TextInputDialog dialog = new TextInputDialog();

dialog.initOwner(stage);
dialog.setHeight(300.0);
dialog.setWidth(600.0);
dialog.setTitle("Adding new selector");
dialog.setHeaderText("test");
dialog.setContentText("text:");

Optional<string> result = dialog.showAndWait();


△ ▽ • Reply • Share ›

Marco Jakob Mod > ilxan • 5 years ago

I don't know if it works, but you could try:

dialog.getDialogPane().setHeight(...);
dialog.getDialogPane().setWidth(...);
△ ▽ • Reply • Share ›
ilxan > Marco Jakob • 5 years ago
Thanks Marco,

i got it to work by setting the style:

dialog.getDialogPane().setStyle(" -fx-max-width:600px; -fx-max-height: 300px; -fx-


pref-width: 600px; -fx-pref-height: 300px;");
△ ▽ • Reply • Share ›

Hoi Sidwell • 5 years ago


Hi, excellent article. I have it bookmarked.

There is probably no way of getting rid of that last pesky x icon on the minimal decorations, I
suppose, shy of an UNDECORATED stage altogether? css or some other hack perhaps?

Also, I am not seeing a way to position the dialog. Any tips?


△ ▽ • Reply • Share ›

Marco Jakob Mod > Hoi Sidwell • 5 years ago


There is actually an undecorated way: dialog.initStyle(StageStyle.UNDECORATED);
Also see here: http://stackoverflow.com/qu... and here: http://pixelduke.wordpress....

About positioning: I think the dialogs should automatically be centered relative the their
owner but I might be wrong. Try setting the owner and then using dialog.setX(...) and
dialog.setY(...);
△ ▽ • Reply • Share ›

driv3l • 5 years ago


What's the best way to handle localization with these new dialogs? The problem I am having is with
replacing the localized text in the default dialog buttons. I basically just want to replace the text (or
even the buttons) with my own localized versions. It seems the dialogs won't work if you remove the
default buttons and add your own e.g. TextInputDialog. I already have a keyed bundle that I am
using and just want to pass my "ok" and "cancel" to the buttons.
△ ▽ • Reply • Share ›

Marco Jakob Mod > driv3l • 5 years ago


Using your own buttons should work. Just make sure you use the ok_done and cancel_close
ButtonData:

ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);


ButtonType buttonTypeOk = new ButtonType("OK", ButtonData.OK_DONE);

dialog.getButtonTypes().setAll(buttonTypeCancel, buttonTypeOk);

△ ▽ • Reply • Share ›

driv3l > Marco Jakob • 5 years ago


Hi Marco,

Thanks for the prompt response. Unfortunately it doesn't work with a


TextInputDialog.
I believe it may be a bug. If you look at the source code for TextInputDialog:

https://bitbucket.org/contr...

Instead of looking at the ButtonData to see if it's OK_DONE, it's actually checking to
see if the button pressed is it's own reference for OK.
△ ▽ • Reply • Share ›

Marco Jakob Mod > driv3l • 5 years ago

I don't know what their idea is about how this should be done properly. But
you could probably set your own result converter:

dialog.setResultConverter((dialogButton) -> dialogButton == yourOkButton ? d

△ ▽ • Reply • Share ›

driv3l > Marco Jakob • 5 years ago


Thanks Marco.. that fixes it.

I hope they decide to change it so that it actually looks at the ButtonData and
not the reference. IMO, that would be the right way to handle it.
△ ▽ • Reply • Share ›

Marco Jakob Mod > driv3l • 5 years ago


I've left a comment on the page of the dialog designers and hope they will see
this discussion and maybe join in:

http://fxexperience.com/201...
△ ▽ • Reply • Share ›

Jonathan Giles > driv3l • 5 years ago


I filed RT-39330 and fixed the issue here: https://javafx-jira.kenai.c...

Please, in the future file bugs in the JavaFX jira issue tracker. Thanks!
23 △ ▽ • Reply • Share ›

JC • 5 years ago
Is there a way of setting the parent stage? Like the old versions?
△ ▽ • Reply • Share ›

William Vincent > JC • 5 years ago


Dialog.initOwner(Window wdw)
△ ▽ • Reply • Share ›

Marco Jakob Mod > William Vincent • 5 years ago


I've added some information about setting the owner and the modality to the blog
post.
△ ▽ • Reply • Share ›

michaelpellis • 5 years ago


When will there be SceneBuilder support for Dialogs? Or is there already a way to use Dialogs with
SceneBuilder?
△ ▽ • Reply • Share ›

Marco Jakob Mod > michaelpellis • 5 years ago


It should be coming to SceneBuilder. But I don't know when exactly. See here:
http://openjdk.java.net/jep...
△ ▽ • Reply • Share ›

michaelpellis > Marco Jakob • 5 years ago


@Marco Jakob. That was a quick reply. Many thanks. I'm just starting with JavaFX
and am loving it so far. At first i thought my application would not benefit too much
from SceneBuilder particularly where the UI is highly dynamic, but I have found an
excellent use for it where I can let system administrators of our application use
SceneBuilder directly to design there own forms and then store/restore the state of
these forms by trawling the Node tree for input items and saving/loading the content
as Java Properties. Saves me having to roll my own form designer!

I have another query which I think is a bug (or my lack of understanding with
SceneBuilder - I am unable to configure a ChoiceBox with its items in SceneBuilder -
completely off topic but where should I address that query to?

Many thanks

-- Michael Ellis
1△ ▽ • Reply • Share ›

Marco Jakob Mod > michaelpellis • 5 years ago


Hi Michael,

I also think SceneBuilder is very helpful and probably the best visual editor
I've seen in my Java career. It's great that your system administrators can use
it in such a way.

If you've found a bug in scene builder it's best if you report it here:
https://javafx-jira.kenai.com/
△ ▽ • Reply • Share ›

michaelpellis > Marco Jakob • 5 years ago


It looks like the limitation is known about. I added my tuppence worth here:
http://goo.gl/vV3LgX I'm confused though as the implication from the
comments that precede mine is that setting the contents for ChoiceBox and
ComboBox are not considered necessary!!!!
△ ▽ • Reply • Share ›

Gazda Miloš • 5 years ago • edited


Hello, good job with the article!

Is there a way how Alert could consume a KeyEvent? I have a simple login AnchorPane
(username/password/login button) which method onKey(KeyEvent event) is assigned to handle
released key to process the login.
private void initialize() {
anchorPane.setOnKeyReleased((event) -> onKey(event))
}

and

public void onKey(KeyEvent keyEvent) {


if (keyEvent.getCode() == KeyCode.ENTER) {
login();
}
}

If the username or pass is wrong an error Alert with a message is shown.


see more

△ ▽ • Reply • Share ›

Marco Jakob Mod > Gazda Miloš • 5 years ago


Sorry, I don't know right away what you could do. But maybe it helps when you look at the
source code of Alert to see what happens when you hit enter: https://bitbucket.org/contr...
△ ▽ • Reply • Share ›

peter hams • 5 years ago


is there a bug with the alert dialog? as when i set UNDECORATED and add a css border around it i
get a 10px white banner on the RHS of the dialog?
△ ▽ • Reply • Share ›

peter > peter hams • 5 years ago


http://tinypic.com/r/24gnmtd/8
△ ▽ • Reply • Share ›

Marco Jakob Mod > peter • 5 years ago


Seems strange. You can report this in the JavaFX Bug tracker: https://javafx-
jira.kenai.com
△ ▽ • Reply • Share ›

Igor Buzatovic • 5 years ago


Am I missing something or there are no internal (lightweight) dialogs in this version ?
I am using 8u25 JDK and openjfx-dialogs-1.0.2
Thanks
△ ▽ • Reply • Share ›

Marco Jakob Mod > Igor Buzatovic • 5 years ago


No, last time I checked there were no openjfx lightweight dialogs. I don't know if they plan
to include it in 8u40. If not, the only way would be to go back to the controls-fx dialogs or
copy parts of the code and css from the controls-fx lightweight dialogs over.
△ ▽ • Reply • Share ›

Hemant Sonawane • 5 years ago


I am trying to validate & then allowing user to submit data using dialog, But whenever user clicks
on any button in the dialog it is closing. How can I control the dialog hide or close on button click.
Previously we were using setClosable from controlsfx dialog to achieve this kinda behaviour.
△ ▽ • Reply • Share ›

Marco Jakob Mod > Hemant Sonawane • 5 years ago


I think it's the idea of the small dialogs that they close when a button is clicked. For more
complex dialogs I would probably not bother with those dialogs and just create a new
custom stage for it.
△ ▽ • Reply • Share ›

Craig • 5 years ago


Macro, I just wanted to thank you for all the great tutorials. I really love how you have included the
projects source code in every blog. It has really helped me understand the basics of MVC and gives
me much more confidence as a programer. I never learned swing, would you say its worth learning
or is JavaFX the future?
△ ▽ • Reply • Share ›

Marco Jakob Mod > Craig • 5 years ago

Hi Craig, thank you. I wouldn't bother learning Swing except if you have a project where you
are forced to use it. Otherwise, JavaFX is the present and future as I see it.
△ ▽ • Reply • Share ›

Load more comments

✉ Subscribe d Add Disqus to your siteAdd DisqusAdd 🔒 Disqus' Privacy PolicyPrivacy PolicyPrivacy

(ht… (ht… (/b… (ht…


   
Subscribe to receive updates by Email (https://tinyletter.com/codemakery).

Enter email

Get updates

Created by Marco Jakob (/about) • Licensed under Creative Commons Attribution 4.0
(https://creativecommons.org/licenses/by/4.0/)

You might also like