Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use JFXAlerts? #633

Open
TurekBot opened this issue Mar 7, 2018 · 9 comments
Open

How to use JFXAlerts? #633

TurekBot opened this issue Mar 7, 2018 · 9 comments

Comments

@TurekBot
Copy link
Collaborator

TurekBot commented Mar 7, 2018

There's no place for JFXAlerts in the demo, yet! Allow me to take the first step.

@TurekBot
Copy link
Collaborator Author

TurekBot commented Mar 7, 2018

Here, now they have a place—all the boilerplate is done. #634

But there's nothing "demonstrated" yet. Can anyone help out with that?

@alamenai
Copy link

Use JFXDialog instead of alerts.

@jfoenixadmin
Copy link
Collaborator

jfoenixadmin commented Mar 20, 2018

Just for clarification, @XlintXms this issue is a request for JFXAlert documentation.

@TurekBot
Copy link
Collaborator Author

@jfoenixadmin, I saw that you added an example of how to use a JFXAlert; thanks 👍 .

You mentioned in #634 that "unlike java Alerts, JFXAlert doesn't support return type."

It'll be important to make it clear in the documentation how users should go about getting a result after a JFXAlert closes.

If one tries to use a JFXAlert like a Dialog things don't work the same. It's quite confusing.

While

Optional<String> result = dialog.showAndWait();
result.ifPresent(string -> System.out.println(string));

would give you back the right result when using a Dialog, with a JFXAlert you'll always get back a ButtonData.CANCEL_CLOSE.

@TurekBot
Copy link
Collaborator Author

TurekBot commented Mar 26, 2018

If I understand correctly, the reason for this is because JFXAlert doesn't use ButtonTypes. Through a series of events native to Dialog, the ButtonData.CANCEL_CLOSE is returned because no result is specified.

I may have found a way to work around this. Say we don't use ButtonTypes, still. But we do set the result in the setOnAction method of the buttons we add to the actions section.

An example:

JFXTextField usernameTextField = new JFXTextField();

addUserButton.setOnAction(event -> {
	// Ensure that the user can't close the alert.
	JFXAlert<String> alert = new JFXAlert<>((Stage) addUserButton.getScene().getWindow());
	alert.initModality(Modality.APPLICATION_MODAL);
	alert.setOverlayClose(false);
	
	// Create the content of the JFXAlert with JFXDialogLayout
	JFXDialogLayout layout = new JFXDialogLayout();
	layout.setHeading(new Label("Enter Username"));
	layout.setBody(new VBox(new Label("Please enter the username of the person you would like to add."),
			usernameTextField));
	
	// Buttons get added into the actions section of the layout.
	JFXButton addButton = new JFXButton("ADD");
	addButton.setDefaultButton(true);
	addButton.setOnAction(addEvent -> {
		// When the button is clicked, we set the result accordingly
		alert.setResult(usernameTextField.getText());
		alert.hideWithAnimation();
	});
	
	JFXButton cancelButton = new JFXButton("CANCEL");
	cancelButton.setCancelButton(true);
	cancelButton.setOnAction(closeEvent -> alert.hideWithAnimation());
	
	layout.setActions(addButton, cancelButton);
	alert.setContent(layout);

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

The sticky part of it is what happens if the result is never set (like in the case of the cancel button): Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: javafx.scene.control.ButtonType cannot be cast to java.lang.String

@stale
Copy link

stale bot commented Jan 7, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added wontfix and removed wontfix labels Jan 7, 2019
@TurekBot
Copy link
Collaborator Author

TurekBot commented May 7, 2019

Recently I discovered a way to avoid the ClassCastException that occurs if the user enters/clicks nothing (the one I mentioned in my last comment).

The default result converter returns a result of type ButtonType, even if the result is never set and no buttons are ever pressed, and that causes the ClassCastException. If we override it like this

    alert.setResultConverter(buttonType -> {
                // We don't want to use a result converter, 
                // if there is no result set explicitly, then return null.
                return null;
            });

then it will no longer try to return a ButtonType when no result is set. The result will be null if the user chooses nothing the first time—but that's what an Optional is for.

With this strategy, if we reuse the dialog, it's important to reset the result after you use it. If you don't, the same result sticks around for next time you use the dialog.

    Optional<String> result = alert.showAndWait();
    if (result.isPresent()){
        System.out.println("Your choice: " + result.get());
        alert.setResult(null); // reset the result for next time
    }

@stars-one
Copy link

If I understand correctly, the reason for this is because JFXAlert doesn't use ButtonTypes. Through a series of events native to Dialog, the ButtonData.CANCEL_CLOSE is returned because no result is specified.

I may have found a way to work around this. Say we don't use ButtonTypes, still. But we do set the result in the setOnAction method of the buttons we add to the actions section.

An example:

JFXTextField usernameTextField = new JFXTextField();

addUserButton.setOnAction(event -> {
	// Ensure that the user can't close the alert.
	JFXAlert<String> alert = new JFXAlert<>((Stage) addUserButton.getScene().getWindow());
	alert.initModality(Modality.APPLICATION_MODAL);
	alert.setOverlayClose(false);
	
	// Create the content of the JFXAlert with JFXDialogLayout
	JFXDialogLayout layout = new JFXDialogLayout();
	layout.setHeading(new Label("Enter Username"));
	layout.setBody(new VBox(new Label("Please enter the username of the person you would like to add."),
			usernameTextField));
	
	// Buttons get added into the actions section of the layout.
	JFXButton addButton = new JFXButton("ADD");
	addButton.setDefaultButton(true);
	addButton.setOnAction(addEvent -> {
		// When the button is clicked, we set the result accordingly
		alert.setResult(usernameTextField.getText());
		alert.hideWithAnimation();
	});
	
	JFXButton cancelButton = new JFXButton("CANCEL");
	cancelButton.setCancelButton(true);
	cancelButton.setOnAction(closeEvent -> alert.hideWithAnimation());
	
	layout.setActions(addButton, cancelButton);
	alert.setContent(layout);

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

The sticky part of it is what happens if the result is never set (like in the case of the cancel button): Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: javafx.scene.control.ButtonType cannot be cast to java.lang.String

thanks.it works!
I want to put your codes to generate a DialogBuilder which is the same as theAlertDiglogBuilder in Android delevopment

@msahban647
Copy link

Can anyone please send the image of alert or dialog... I want to see it's look and feel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants