Reputation: 3
I actually want to make OK button respond only when all the field in dialog are filled. And I also do not prefer to disable OK button.
This is the method from MainController that sets Dialog:
public void showItemDialog(){
Dialog<ButtonType> dialog = new Dialog<>();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("todoItemDialog.fxml"));
try {
dialog.getDialogPane().setContent(fxmlLoader.load());
} catch (IOException e){
System.out.println("Couldn't load Dialog");
}
dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
Optional<ButtonType> result = dialog.showAndWait();
if(result.isPresent() && result.get() == ButtonType.OK){
DialogController controller = fxmlLoader.getController();
controller.processResults();
}
}
And this is my DialogController class:
public class DialogController {
@FXML
private TextField descriptionTextField;
@FXML
private TextArea detailsTextArea;
@FXML
private DatePicker deadlinePicker;
@FXML
private DialogPane dialogPaneId;
public void processResults(){
String description = descriptionTextField.getText();
String details = detailsTextArea.getText();
LocalDate date = deadlinePicker.getValue();
TodoData.getInstance().addTodoItem(new TodoItem(description, details, date));
}
public boolean areFieldsEmpty(){
//checks if fields are empty...
return (descriptionTextField.getText().trim().isEmpty() || detailsTextArea.getText().trim().isEmpty() ||
deadlinePicker.getValue() == null);
}
}
Now, I think that the EventHandler for OK button should look something like this:
Button okButton = (Button) dialogPaneId.lookupButton(ButtonType.OK);
okButton.addEventFilter(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("was here");
if(areFieldsEmpty()){
event.consume();
}
}
});
But this is not working in MainController class Or in DialogController class (shows NullPointerException). I am very new to JavaFX, also I searched it a lot here but couldnt find any specific result. Thanks in advance.
Upvotes: 0
Views: 1272
Reputation: 1708
I think in this case you should not work with the Dialog functionality. Here is a small example how it can be done:
MainController Class:
package sample;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class MainController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
//...
}
@FXML
public void handleShowDialogBtnClick(ActionEvent event) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ToDoItem.fxml"));
Parent root = null;
try {
root = loader.load();
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
if (root == null) return;
Stage toDoItemStage = new Stage();
toDoItemStage.setTitle("My Dialog Title");
toDoItemStage.setAlwaysOnTop(true);
ToDoItemController toDoItemController = loader.getController();
toDoItemStage.setScene(new Scene(root));
toDoItemStage.initOwner((((Button) event.getSource()).getScene().getWindow()));
toDoItemController.setStage(toDoItemStage);
toDoItemStage.setOnCloseRequest(e -> toDoItemController.removeController());
toDoItemStage.show();
}
}
Main FXML File:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<Button onAction="#handleShowDialogBtnClick" text="Show Dialog" xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainController"/>
ToDoItemController Class:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.LoadException;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class ToDoItemController {
@FXML
private TextField
descriptionTextField;
@FXML
private DatePicker
deadlineDatePicker;
@FXML
private TextArea
detailsTextArea;
private Stage toDoItemStage;
private static ToDoItemController toDoItemController;
public ToDoItemController() throws LoadException {
if (toDoItemController == null) toDoItemController = this;
else throw new LoadException("Singleton FXML");
}
@FXML
public void handleOkayBtnClick() {
if (descriptionTextField.getText().trim().isEmpty()
|| detailsTextArea.getText().trim().isEmpty()
|| deadlineDatePicker.getValue() == null) {
Alert alert = new Alert(Alert.AlertType.ERROR, "Some information is missing.", ButtonType.OK);
alert.initOwner(toDoItemStage);
alert.showAndWait();
} else {
TodoData.getInstance().addTodoItem(new TodoItem(description.get(), details.get(), deadline.get()));
closeStage();
}
}
@FXML
public void handleCancelBtnClick() {
closeStage();
}
void setStage(Stage toDoItemStage) {
this.toDoItemStage = toDoItemStage;
}
void removeController() {
toDoItemController = null;
}
private void closeStage() {
removeController();
toDoItemStage.close();
}
}
ToDoItem FXML File:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<GridPane fx:id="rootGridPane" hgap="3.0" vgap="3.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="sample.ToDoItemController">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" />
<ColumnConstraints hgrow="NEVER" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" vgrow="ALWAYS" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<HBox GridPane.columnSpan="2">
<children>
<Label text="My Custom Dialog">
<font>
<Font size="24.0" />
</font>
</Label>
</children>
</HBox>
<Label text="Description:" GridPane.rowIndex="1" />
<TextField fx:id="descriptionTextField" GridPane.rowIndex="2" />
<Label text="Details:" GridPane.rowIndex="3" />
<TextArea fx:id="detailsTextArea" GridPane.columnSpan="2" GridPane.rowIndex="4" />
<Label text="Deadline:" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<DatePicker fx:id="deadlineDatePicker" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<HBox alignment="CENTER_RIGHT" spacing="10.0" GridPane.columnSpan="2" GridPane.rowIndex="5">
<children>
<Button defaultButton="true" onAction="#handleOkayBtnClick" prefWidth="70.0" text="OK" />
<Button cancelButton="true" onAction="#handleCancelBtnClick" prefWidth="70.0" text="Cancel" />
</children>
</HBox>
</children>
<padding>
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
</padding>
</GridPane>
MainApplication Class:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 1