R
- The return type of the dialog, via the
result
property.public class Dialog<R> extends java.lang.Object implements EventTarget
DialogPane
and provides the necessary API
to present it to end users. In JavaFX 8u40, this essentially means that the
DialogPane
is shown to users inside a Stage
, but future releases
may offer alternative options (such as 'lightweight' or 'internal' dialogs).
This API therefore is intentionally ignorant of the underlying implementation,
and attempts to present a common API for all possible implementations.
The Dialog class has a single generic type, R, which is used to represent
the type of the result
property (and also, how to
convert from ButtonType
to R, through the use of the
result converter
Callback
).
Critical note: It is critical that all developers who choose
to create their own dialogs by extending the Dialog class understand the
importance of the result converter
property.
A result converter must always be set, whenever the R type is not
Void
or ButtonType
. If this is not heeded, developers will find
that they get ClassCastExceptions in their code, for failure to convert from
ButtonType
via the result converter
.
It is likely that most developers would be better served using either the
Alert
class (for pre-defined, notification-style alerts), or either of
the two pre-built dialogs (TextInputDialog
and ChoiceDialog
),
depending on their needs.
Once a Dialog is instantiated, the next step is to configure it. Almost
all properties on Dialog are not related to the content of the Dialog, the
only exceptions are contentTextProperty()
,
headerTextProperty()
, and graphicProperty()
, and these
properties are simply forwarding API onto the respective properties on the
DialogPane
stored in the dialog pane
property. These three properties are forwarded from DialogPane for developer
convenience. For developers wanting to configure their dialog, they will in many
cases be required to use code along the lines of
dialog.getDialogPane().setExpandableContent(node)
.
After configuring these properties, all that remains is to consider whether
the buttons (created using ButtonType
and the
DialogPane.createButton(ButtonType)
method) are fully configured.
Developers will quickly find that the amount of configurability offered
via the ButtonType
class is minimal. This is intentional, but does not
mean that developers can not modify the buttons created by the ButtonType
that have been specified. To do this, developers simply call the
DialogPane.lookupButton(ButtonType)
method with the ButtonType
(assuming it has already been set in the DialogPane.getButtonTypes()
list. The returned Node is typically of type Button
, but this depends
on if the DialogPane.createButton(ButtonType)
method has been overridden. A
typical approach is therefore along the following lines:
ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
Dialog<String> dialog = new Dialog<>();
dialog.getDialogPane().getButtonTypes().add(loginButtonType);
boolean disabled = false; // computed based on content of text fields, for example
dialog.getDialogPane().lookupButton(loginButtonType).setDisable(disabled);
Once a Dialog is instantiated and fully configured, the next step is to show it. More often than not, dialogs are shown in a modal and blocking fashion. 'Modal' means that the dialog prevents user interaction with the owning application whilst it is showing, and 'blocking' means that code execution stops at the point in which the dialog is shown. This means that you can show a dialog, await the user response, and then continue running the code that directly follows the show call, giving developers the ability to immediately deal with the user input from the dialog (if relevant).
JavaFX dialogs are modal by default (you can change this via the
initModality(javafx.stage.Modality)
API). To specify whether you want
blocking or non-blocking dialogs, developers simply choose to call
showAndWait()
or show()
(respectively). By default most
developers should choose to use showAndWait()
, given the ease of
coding in these situations. Shown below is three code snippets, showing three
equally valid ways of showing a dialog:
Option 1: The 'traditional' approach
Optional<ButtonType> result = dialog.showAndWait();
if (result.isPresent() && result.get() == ButtonType.OK) {
formatSystem();
}
Option 2: The traditional + Optional approach
dialog.showAndWait().ifPresent(response -> {
if (response == ButtonType.OK) {
formatSystem();
}
});
Option 3: The fully lambda approach
dialog.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> formatSystem());
There is no better or worse option of the three listed above, so developers
are encouraged to work to their own style preferences. The purpose of showing
the above is to help introduce developers to the Optional
API, which
is new in Java 8 and may be foreign to many developers.
In some circumstances it is desirable to prevent a dialog from closing
until some aspect of the dialog becomes internally consistent (e.g. a form
inside the dialog has all fields in a valid state). To do this, users of the
dialogs API should become familiar with the
DialogPane.lookupButton(ButtonType)
method. By passing in a
ButtonType
(that has already been set
in the button types
list), users will be
returned a Node that is typically of type Button
(but this depends
on if the DialogPane.createButton(ButtonType)
method has been
overridden). With this button, users may add an event filter that is called
before the button does its usual event handling, and as such users may
prevent the event handling by consuming
the event. Here's a simplified
example:
final Button btOk = (Button) dlg.getDialogPane().lookupButton(ButtonType.OK);
btOk.addEventFilter(ActionEvent.ACTION, event -> {
if (!validateAndStore()) {
event.consume();
}
});
It is important to understand what happens when a Dialog is closed, and also how a Dialog can be closed, especially in abnormal closing situations (such as when the 'X' button is clicked in a dialogs title bar, or when operating system specific keyboard shortcuts (such as alt-F4 on Windows) are entered). Fortunately, the outcome is well-defined in these situations, and can be best summarised in the following bullet points:
ButtonType
whose ButtonBar.ButtonData
is of type
ButtonBar.ButtonData.CANCEL_CLOSE
.ButtonType
whose ButtonBar.ButtonData
returns true
when ButtonBar.ButtonData.isCancelButton()
is called.DialogPane
area of the dialog.
result
property to whatever value is returned
from calling the result converter
with
the first matching ButtonType
.
result
property will be null, and the
showAndWait()
method will return Optional.empty()
. This
later point means that, if you use either of option 2 or option 3 (as
presented earlier in this class documentation), the
Optional.ifPresent(java.util.function.Consumer)
lambda will never
be called, and code will continue executing as if the dialog had not
returned any value at all.
Alert
,
TextInputDialog
,
ChoiceDialog
Modifier and Type | Field and Description |
---|---|
(package private) FXDialog |
dialog
Private fields
|
private ObjectProperty<DialogPane> |
dialogPane
The root node of the dialog, the
DialogPane contains all visual
elements shown in the dialog. |
private EventHandlerManager |
eventHandlerManager
Events
|
private static PseudoClass |
HEADER_PSEUDO_CLASS
Stylesheet Handling
|
private boolean |
isClosing |
private static PseudoClass |
NO_HEADER_PSEUDO_CLASS |
private ObjectProperty<EventHandler<DialogEvent>> |
onCloseRequest
Called when there is an external request to close this
Dialog . |
private ObjectProperty<EventHandler<DialogEvent>> |
onHidden
Called just after the Dialog has been hidden.
|
private ObjectProperty<EventHandler<DialogEvent>> |
onHiding
Called just prior to the Dialog being hidden.
|
private ObjectProperty<EventHandler<DialogEvent>> |
onShowing
Called just prior to the Dialog being shown.
|
private ObjectProperty<EventHandler<DialogEvent>> |
onShown
Called just after the Dialog is shown.
|
private ObjectProperty<Callback<ButtonType,R>> |
resultConverterProperty |
private ObjectProperty<R> |
resultProperty |
Constructor and Description |
---|
Dialog()
Creates a dialog without a specified owner.
|
Modifier and Type | Method and Description |
---|---|
EventDispatchChain |
buildEventDispatchChain(EventDispatchChain tail)
Construct an event dispatch chain for this target.
|
void |
close()
Hides the dialog.
|
StringProperty |
contentTextProperty()
A property representing the content text for the dialog pane.
|
ObjectProperty<DialogPane> |
dialogPaneProperty() |
java.lang.String |
getContentText()
Returns the currently-set content text for this DialogPane.
|
DialogPane |
getDialogPane() |
Node |
getGraphic() |
java.lang.String |
getHeaderText()
Returns the currently-set header text for this DialogPane.
|
double |
getHeight()
Returns the height of the dialog.
|
Modality |
getModality()
Retrieves the modality attribute for this dialog.
|
EventHandler<DialogEvent> |
getOnCloseRequest() |
EventHandler<DialogEvent> |
getOnHidden() |
EventHandler<DialogEvent> |
getOnHiding() |
EventHandler<DialogEvent> |
getOnShowing() |
EventHandler<DialogEvent> |
getOnShown() |
Window |
getOwner()
Retrieves the owner Window for this dialog, or null for an unowned dialog.
|
R |
getResult() |
Callback<ButtonType,R> |
getResultConverter() |
java.lang.String |
getTitle()
Return the title of the dialog.
|
double |
getWidth()
Returns the width of the dialog.
|
double |
getX() |
double |
getY() |
ObjectProperty<Node> |
graphicProperty()
The dialog graphic, presented either in the header, if one is showing, or
to the left of the
content . |
StringProperty |
headerTextProperty()
A property representing the header text for the dialog pane.
|
ReadOnlyDoubleProperty |
heightProperty()
Property representing the height of the dialog.
|
void |
hide()
closes the dialog.
|
(package private) void |
impl_setResultAndClose(ButtonType cmd,
boolean close)
Private implementation
|
void |
initModality(Modality modality)
Specifies the modality for this dialog.
|
void |
initOwner(Window window)
Specifies the owner
Window for this dialog, or null for a top-level,
unowned dialog. |
void |
initStyle(StageStyle style)
Specifies the style for this dialog.
|
boolean |
isResizable()
Returns whether or not the dialog is resizable.
|
boolean |
isShowing()
Returns whether or not the dialog is showing.
|
ObjectProperty<EventHandler<DialogEvent>> |
onCloseRequestProperty() |
ObjectProperty<EventHandler<DialogEvent>> |
onHiddenProperty() |
ObjectProperty<EventHandler<DialogEvent>> |
onHidingProperty() |
ObjectProperty<EventHandler<DialogEvent>> |
onShowingProperty() |
ObjectProperty<EventHandler<DialogEvent>> |
onShownProperty() |
BooleanProperty |
resizableProperty()
Represents whether the dialog is resizable.
|
ObjectProperty<Callback<ButtonType,R>> |
resultConverterProperty()
API to convert the
ButtonType that the user clicked on into a
result that can be returned via the result
property. |
ObjectProperty<R> |
resultProperty()
A property representing what has been returned from the dialog.
|
void |
setContentText(java.lang.String contentText)
Sets the string to show in the dialog content area.
|
void |
setDialogPane(DialogPane value) |
void |
setGraphic(Node graphic)
Sets the dialog graphic, which will be displayed either in the header, if
one is showing, or to the left of the
content . |
void |
setHeaderText(java.lang.String headerText)
Sets the string to show in the dialog header area.
|
void |
setHeight(double height)
Sets the height of the dialog.
|
void |
setOnCloseRequest(EventHandler<DialogEvent> value) |
void |
setOnHidden(EventHandler<DialogEvent> value) |
void |
setOnHiding(EventHandler<DialogEvent> value) |
void |
setOnShowing(EventHandler<DialogEvent> value) |
void |
setOnShown(EventHandler<DialogEvent> value) |
void |
setResizable(boolean resizable)
Sets whether the dialog can be resized by the user.
|
void |
setResult(R value) |
void |
setResultConverter(Callback<ButtonType,R> value) |
void |
setTitle(java.lang.String title)
Change the Title of the dialog.
|
void |
setWidth(double width)
Sets the width of the dialog.
|
void |
setX(double x) |
void |
setY(double y) |
void |
show()
Shows the dialog but does not wait for a user response (in other words,
this brings up a non-blocking dialog).
|
java.util.Optional<R> |
showAndWait()
Shows the dialog and waits for the user response (in other words, brings
up a blocking dialog, with the returned value the users input).
|
ReadOnlyBooleanProperty |
showingProperty()
Represents whether the dialog is currently showing.
|
StringProperty |
titleProperty()
Return the titleProperty of the dialog.
|
private void |
updatePseudoClassState() |
ReadOnlyDoubleProperty |
widthProperty()
Property representing the width of the dialog.
|
ReadOnlyDoubleProperty |
xProperty()
The horizontal location of this
Dialog . |
ReadOnlyDoubleProperty |
yProperty()
The vertical location of this
Dialog . |
final FXDialog dialog
private boolean isClosing
private ObjectProperty<DialogPane> dialogPane
DialogPane
contains all visual
elements shown in the dialog. As such, it is possible to completely adjust
the display of the dialog by modifying the existing dialog pane or creating
a new one.private final ObjectProperty<R> resultProperty
private final ObjectProperty<Callback<ButtonType,R>> resultConverterProperty
private final EventHandlerManager eventHandlerManager
private ObjectProperty<EventHandler<DialogEvent>> onShowing
private ObjectProperty<EventHandler<DialogEvent>> onShown
private ObjectProperty<EventHandler<DialogEvent>> onHiding
private ObjectProperty<EventHandler<DialogEvent>> onHidden
Dialog
is hidden, this event handler is invoked allowing
the developer to clean up resources or perform other tasks when the
Alert
is closed.private ObjectProperty<EventHandler<DialogEvent>> onCloseRequest
Dialog
.
The installed event handler can prevent dialog closing by consuming the
received event.private static final PseudoClass HEADER_PSEUDO_CLASS
private static final PseudoClass NO_HEADER_PSEUDO_CLASS
public final void show()
result property
, or else add a listener
to the result property to be informed of when it is set.java.lang.IllegalStateException
- if this method is called on a thread
other than the JavaFX Application Thread.public final java.util.Optional<R> showAndWait()
This method must be called on the JavaFX Application thread.
Additionally, it must either be called from an input event handler or
from the run method of a Runnable passed to
Platform.runLater
.
It must not be called during animation or layout processing.
Optional
that contains the result
.
Refer to the Dialog
class documentation for more detail.java.lang.IllegalStateException
- if this method is called on a thread
other than the JavaFX Application Thread.java.lang.IllegalStateException
- if this method is called during
animation or layout processing.public final void close()
public final void hide()
public final void initModality(Modality modality)
modality
- the modality for this dialog.java.lang.IllegalStateException
- if this property is set after the dialog
has ever been made visible.public final Modality getModality()
public final void initStyle(StageStyle style)
style
- the style for this dialog.java.lang.IllegalStateException
- if this property is set after the dialog
has ever been made visible.public final void initOwner(Window window)
Window
for this dialog, or null for a top-level,
unowned dialog. This must be done prior to making the dialog visible.window
- the owner Window
for this dialog.java.lang.IllegalStateException
- if this property is set after the dialog
has ever been made visible.public final Window getOwner()
public final ObjectProperty<DialogPane> dialogPaneProperty()
public final DialogPane getDialogPane()
public final void setDialogPane(DialogPane value)
public final StringProperty contentTextProperty()
content node
, meaning
that if both the content node and the contentText properties are set, the
content text will not be displayed in a default DialogPane instance.public final java.lang.String getContentText()
public final void setContentText(java.lang.String contentText)
content node
, meaning
that if both the content node and the contentText properties are set, the
content text will not be displayed in a default DialogPane instance.public final StringProperty headerTextProperty()
header node
, meaning
that if both the header node and the headerText properties are set, the
header text will not be displayed in a default DialogPane instance.public final java.lang.String getHeaderText()
public final void setHeaderText(java.lang.String headerText)
header node
, meaning
that if both the header node and the headerText properties are set, the
header text will not be displayed in a default DialogPane instance.public final ObjectProperty<Node> graphicProperty()
content
.public final Node getGraphic()
public final void setGraphic(Node graphic)
content
.graphic
- The new dialog graphic, or null if no graphic should be shown.public final ObjectProperty<R> resultProperty()
result converter
,
which is intended to convert from the ButtonType
that the user
clicked on into a value of type R. Refer to the Dialog
class
JavaDoc for more details.public final R getResult()
public final void setResult(R value)
public final ObjectProperty<Callback<ButtonType,R>> resultConverterProperty()
ButtonType
that the user clicked on into a
result that can be returned via the result
property. This is necessary as ButtonType
represents the visual
button within the dialog, and do not know how to map themselves to a valid
result - that is a requirement of the dialog implementation by making use
of the result converter. In some cases, the result type of a Dialog
subclass is ButtonType (which means that the result converter can be null),
but in some cases (where the result type, R, is not ButtonType or Void),
this callback must be specified.public final Callback<ButtonType,R> getResultConverter()
public final void setResultConverter(Callback<ButtonType,R> value)
public final ReadOnlyBooleanProperty showingProperty()
public final boolean isShowing()
public final BooleanProperty resizableProperty()
public final boolean isResizable()
public final void setResizable(boolean resizable)
resizable
- true if dialog should be resizable.public final ReadOnlyDoubleProperty widthProperty()
public final double getWidth()
public final void setWidth(double width)
public final ReadOnlyDoubleProperty heightProperty()
public final double getHeight()
public final void setHeight(double height)
public final StringProperty titleProperty()
public final java.lang.String getTitle()
public final void setTitle(java.lang.String title)
title
- public final double getX()
public final void setX(double x)
public final ReadOnlyDoubleProperty xProperty()
Dialog
. Changing this attribute
will move the Dialog
horizontally.public final double getY()
public final void setY(double y)
public final ReadOnlyDoubleProperty yProperty()
Dialog
. Changing this attribute
will move the Dialog
vertically.public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail)
EventTarget
. This event target is
not automatically added to the chain, so if it wants to process events,
it needs to add an EventDispatcher
for itself to the chain.
In the case the event target is part of some hierarchy, the chain for it is usually built from event dispatchers collected from the root of the hierarchy to the event target.
The event dispatch chain is constructed by modifications to the provided initial event dispatch chain. The returned chain should have the initial chain at its end so the dispatchers should be prepended to the initial chain.
The caller shouldn't assume that the initial chain remains unchanged nor that the returned value will reference a different chain.
buildEventDispatchChain
in interface EventTarget
tail
- the initial chain to build frompublic final void setOnShowing(EventHandler<DialogEvent> value)
public final EventHandler<DialogEvent> getOnShowing()
public final ObjectProperty<EventHandler<DialogEvent>> onShowingProperty()
public final void setOnShown(EventHandler<DialogEvent> value)
public final EventHandler<DialogEvent> getOnShown()
public final ObjectProperty<EventHandler<DialogEvent>> onShownProperty()
public final void setOnHiding(EventHandler<DialogEvent> value)
public final EventHandler<DialogEvent> getOnHiding()
public final ObjectProperty<EventHandler<DialogEvent>> onHidingProperty()
public final void setOnHidden(EventHandler<DialogEvent> value)
public final EventHandler<DialogEvent> getOnHidden()
public final ObjectProperty<EventHandler<DialogEvent>> onHiddenProperty()
public final void setOnCloseRequest(EventHandler<DialogEvent> value)
public final EventHandler<DialogEvent> getOnCloseRequest()
public final ObjectProperty<EventHandler<DialogEvent>> onCloseRequestProperty()
void impl_setResultAndClose(ButtonType cmd, boolean close)
private void updatePseudoClassState()