Issue
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:
- print two random generated integers
- let me insert the fraction of those two numbers
- print statement whether my insertet answer was correct or not
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!
Solution
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.
Answered By - fabian
Answer Checked By - Mary Flores (JavaFixing Volunteer)