How can i make JavaFX Confirmation dialog without cancel button? [duplicate] - javafx

This question already has answers here:
javafx.scene.control.Dialog<R> won't close on pressing "x"
(5 answers)
Closed 3 years ago.
I just want to make javaFX Confirmation dialog without cancel button.
When i just made dialog without cancel button, "X" button to close the dialog does not work.
How can i make without "Cancel" button?
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
}
In this code i want to remove
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
to make user can choose one of "One, Two, Three" without cancel button but the "X" button to work well.
I just tried like this.
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");
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree);
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
}
But when i made like this, the "X" button does not work. How can i handle this?

I just made the Button invisible.
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog with Custom Actions");
alert.setHeaderText(null);
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);
alert.getDialogPane().lookupButton(buttonTypeCancel).setVisible(false);
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
}

Related

JavaFx when I open dialog.showAndWait() how to focus TextArea

public Node dialog(){
Pane root = new Pane();
root.setPrefWidth(200);
root.setPrefHeight(200);
Button button = new Button("Dialog");
button.setOnAction(event -> {
Dialog dialog = new Dialog();
TextArea textArea = new TextArea();
dialog.getDialogPane().setContent(textArea);
ButtonType ok = new ButtonType("OK", ButtonBar.ButtonData.OK_DONE);
ButtonType cancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
DialogPane dialogPane = dialog.getDialogPane();
dialogPane.getButtonTypes().addAll(ok, cancel);
textArea.requestFocus();
dialog.showAndWait();
});
root.getChildren().add(button);
return root;
}
I try use textArea.requestFocus(); before dialog.showAndWait(); but when dialog open it always
focus OK Button. How to foucs textArea when dialog first open?
This should do the trick:
dialog.setOnShown(event -> {
Platform.runLater(textArea::requestFocus);
event.consume();
});
dialog.showAndWait();

JavaFX custom dialog set Layout of node

We created a Custom Dialog without an FXML file. We are using JavaFX 8.
The dialog loads and functions as expected but we can not move the Buttons and the TextField to enhance the styling.
We have tried to use tf.setLayoutY(50) this has no effect.
We used this tf.setPromptText("This Works ?") and it works.
We would rather not use css to accomplish this styling.
And we will consider a FXML file if we can keep the two event handlers that force data to be entered in the TextField.
So the question is: How to style this Custom Dialog?
The code is a mess as it includes some concepts we tried:
public void CustomDialog() {
Dialog dialog = new Dialog<>();
dialog.setResizable(false);
final Window window = dialog.getDialogPane().getScene().getWindow();
stage = (Stage) window;
stage.setMinHeight(600);
stage.setMinWidth(400);
TextField tf = new TextField();
tf.setLayoutX(10);
tf.setLayoutY(50);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
dialog.getDialogPane().getChildren().add(tf);
dialog.getDialogPane().setContent(tf);
// Create an event filter that consumes the action if the text is empty
EventHandler<ActionEvent> filter = event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
};
// lookup the buttons
ButtonBase okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
Button cancelButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.CANCEL);
// add the event-filter
okButton.addEventFilter(ActionEvent.ACTION, filter);
cancelButton.addEventFilter(ActionEvent.ACTION, filter);
stage.setOnCloseRequest(event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
}
//Scene scene = new Scene(root);
//dialogStage.setScene(scene);
dialog.initModality(Modality.APPLICATION_MODAL);
//dialogStage.setAlwaysOnTop(true);
//dialogStage.setResizable(false);
tf.setPromptText("This Works ?");
tf.requestFocus();// This does not work
dialog.showAndWait();
}
Grendel we enhanced your answer so anyone who comes by and sees the code you posted in your question will understand as you said it was a mess
Your posted answer was real old school but less work perhaps than building a FXML file
Besides it is good to know some old school tricks
public void NewDialog(){
Label lblAmt = new Label("Enter Amount");
Button btnOK = new Button("OK");
TextField txtAmt = new TextField();
AnchorPane secondaryLayout = new AnchorPane();
secondaryLayout.setStyle("-fx-border-color:red;-fx-border-width:10px; -fx-background-color: lightblue;");
secondaryLayout.getChildren().addAll(lblAmt,btnOK,txtAmt);
lblAmt.setLayoutX(30);
lblAmt.setLayoutY(30);
txtAmt.setLayoutX(164);
txtAmt.setLayoutY(25);
txtAmt.setMaxWidth(116);
btnOK.setLayoutX(190);
btnOK.setLayoutY(100);
btnOK.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
lblAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
txtAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
Scene secondScene = new Scene(secondaryLayout, 300, 180);
EventHandler<ActionEvent> filter = event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
};
// New window (Stage)
Stage newWindow = new Stage();
newWindow.initStyle(StageStyle.UNDECORATED);
//newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setResizable(false);
newWindow.setTitle("Second Stage");
newWindow.setScene(secondScene);
btnOK.addEventHandler(ActionEvent.ACTION,filter);
btnOK.setOnAction(evt -> {
String str = txtAmt.getText();
System.out.println("################ str "+str);
if(txtAmt.getText().equals("")) {
evt.consume();
txtAmt.requestFocus();
}else{
newWindow.close();
}
});
newWindow.setOnCloseRequest(event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
});
txtAmt.requestFocus();
newWindow.showAndWait();
}

Open another window on clicking OK button of Alert in JavaFX

private void showAlert(Alert.AlertType alertType, Window owner, String title, String message) {
Alert alert = new Alert(alertType);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(message);
alert.initOwner(owner);
//alert.show();
Optional<ButtonType> result = alert.showAndWait();
if ((result.isPresent()) && (result.get() == ButtonType.OK))
{
System.out.println("ALL OK..!");
//Open another window on clicking the OK button
}
}
On this particular section, on clicking OK button, I want to open another window.
Usually Button type is used for which an event can be defined by
buttonName.setOnAction( event -> {
//Action to do
} );
Now how do I define this OK as a button Type?

Enter Key Event Is Not Working On Dialog In Javafx?

I have tried the below code, it works fine with mouse event, but when I use key event i.e ENTER Key on any button than its not showing the result.
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle(null);
alert.setHeaderText(null);
alert.setGraphic(null);
alert.setContentText("Choose your option.");
ButtonType buttonTypeOne = new ButtonType("One");
ButtonType buttonTypeTwo = new ButtonType("Two");
ButtonType buttonTypeThree = new ButtonType("Three");
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree);
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == buttonTypeOne) {
System.out.println("One");
} else if (result.get() == buttonTypeTwo) {
System.out.println("Two");
} else if (result.get() == buttonTypeThree) {
System.out.println("Three");
}
I do not recommend making all buttons respond to enter, as that is counter to how most UI dialogs work.
Normally, a button with focus will fire when you press space, not enter. There are however special buttons that will activate on specific keys: A default button will fire on enter and a cancel button will fire on esc. Usually you will have only one of each of these special types of buttons in your dialog, so that they can be fired via the special keyboard accelerator, regardless of which button currently has focus.
Additionally, different desktop OS systems have different standards on placement of default and cancel buttons in a dialog system. This is to assist the user in easily finding these special buttons in any dialog. The JavaFX dialog system implements some logic internally for locating buttons in dialogs where the user would expect to see them across different desktop operating systems.
Let's say you want the button types from your example to be defined as default or cancel buttons and placed in the correct position for such buttons for your OS, then you can do as below:
ButtonType buttonTypeTwo = new ButtonType(
"Two",
ButtonBar.ButtonData.OK_DONE
);
ButtonType buttonTypeThree = new ButtonType(
"Three",
ButtonBar.ButtonData.CANCEL_CLOSE
);
Note the JavaFX system has automatically changed the position of the buttons and some of the color highlighting. When the user presses enter, then "Two" will fire, when the user presses esc, then "Three" will fire. If you run the same code on Windows or Linux, likely the buttons will be positioned differently, according to whatever button positioning standard is used for those OSes.
If you don't want JavaFX to reposition your buttons according to OS standards, but you want them to still respond to enter and esc keys, then you can lookup the buttons and directly modify the button attributes like below:
Button buttonTwo = (Button) alert.getDialogPane().lookupButton(buttonTypeTwo);
buttonTwo.setDefaultButton(true);
Button buttonThree = (Button) alert.getDialogPane().lookupButton(buttonTypeThree);
buttonThree.setCancelButton(true);
I recommend letting JavaFX appropriately position buttons of specific types rather than performing lookups as above.
I also recommend setting at least a CANCEL_CLOSE button or OK_DONE button in your JavaFX Alert, otherwise the user may have a difficult time actually closing the alert as the dialog will probably not respond to key presses as the user expects.
I don't know if this is not a kind of too much of a workaround, but at least it works:
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
[...]
ButtonType buttonTypeTwo = new ButtonType("Two");
ButtonType buttonTypeThree = new ButtonType("Three");
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree);
//Create a button for every ButtonType you add to your alert and give it a Eventhandler
Button button1 = (Button) alert.getDialogPane().lookupButton(buttonTypeOne);
Button button2 = (Button) alert.getDialogPane().lookupButton(buttonTypeTwo);
Button button3 = (Button) alert.getDialogPane().lookupButton(buttonTypeThree);
button1.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.ENTER)
alert.setResult(buttonTypeOne);
}
});
button2.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.ENTER)
alert.setResult(buttonTypeTwo);
}
});
button3.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.ENTER)
alert.setResult(buttonTypeThree);
}
});
//go ahead with your code
Optional<ButtonType> result = alert.showAndWait();
[...]
You just create some Buttons and assigned them the actual buttons on your alert. In the next Step you can give every button an EventHandler which just (In this example) checks - when any key is released - if the key was ENTER and set the result.
I guess there are better solutions for this. But it's the easiest way which comes to my mind currently. Hope it helps you.
Here how i solved it.
it works fine below is my confirm alert function.
public static boolean confirmAlert(String title, String msg){
ButtonType buttonTypeYes = new ButtonType("Yes", ButtonBar.ButtonData.OK_DONE);
ButtonType buttonTypeNo = new ButtonType("No",ButtonBar.ButtonData.CANCEL_CLOSE);
Alert alert = new Alert(Alert.AlertType.NONE, msg,buttonTypeNo,buttonTypeYes);
alert.setTitle(title);
Button button1 = (Button) alert.getDialogPane().lookupButton(buttonTypeYes);
button1.setDefaultButton(false); //***set default to false***
Button button2 = (Button) alert.getDialogPane().lookupButton(buttonTypeNo);
button1.setOnKeyReleased(event -> {
if(event.getCode() == KeyCode.ENTER)
alert.setResult(buttonTypeYes);
});
button2.setOnKeyReleased(event -> {
if(event.getCode() == KeyCode.ENTER)
alert.setResult(buttonTypeNo);
});
alert.showAndWait();
return alert.getResult()==buttonTypeYes;
}
you don't need to set default method, On which ever button you want to enter key
Alert confirmAlert = new Alert(Alert.AlertType.CONFIRMATION, "", ButtonType.YES, ButtonType.NO);
confirmAlert.setHeaderText("Are You Sure Want To Delete ?");
Button bt1 = (Button) confirmAlert.getDialogPane().lookupButton(ButtonType.YES);
Button bt2 = (Button) confirmAlert.getDialogPane().lookupButton(ButtonType.NO);
bt2.addEventHandler(KeyEvent.ANY,(event) -> {
if(event.getCode() == KeyCode.ENTER){
confirmAlert.setResult(ButtonType.NO);
}
});
Optional <ButtonType> action = confirmAlert.showAndWait();
if(action.get() == ButtonType.NO){
System.err.println("Action You Want");
}

Javafx: Close alert box (or, any dialog box) programatically

I have a JavaFx application in which I display an alert box using:
alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Title");
alert.setHeaderText("Some Text");
alert.setContentText("Choose your option.");
buttonTypeOne = new ButtonType("Yes");
buttonTypeCancel = new ButtonType("No", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeCancel);
Optional<ButtonType> result = alert.showAndWait();
Because the alert executesshowAndWait, so it will be displayed till the user either presses 'Yes' or 'No' or 'Close' the dialog.
Problem: I need to close this dialog programatically from somewhere else. To elaborate, if, let's say the user does not chose any option for 20 sec, or let's say this alert box was shown for some background process which just got over, and now I wish to close this alert box by setting result to be buttonTypeCancel, instead of the user pressing any button.
(Like dispose method in Swing)
How can I do this? I tried Event.fireevent (https://stackoverflow.com/a/22459308/3155986) but I am not able to write the correct event associated.
Thanks in advance!
Edit: Including sample code-
MainApp.java - Java class responsible for handling the application
Controller.java - Corresponding controller file
Design.fxml - FXML file for the application which is loaded via MainApp.java and controlled by Controller.java
Compute.java - Another java class to perform computations.
public class Compute{
Alert alert;
public void function1{
Platform.runLater(new Runnable(){
public void run(){
alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Title");
alert.setHeaderText("Some Text");
alert.setContentText("Choose your option.");
buttonTypeOne = new ButtonType("Yes");
buttonTypeCancel = new ButtonType("No", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeCancel);
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == buttonTypeOne){
// ... user chose "One"
} else {
// ... user chose CANCEL or closed the dialog
}
}
});
}
public void function2{
//......Does some long computation here
//.... If the computation finishes before the user chooses 'Yes' or 'No' on alert box
//...Then close the alertbox here and execute the code corresponding to buttonTypeCancel
//..I tried alert.close(); and alert.hide(); but doesn't work.
}
}
Also, is there any alternate solution to do this? Originally, I wanted to keep the Compute.java clean of any javafx code but couldn't figure out how.
Try this
public void function2 {
Button cancelButton = ( Button ) alert.getDialogPane().lookupButton( buttonTypeCancel );
cancelButton.fire();
}
Or for more general
public void function2 {
for ( ButtonType bt : alert.getDialogPane().getButtonTypes() )
{
if ( bt.getButtonData() == ButtonBar.ButtonData.CANCEL_CLOSE )
{
Button cancelButton = ( Button ) alert.getDialogPane().lookupButton( bt );
cancelButton.fire();
break;
}
}
}
Full example:
#Override
public void start( final Stage primaryStage )
{
Alert alert = new Alert( Alert.AlertType.CONFIRMATION );
alert.setTitle( "Title" );
alert.setHeaderText( "Some Text" );
alert.setContentText( "Choose your option." );
ButtonType buttonTypeOne = new ButtonType( "Yes" );
alert.initModality( Modality.NONE );
ButtonType buttonTypeCancel = new ButtonType( "No", ButtonBar.ButtonData.CANCEL_CLOSE );
alert.getButtonTypes().setAll( buttonTypeOne, buttonTypeCancel );
Button b = new Button( "close alert" );
b.setOnAction(( ActionEvent event ) ->
{
for ( ButtonType bt : alert.getDialogPane().getButtonTypes() )
{
System.out.println( "bt = " + bt );
if ( bt.getButtonData() == ButtonBar.ButtonData.CANCEL_CLOSE )
{
Button cancelButton = ( Button ) alert.getDialogPane().lookupButton( bt );
cancelButton.fire();
break;
}
}
});
final Scene scene = new Scene( new Group( b ), 400, 300 );
primaryStage.setScene( scene );
primaryStage.show();
Optional<ButtonType> result = alert.showAndWait();
if ( result.get() == buttonTypeOne )
{
System.out.println( "one " );
}
else if( result.get() == buttonTypeCancel )
{
System.out.println( "cancel " );
}
}
You can invoke close() method on the Alert or any Dialog.
Here is a simple example which waits for 5 secs, and if the Alert is still showing, it closes it.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.stage.Stage;
import java.util.Optional;
public class Main extends Application{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Title");
alert.setHeaderText("Some Text");
alert.setContentText("Choose your option.");
ButtonType buttonTypeOne = new ButtonType("Yes");
ButtonType buttonTypeCancel = new ButtonType("No", ButtonBar.ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeCancel);
Thread thread = new Thread(() -> {
try {
// Wait for 5 secs
Thread.sleep(5000);
if (alert.isShowing()) {
Platform.runLater(() -> alert.close());
}
} catch (Exception exp) {
exp.printStackTrace();
}
});
thread.setDaemon(true);
thread.start();
Optional<ButtonType> result = alert.showAndWait();
}
}
It's closing opened dialog in 2 second.
dialog = new Dialog<>();
dialog.setTitle("It's a dialog!");
dialog.show();
Thread newThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
Platform.runLater(new Runnable() {
#Override
public void run() {
dialog.close();
}
});
}
});
newThread.start();

Resources