Zest
Zest

Reputation: 127

How can i add a reset/restart button to my JavaFX Application in order to reset my scene?

I am about to finish my very first JavaFX application, which is not much more than a simple calculation tool with a GUI. The program does the following:

However, i didn't manage to figure out how to implement a "Reset" or "Restart"-Button in order to avoid closing the programm each time.

This is my code:

package sample;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;


import java.io.InputStream;

public class Game extends Application implements EventHandler<ActionEvent> {

    private Button button;

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Pot Odds Trainer");

        Class<?> genericClass = this.getClass();
        InputStream input1 = genericClass.getResourceAsStream("img/chipsGREEN.png");
        InputStream input2 = genericClass.getResourceAsStream("img/chipsREDsmall.png");
        InputStream input3 = genericClass.getResourceAsStream("img/01ACE.png");
        InputStream input4 = genericClass.getResourceAsStream("img/01ACE.png");
        InputStream input5 = genericClass.getResourceAsStream("img/chipsBLUE03small.png");
        InputStream input6 = genericClass.getResourceAsStream("img/chipsGREENstack.png");

        Image image1 = new Image(input1);
        ImageView imageView1 = new ImageView(image1);
        Image image2 = new Image(input2);
        ImageView redChips = new ImageView(image2);
        Image image3 = new Image(input3);
        ImageView imageView3 = new ImageView(image3);
        Image image4 = new Image(input4);
        ImageView imageView4 = new ImageView(image4);
        Image image5 = new Image(input5);
        ImageView blueChipsStack = new ImageView(image5);
        Image image6 = new Image(input6);
        ImageView greenChipStack = new ImageView(image6);

        Button buttonRotate = new Button("Rotate");
        buttonRotate.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                double value = imageView1.getRotate();
                imageView1.setRotate(value + 30);
            }
        });

        button = new Button("Text of Button");

        Button buttonRestart = new Button("Restart");
        buttonRestart.setOnAction((ActionEvent event) -> {
            ((Node) (event.getSource())).getScene().getWindow().hide();
        });

        button.setOnAction(this);

        GridPane gridPane = new GridPane();
        gridPane.setHgap(10);
        gridPane.setVgap(10);
        gridPane.setGridLinesVisible(false);

        int potSizeValue = Potsize.getPotSize();
        int betSizeValue = Potsize.getBetSize();
        int stackSizeValue = Potsize.getStackSize();

        Potsize potsize = new Potsize(potSizeValue);
        Potsize betsize = new Potsize(betSizeValue);
        Potsize stacksize = new Potsize(stackSizeValue);

        Label potsizeText = new Label("Der Pot liegt bei: ");
        Label betsizeText = new Label("Ein Call beträgt: ");
        Label stacksizeText = new Label("Dein Stack liegt bei: ");

        Label potOddsLabel = new Label("Pot Odds:");
        Label textConfirm = new Label();

        Button submitButton = new Button("Submit");
        TextField potOddsTextField = new TextField();
        potOddsTextField.setMaxWidth(50);
        submitButton.setOnAction(e ->
                {
                    textConfirm.setText(MyMath.checkOdds(potOddsTextField.getText(), (double) betSizeValue / (potSizeValue + betSizeValue)));
                }
        );

        Label potsizeLabel = new Label(potsize.toString());
        Label stacksizeLabel = new Label(stacksize.toString());
        Label betsizeLabel = new Label(betsize.toString());

        gridPane.add(button, 0, 0, 1, 1);
        gridPane.add(buttonRotate, 2, 3, 1, 1);
        gridPane.add(imageView1, 0, 2, 1, 1);
        gridPane.add(imageView3, 4, 3, 1, 1);
        gridPane.add(imageView4, 5, 3, 1, 1);
        gridPane.add(potsizeText, 4, 5, 2, 1);
        gridPane.add(betsizeText, 4, 6, 2, 1);
        gridPane.add(stacksizeText, 4, 7, 2, 1);
        gridPane.add(potsizeLabel, 6, 5, 2, 1);
        gridPane.add(betsizeLabel, 6, 6, 2, 1);
        gridPane.add(stacksizeLabel, 6, 7, 2, 1);
        gridPane.add(blueChipsStack, 8, 5, 1, 1);
        gridPane.add(redChips, 8, 6, 1, 1);
        gridPane.add(greenChipStack, 8, 7, 1, 1);
        gridPane.add(potOddsLabel, 4, 8, 2, 1);
        gridPane.add(potOddsTextField, 6, 8, 2, 1);
        gridPane.add(submitButton, 8, 8, 1, 1);
        gridPane.add(textConfirm, 4, 9, 2, 1);
        gridPane.add(buttonRestart, 4, 11, 2, 1);


        Scene scene = new Scene(gridPane, 650, 550);
        scene.getStylesheets().add(Main.class.getResource("css/styles.css").toExternalForm());

        primaryStage.setScene(scene);
        primaryStage.show();

    }

    @Override
    public void handle(ActionEvent event) {
        if (event.getSource() == button) {
            System.out.println("Ooooooo test");

        }
    }


}
This is my Main Class:

package sample;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import java.io.InputStream;
import java.util.concurrent.ThreadLocalRandom;

public class Main {
    public static void main(String[] args) {

        Game game = new Game();
        game.launch(Game.class, args);

    }
}
package sample;

import java.util.concurrent.ThreadLocalRandom;

public class Potsize {

    private int size;

    public Potsize(int size){
        this.size = size;
    }

    static public int getStackSize(){
        return (int)MyMath.round(ThreadLocalRandom.current().nextInt(100, 2500 + 1));
    }

    static public int getPotSize(){
        return (int)MyMath.round(ThreadLocalRandom.current().nextInt(100, 1000 + 1));
    }

    static public int getBetSize(){
        return (int)MyMath.round(MyMath.divide(getPotSize(),  ThreadLocalRandom.current().nextInt(2, 10 + 1)));
    }

    public void setPotSize(int size){
        this.size = size;
    }

    public void setBetSize(int size){
        this.size = size;
    }

    public void setStackSize(int size){
        this.size = size;
    }

    public String toString() {
        return ""+ size;
    }

}

I've read a lot of similar questions but unfortunately, none have helped me so far.

Currently i am having an ActionEvent on "buttonRestart" that closes my programm - however, that's not what i want. I'd like the Scene to simply reset/restart in order to have a "next try".

Can anyone help me?

Thanks so much!

Upvotes: 0

Views: 8607

Answers (3)

fabian
fabian

Reputation: 82491

There is no general way of doing this easily: The code could e.g. in some circumstances invoke Platform.exit and at that time it's not possible to prevent the GUI from shutting down.

Depending on the code in some cases passing a stage to the start method may work:

start(primaryStage);

or

primaryStage.hide();
start(new Stage());

But in general I recommend resetting the things changed in the scene to their original state:

private Label potsizeLabel;
private Label stacksizeLabel;
private Label betsizeLabel;

private void initPot() {
    int potSizeValue = Potsize.getPotSize();
    int betSizeValue = Potsize.getBetSize();
    int stackSizeValue = Potsize.getStackSize();

    Potsize potsize = new Potsize(potSizeValue);
    Potsize betsize = new Potsize(betSizeValue);
    Potsize stacksize = new Potsize(stackSizeValue);

    potsizeLabel.setText(potsize.toString());
    stacksizeLabel.setText(stacksize.toString());
    betsizeLabel.setText(betsize.toString());
}

@Override
public void start(Stage primaryStage) throws Exception {
    ...

    buttonRestart.setOnAction((ActionEvent event) -> {
        // change node properites that could have been modified to their's original states
        imageView1.setRotate(0);
        textConfirm.setText("");

        // redo Potsize thing
        initPot();
    });

    ...

    potsizeLabel = new Label();
    stacksizeLabel = new Label();
    betsizeLabel = new Label();

    initPot();

    ...

}

If the Potsize class contains a state in a static member, you also need to reset this (but it would be better to avoid this scenario in the first place; note that this could also prevent the first approaches from working properly).


I'm not sure about the responsibility of the Potsize class, but it's sole purpose (ignoring static members) currently seems to be to convert an int to a String which does not require creating an instance of that class; Integer.toString(potSizeValue) can be used, if the int is converted to a string containing it's decimal representation; otherwise a static method seems sufficient.

Upvotes: 2

ManLaw
ManLaw

Reputation: 115

The first two links provide StackOverflow source code posts on implementing refresh options for scenes. The last link concerns JavaFX multithreading from Oracle’s tutorials, an option you will likely need to consider if you don’t want to completely close your JavaFX application just to refresh a scene.

Restarting your application on-click. How to restart a JavaFX application when a button is clicked

Reloading JavaFX application How to reload an Application in JavaFX?

There might not be a quick solution to reloading a scene if your scene is in the main thread that contains your main JavaFX application. You should create a new thread and place the scene within this thread, stop the same thread update the scene as needed, and then launch a new thread with the updated scene. Here’s a link to concurrency (multithreading) with JavaFX.

Concurrency in JavaFX https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm

P.S. By the way, a couple of months ago I built a couple of JavaFX gui applications to take user file information and process the file. I, too, wanted to leave the application open but couldn’t and found the Oracle resources.

Upvotes: 0

Patrick Zamarian
Patrick Zamarian

Reputation: 276

I dont see your Potsize class but I think you have to reset this values

int potSizeValue = Potsize.getPotSize();
int betSizeValue = Potsize.getBetSize();
int stackSizeValue = Potsize.getStackSize();

Potsize potsize = new Potsize(potSizeValue);
Potsize betsize = new Potsize(betSizeValue);
Potsize stacksize = new Potsize(stackSizeValue);

And then refresh on GridPane

gridPane.add(potsizeLabel, 6, 5, 2, 1);
gridPane.add(betsizeLabel, 6, 6, 2, 1);
gridPane.add(stacksizeLabel, 6, 7, 2, 1);

Upvotes: 1

Related Questions