0

I have a programm with a TextArea which enables the user to add notes to a particular verse number. Every verse number has a dedicated note entry. The values for the verses and the notes are loaded from a SQLite database. The text is loaded correctly and the "Save" ("Speichern") button is working.

I want to show an alert window, which displays the question "Do you want to save the text?", when the user has changed the TextArea and not clicked on the "Save" button. I have tried to add a listener for the TextArea having a variable , but the problem is, that it detects a change every time the Notes Text Area is updated.

My idea is to save the text of the Notes Text Area to a String or HashMap, after the verse is loaded. There should be a respective String or a HashMap which saves the original notes. The String / HashMap should then be compared to the value of the listener, but only if the "Save" button hasn't been clicked on before closing the programm.

How do I achieve this?

This is how the relevant of the programm looks like.

This is the method which I am trying to change:

private void loadNotesFromPaliVerse() throws SQLException {


    // Check if a number has been selected
    Integer selectedNumber = comboBoxVerseNr.getValue();

    if (selectedNumber == null) {
        return;
    }

    if (selectedNumber.equals(previousSelectedNumber)) {
        return;
    }


    // Retrieve verse number based on comboBoxVerseNr

    String queryNote = DatabaseMethods.notesToPaliVerse(comboBoxVerseNr.getValue());


    try (PreparedStatement statement = connection.prepareStatement(queryNote)) {

        try (ResultSet resultSet = statement.executeQuery()) {
            if (resultSet.next()) {

                // Retrieve text value from the table
                String textValue = resultSet.getString("Notes");

                // Insert text into TextArea
                notesTextArea.setText(textValue);




            } else {

                // No corresponding entry found, clear the TextArea
                notesTextArea.clear();
              

            }
        }
    }
}
Jacob J.
  • 3
  • 6
  • You have already outlined a possible solution. I am not sure where exactly you see a problem. – Petra Minaler Jun 13 '23 at 13:53
  • 2
    *but the problem is, that it detects a change every time the Notes Text Area is updated.* - not understanding why that is a problem? Just keep setting the variable to "true" every time a change is made. You only need to test the variable when the user invokes a action that requires the text area to be saved. – camickr Jun 13 '23 at 14:26
  • @camickr The problem is, that a change is detetected even though just the relevant note is loaded. There should only be a detection of a change if the text is in the note text area is manually changed by the user. – Jacob J. Jun 13 '23 at 15:00
  • 2
    So you need to add your "change listener" AFTER the code is loaded. Or you need to reset the boolean variable to false AFTER the code is loaded. Can't give any more specific advice because we don't know what GUI toolkit you are using. – camickr Jun 13 '23 at 15:53
  • I tried but it is not working. I am using JavaFX. – Jacob J. Jun 13 '23 at 16:59
  • 1
    I don't use JavaFX so I can't help. Post an [mre] demonstrating the problem for others to see what you are doing. – camickr Jun 13 '23 at 20:56
  • show code its easier to help / fix problem – Anon Jun 14 '23 at 08:49
  • @Anon I have added code to my question. – Jacob J. Jun 14 '23 at 09:19
  • the method you added has nothing to do with saving its only retrieving info? – Anon Jun 14 '23 at 14:50
  • 1
    The code you posted doesn't seem to have anything at all to do with the problem you describe. Please post a [mre] as requested. I don't see a way this question can be answered without one. – James_D Jun 14 '23 at 15:16

1 Answers1

1

My guess is that you are looking for primaryStage.setOnCloseRequest. Here is an example app. This app uses the Button's style to determine if a save needs to happen. You may choose to use a variable/property.


Main

import java.util.Optional;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TextArea;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class App extends Application {
    String originalText;
    
    public static void main(String[] args) {
        App.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        Button btnSave = new Button("Save");
        btnSave.setOnAction(event -> System.out.println("Saving text!!!"));
        
        originalText = loadOriginalText();        
        TextArea textArea = new TextArea(originalText);
        textArea.setWrapText(true);
        textArea.textProperty().addListener((obs, oldText, newText) ->{
            if(newText != null)
            {
                if(!originalText.equals(newText))
                {
                    btnSave.setStyle("-fx-border-color: red;");
                }
                else
                {
                    btnSave.setStyle(null);
                }                
            }
        });        
        
        VBox root = new VBox(new StackPane(textArea), new StackPane(btnSave));
        Scene scene = new Scene(root, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
        
        primaryStage.setOnCloseRequest((windowEvent)->{
            if(btnSave.getStyle().equals("-fx-border-color: red;"))
            {
                Alert alert = new Alert(AlertType.CONFIRMATION);
                alert.setTitle("Confirmation Dialog");
                alert.setHeaderText("Do you want to save the text before ending the app?");
                alert.setContentText("Press 'Ok' to close the app with save. Press 'Cancel' to close the app with out save.");

                Optional<ButtonType> result = alert.showAndWait();
                if (result.get() == ButtonType.OK)
                {
                   btnSave.fire();
                   
                } 
                
                Platform.exit();
            }
        });        
    }
    
    public String loadOriginalText()
    {
        return """
               Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
               """;
    }
}

enter image description here


Note: Doing this in FXML will require the Main have access to the save Button. This is something I would do in the Main using ideas from MVC or passing parameters. The code below does not work as-is. I freestyle it without an IDE.

basically something like

import java.util.Optional;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class App extends Application {
    Button btnSave;
    
    public static void main(String[] args) {
        App.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        
        FXMLLoader yourControllerLoader = new FXMLLoader(getClass().getResource("yourfxml.fxml"));
        YourFxmlRootNodeType fxmlRoot = yourControllerLoader.load();
        YourController yourController = yourControllerLoader.getController();
        
        Button btnSave = yourController.getSaveButton();        
        
        Scene scene = new Scene(fxmlRoot, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
        
        primaryStage.setOnCloseRequest((windowEvent)->{
            if(btnSave.getStyle().equals("-fx-border-color: red;"))
            {
                Alert alert = new Alert(AlertType.CONFIRMATION);
                alert.setTitle("Confirmation Dialog");
                alert.setHeaderText("Do you want to save the text before ending the app?");
                alert.setContentText("Press 'Ok' to close the app with save. Press 'Cancel' to close the app with out save.");

                Optional<ButtonType> result = alert.showAndWait();
                if (result.get() == ButtonType.OK)
                {
                   btnSave.fire();
                   
                } 
                
                Platform.exit();
            }
        });        
    }
}
SedJ601
  • 12,173
  • 3
  • 41
  • 59