Changing the cursor in an alertbox JavaFX - java

Hi I am trying to change the cursor, in a JavaFX alert which displays once a button in sceneHome is pressed, once a buttontype is clicked.
This is the function thats gets called when the user presses the button in sceneHome:
public void export() {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Export menu");
alert.setHeaderText("Wat wilt u exporteren, adressen of ritten?");
alert.setContentText("Maak een keuze.");
ButtonType buttonTypeOne = new ButtonType("Adressen");
ButtonType buttonTypeTwo = new ButtonType("Ritten");
ButtonType buttonTypeCancel = new ButtonType("Annuleren", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeCancel);
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == buttonTypeOne){
//scene.setCursor(Cursor.WAIT);
ToCSV.export("adressen");
//scene.setCursor(Cursor.DEFAULT);
} else if (result.get() == buttonTypeTwo) {
//scene.setCursor(Cursor.WAIT);
ToCSV.export("ritten");
//scene.setCursor(Cursor.DEFAULT);
} else{
//do nothing
}
}
If I say sceneHome.setCursor(Cursor.WAIT) nothing happens and if I say alert.getDialogPane().getScene().setCursor(Cursor.WAIT) I get a NullPointerException...
So which scene should I pass in (at //scene.setCursor(Cursor.DEFAULT); and //scene.setCursor(Cursor.WAIT);)?

It looks like your ToCSV.export call actually block the program to change the cursor. Try to run execution of this method in separate Task:
private static void export(Scene scene) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Export menu");
alert.setHeaderText("Wat wilt u exporteren, adressen of ritten?");
alert.setContentText("Maak een keuze.");
ButtonType buttonTypeOne = new ButtonType("Adressen");
ButtonType buttonTypeTwo = new ButtonType("Ritten");
ButtonType buttonTypeCancel = new ButtonType("Annuleren", ButtonBar.ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeCancel);
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == buttonTypeOne){
scene.setCursor(Cursor.WAIT);
final Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
ToCSV.export("adressen");
return null;
}
#Override
protected void succeeded() {
scene.setCursor(Cursor.DEFAULT);
}
};
new Thread(task).start();
} else if (result.get() == buttonTypeTwo) {
//
} else{
//do nothing
}
}
The scene is the one where the button that opens this dialog located.
Ideally, for the clean code sake, you should create a separate ToCSVTask class with this logic and submit it to ExecutorService - you may google the cleanest way how to do it.

Related

if no item of a combobox is selected do semothing in Java Fx

I am using JavaFX have a list of items in a combobox , when a user trys to register i want that a condition cheks if he selected an item or not in that combo. i have tryed this but it doesent work , how to do it please .
public void ADDuser(ActionEvent event) {
String username = usernametf.getText();
String pass = passtf.getText();
LocalDate datebirth = dateofbirth.getValue();
String situation = situationcombobox.getSelectionModel().getSelectedItem().toString();
if (!username.equals("") &&
!pass.equals("") &&
!datebirth.equals(null) &&
!situation.equals(null)) {// situaion problem
mainc.con.AdduserDatabase(username, pass, datebirth, situation, gender);
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Information Ajout");
alert.setHeaderText(null);
alert.setContentText("Ajout réussi merci " );
alert.showAndWait();
Stage stage = (Stage) btnadd.getScene().getWindow();
stage.close();
} else {
System.out.println(situation);
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Information Ajout");
alert.setHeaderText(null);
alert.setContentText("Please Fill All the fields ! " );
alert.showAndWait();
}
}
}

JavaFX how can I reset the application?

my code opens another window but the first one is still open. How can I close the first window?
ButtonType continue = new ButtonType("Continue");
ButtonType exit= new ButtonType("Exit");
alert.getButtonTypes().setAll(continue, exit);
Optional<ButtonType> result = alert.showAndWait();
if (result .get() == continue ) {
Controllerxx = new commandCenter();
centerFX newFX= new centerFX ();
Stage stage = new Stage();
newFX.start(stage);
} else if (result .get() == exit) {
Platform.exit();
}
You can try something like below :
btn.setOnAction((ActionEvent event) -> {
((Node) (event.getSource())).getScene().getWindow().hide();
});
You can get the current scene by the Action event of your exit button and close it.

JavaFX Opening one dialog from another

I have the following workflow in my application that is causing a problem:
Click Button to Open Dialog > Open Dialog > Click Button From Dialog > Display Confirmation Alert > Upon Confirmation close the first dialog and open a new dialog
The second dialog does not allow input into the TextField. I have included a SSCE that displays the problem. One additional weird thing is that if you try to close the second dialog by clicking the 'X', and then close the Alert then I am able to type into the field.
public class DialogTest extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Show Dialog");
VBox root = new VBox(10, button);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 350, 120);
primaryStage.setScene(scene);
primaryStage.show();
button.setOnAction(event -> {
Dialog<Pair<String, String>> dialog = getDialog(scene.getWindow(), "Dialog 1", true);
dialog.showAndWait();
});
}
public static void main(String[] args) {
launch(args);
}
public Dialog<Pair<String, String>> getDialog(Window owner, String title, boolean addButton) {
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle(title);
dialog.initOwner(owner);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
if(addButton) {
Button button = new Button("Show Dialog");
dialog.getDialogPane().setContent(button);
button.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION, "Are you sure?", ButtonType.YES, ButtonType.NO);
alert.initOwner(owner);
if(alert.showAndWait().get() == ButtonType.YES) {
dialog.close();
Dialog<Pair<String, String>> dialog2 = getDialog(owner, "Dialog 2", false);
TextField textField = new TextField();
dialog2.getDialogPane().setContent(textField);
dialog2.getDialogPane().getScene().getWindow().setOnCloseRequest(closeEvent -> {
closeEvent.consume();
if(textField.getText().trim().isEmpty()) {
Alert alert2 = new Alert(AlertType.ERROR, "Please enter a value", ButtonType.OK);
alert2.initOwner(dialog2.getDialogPane().getScene().getWindow());
alert2.showAndWait();
}
});
dialog2.showAndWait();
}
});
}
return dialog;
}
}
Problem
As explained, you have a modality problem.
Solution
The following code will demonstrate a solution where the user is asked if he really wants to print and after printing, if the ending number is correct.
(Note, that I use a class IntField from here)
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.Window;
public class DialogTest extends Application {
Region veil;
ProgressIndicator indicator;
IntField startingNumber = new IntField(0, 999999, 0);
IntField endingNumber = new IntField(startingNumber.getValue(), 999999, startingNumber.getValue() + 1);
ButtonType printButtonType = new ButtonType("Print", ButtonData.OK_DONE);
Stage stage;
#Override
public void start(Stage primaryStage) {
stage = primaryStage;
Button button = new Button("Print Checks");
VBox box = new VBox(10, button);
box.setAlignment(Pos.CENTER);
veil = new Region();
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.3);");
veil.setVisible(false);
indicator = new ProgressIndicator();
indicator.setMaxHeight(60);
indicator.setMinWidth(60);
indicator.setVisible(false);
StackPane root = new StackPane(box, veil, indicator);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
button.setOnAction((event) -> {
Dialog<ButtonType> dialog
= getCheckPrintDialog(primaryStage, "Enter starting check number");
dialog.showAndWait()
.filter(result -> result == printButtonType)
.ifPresent(result -> {
// this is for this example only, normaly you already have this value
endingNumber.setValue(startingNumber.getValue() + 1);
printChecks(startingNumber.getValue(), endingNumber.getValue());
});
});
}
public static void main(String[] args) {
launch(args);
}
public <R extends ButtonType> Dialog getCheckPrintDialog(Window owner, String title) {
Dialog<R> dialog = new Dialog<>();
dialog.initOwner(owner);
dialog.setTitle(title);
dialog.getDialogPane().getButtonTypes().addAll(printButtonType, ButtonType.CANCEL);
Button btOk = (Button) dialog.getDialogPane().lookupButton(printButtonType);
btOk.addEventFilter(ActionEvent.ACTION, event -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Print Checks? Are you sure?", ButtonType.YES, ButtonType.NO);
alert.showAndWait()
.filter(result -> result == ButtonType.NO)
.ifPresent(result -> event.consume());
});
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
Text from = new Text("Starting Number:");
grid.add(from, 0, 0);
grid.add(startingNumber, 1, 0);
dialog.getDialogPane().setContent(grid);
return dialog;
}
private void printChecks(int from, int to) {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
Thread.sleep(5000);
return null;
}
};
task.setOnSucceeded((event) -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Has the last check, the number: " + endingNumber.getValue() + "?", ButtonType.YES, ButtonType.NO);
alert.initOwner(stage);
Button btnNo = (Button) alert.getDialogPane().lookupButton(ButtonType.NO);
btnNo.addEventFilter(ActionEvent.ACTION, e -> {
Dialog<ButtonType> newEndNum = new Dialog<>();
newEndNum.setTitle("Enter the ending check number");
newEndNum.initOwner(stage);
newEndNum.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
Text toUser = new Text("Ending Number:");
grid.add(toUser, 0, 0);
grid.add(endingNumber, 1, 0);
newEndNum.getDialogPane().setContent(grid);
newEndNum.showAndWait().filter(result -> result == ButtonType.CANCEL)
.ifPresent(result -> e.consume());
});
alert.showAndWait();
});
veil.visibleProperty().bind(task.runningProperty());
indicator.visibleProperty().bind(task.runningProperty());
new Thread(task).start();
}
}
Working Application
The main Window:
The Print Dialog:
After a click on Print (Alerts are localized, for me in german):
After a click on Yes the Print Dialog closes and a progress will be visible (for 5 sec. in this example)
After the Printing finishes a Dialog comes up which is asking for the correct ending number
If you click Yes all is done, if you click No another dialog opens to enter the correct ending value
I have found a point where the problem is. But because I am just beginning with JavaFx I cannot provide the "why".
It seems to me that the problem is in the dialog.close(), just after the if (alert.showAndWait().get() == ButtonType.YES).
Look like it looses some reference to the dialog when you close it or something like that (I let the experts clear this out).
As a workaround, and it works for me, is move the dialog.close() to after dialog2.showAndWait();
public Dialog<Pair<String, String>> getDialog(Window owner, String title, boolean addButton) {
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle(title);
dialog.initOwner(owner);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
if (addButton) {
Button button = new Button("Show Dialog");
dialog.getDialogPane().setContent(button);
button.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION, "Are you sure?", ButtonType.YES, ButtonType.NO);
alert.initOwner(owner);
if (alert.showAndWait().get() == ButtonType.YES) {
// dialog.close(); // supressed this and placed at the bottom
Dialog<Pair<String, String>> dialog2 = getDialog(owner, "Dialog 2", false);
TextField textField = new TextField();
dialog2.getDialogPane().setContent(textField);
dialog2.getDialogPane().getScene().getWindow().setOnCloseRequest(closeEvent -> {
closeEvent.consume();
if (textField.getText().trim().isEmpty()) {
Alert alert2 = new Alert(AlertType.ERROR, "Please enter a value", ButtonType.OK);
alert2.initOwner(dialog2.getDialogPane().getScene().getWindow());
alert2.showAndWait();
}
});
dialog2.showAndWait();
dialog.close(); // new location
}
});
}
return dialog;
}
The reasons for this to happen I cannot explain, but this could be a workaround.
I hope this helps you.
In your "start" method where you create Dialog1 you should call dialog.show() instead of dialog.showAndWait().
i.e.
button.setOnAction(event -> {
Dialog<Pair<String, String>> dialog = getDialog(scene.getWindow(), "Dialog 1", true);
// dialog.showAndWait();
dialog.show();
});

javafx: bug when trying to close window properly

I am designing the close window functionality for my desktop application. A high level explanation of the functionality is listed:
If I click the Exit menuItem, it prompts a ConfirmBox the user to confirm whether he wants to save or not before closing the application.
If the user click on the CloseButton on the window to force close the window (i.e. setOnCloseRequest function), the Exit menuItem event is fire off, which brings the user to case (1) again.
Within my ConfirmBoxcode, I have bind ENTER key to save things, N key to not save things and ESCAPE key to close confirmBox.
I have also set accelerator for the Exit menuItem (METAKEY + E).
Everything works fine. However, there is a minor bug if I follow this special sequence of steps. Whenever I use the accelerator for the Exit menuItem (i.e. METAKEY + E) and then I press either one of the 3 keys(ENTER, ESCAPE, N), the confirmBox closes but it pops up again.
I am wondering why is this happening only in this very special case?
public class ConfirmBox {
// answer[0] determines the need to Save
// answer[1] determines whether to close the application or not
private static boolean[] answer = new boolean[]{false,false};
private static Stage window;
public static boolean[] displayWarning(String title, String message){
window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setMinWidth(300);
Label label = new Label();
label.setText(message);
Button yesButton = new Button("Yes");
Button noButton = new Button("No");
// needToSave = true, close Application = true and close this confirmbox
yesButton.setOnAction(ey ->{
answer[0] = true;
answer[1] = true;
window.close();
});
// needToSave = false, close Application = true and close this confirmbox
noButton.setOnAction(en -> {
answer[0] = false;
answer[1] = true;
window.close();
});
// needToSave = false, close Application = false and close this confirmbox
window.setOnCloseRequest(e -> {
answer[0] = false;
answer[1] = false;
closeConfirmBox();
});
// key binding
window.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
if ( e.getCode() == KeyCode.N){
noButton.fire();
e.consume();
}
});
// bind enter key to yesButton
window.addEventHandler(KeyEvent.KEY_PRESSED, ev -> {
if (ev.getCode() == KeyCode.ENTER ){
yesButton.fire();
ev.consume();
}
});
window.addEventFilter(KeyEvent.KEY_PRESSED, ev ->{
if(ev.getCode()==KeyCode.ESCAPE){
ev.consume();
answer[0] = false;
answer[1] = false;
closeConfirmBox();
}
});
VBox layout = new VBox(20);
layout.setPadding(new Insets(20,5,20,5));
HBox bottomLayout = new HBox(50);
bottomLayout.setPadding(new Insets(20,5,20,5));
bottomLayout.getChildren().addAll(yesButton,noButton);
bottomLayout.setAlignment(Pos.CENTER);
layout.getChildren().addAll(label,bottomLayout);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout);
window.setScene(scene);
window.showAndWait();
return answer;
}
public static void closeConfirmBox(){
window.close();
}
}
Within my controller class, this is how I designed my MenuItem menuItemExit.
menuItemExit.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
//System.out.println("set stage" + primaryStage);
boolean[] answer;
boolean needToSave = false;
boolean closeApplication = false;
if(saved.get() == false){
answer = ConfirmBox.displayWarning("Warning", "Do you want to save your stuff?");
needToSave = answer[0];
closeApplication = answer[1];
}
if(needToSave == true){
menuItemSave.fire();
}
if(closeApplication== true){
Platform.runLater(new Runnable() {
public void run() {
close();
}
});
}
}
});
primaryStage.setOnCloseRequest(e -> {
e.consume();
menuItemExit.fire();
});
menuItemExit.setAccelerator(new KeyCodeCombination(KeyCode.E, KeyCombination.META_DOWN));
public void close(){
this.primaryStage.close();
}

JavaFX Alert Dialog Cancel Button

I made a JavaFX alert dialog box to prompt the user, asking if they want to save the output from the console before closing the application.
I have the yes and no options taken care of. If the user clicks cancel, I want it to just close the dialog box and leave everything open. As of right now, if I hit cancel it will close the GUI.
Here is my code for overriding the close button on the GUI.
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
#Override
public void handle(WindowEvent event)
{
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Warning");
alert.setHeaderText("Would You Like To Save Your Console Output?");
alert.setContentText("Please choose an option.");
ButtonType yesButton = new ButtonType("Yes");
ButtonType noButton = new ButtonType("No");
ButtonType cancelButton = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(yesButton, noButton, cancelButton);
Optional<ButtonType> result = alert.showAndWait();
if(result.get() == yesButton)
{
Main.setConsoleVisible();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
else if(result.get() == noButton)
{
System.exit(0);
}
else if(result.get() == cancelButton)
{
}
}
});
Both in "yesButton" and "cancelButton" if-blocks consume the CloseRequest WindowEvent:
else if(result.get() == cancelButton)
{
event.consume();
}
Use Platform.exit() instead of System.exit(0).
Use primaryStage.close(); instead of System.exit(0);
From the documentation for onCloseRequest:
Called when there is an external request to close this Window. The installed event handler can prevent window closing by consuming the received event.
Be aware that result.get() will throw an exception if the user closes the alert dialog without pressing any buttons. The Dialog documentation explains this thoroughly.

Categories

Resources