Warm tip: This article is reproduced from stackoverflow.com, please click
debugging java javafx

How to fix this bug in JavaFX that the value changes?

发布于 2020-04-10 16:06:57

I've got a small bug in JavaFX and need help. I want to generate a random number within a bound that the user can choose. I chose a slider and get the value in the controller when the user changes it and set it to the bound of the random number. But when I start to check if some user input is higher or lower than this number the bound goes back to 100 (which is the default value when the user doesn't change the slider). Here is some code:

Main:

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 {
    public static Stage pStage;

    public static Parent root1;
    public static Parent root2;
    public static Parent root3;

    public static Scene scene1;
    public static Scene scene2;
    public static Scene scene3;

    public Main() {
    }

    @Override
    public void start(Stage stage) throws Exception {

        pStage = stage;

        root1 = FXMLLoader.load(getClass().getResource("scene1.fxml"));
        root2 = FXMLLoader.load(getClass().getResource("scene2.fxml"));
        root3 = FXMLLoader.load(getClass().getResource("scene3.fxml"));


        scene1 = new Scene(root1);
        scene2 = new Scene(root2);
        scene3 = new Scene(root3);

        stage.setScene(scene1);
        stage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

Controller:

import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;

public class Controller {

    GuessingGame guessingGame = new GuessingGame();
                    //Hier die Zufallszahl hinsetzen und auf 100 und drüben dann mit Setter und Getter abgreifen

    @FXML
    private TextField textfield;
    @FXML
    private Label countText;
    @FXML
    public Label notification;
    @FXML
    public Label textBetween;
    @FXML
    public Slider sliderSettings;

    int currentNumber;

    @FXML
    public void clickedOnExit() {
        System.exit(1);
    }
    @FXML
    public void clickedOnSettings() {
        Main.pStage.setScene(Main.scene3);
        System.out.println(guessingGame.getRandomBound());
    }
    @FXML
    public void sliderSetValue() {
        guessingGame.setRandomBound((int) sliderSettings.getValue());
        System.out.println(guessingGame.getRandomBound());
    }
    @FXML
    public void clickedBackToMenuSettings() {
        Main.pStage.setScene(Main.scene1);
        System.out.println(guessingGame.getRandomBound());
    }
    @FXML
    public void clickedOnPlay() {
        Main.pStage.setScene(Main.scene2);  //Beim wechsel zu szene 2 wird der wert wieder auf 100 gesetzt
        System.out.println(guessingGame.getRandomBound());
    }
    @FXML
    public void clickedBackToMenu() {
        Main.pStage.setScene(Main.scene1);
    }
    @FXML
    public void enteredTextfield() {

        System.out.println(guessingGame.getNumber());

        currentNumber = Integer.parseInt(textfield.getText());

        GuessingGame.Result checkNumber;

        checkNumber = guessingGame.evaluateEnteredNumber(currentNumber);

        if (checkNumber == GuessingGame.Result.HIGHER) {
            notification.setText("HIGHER");
        }
        ;
        if (checkNumber == GuessingGame.Result.LOWER) {
            notification.setText("LOWER");
        }
        ;
        if (checkNumber == GuessingGame.Result.EQUALS) {
            notification.setText("YOU GOT IT!");
            textBetween.setText("Congratulations! The number was: " + guessingGame.getNumber());
        }
        ;
        textfield.clear();
        countText.setText("" + guessingGame.getCounter());  //Gibts ihr eine bessere Lösung?
    }
}

The Game:

import java.util.Random;

public class GuessingGame {

    Random rand = new Random();

    private int number;
    private int counter;
    //Variable die maxhöhe der Zufallszahl am Anfang auf 100 Stand
    private int randomBound = 100;

    public enum Result {
        EQUALS, HIGHER, LOWER
    }

    //Random number muss noch implementiert werden, sodass sie im Bound steht
    public GuessingGame() {
        getNumberToGuess();             //Konstruktor
    }

    public int getNumberToGuess() {
        this.number = rand.nextInt(randomBound);                 //im bound muss der wert vom slide sein
        return number;
    }

    //Methode für das Spielgeschehen gibt Das Ergebnis wieder obs höher/tiefer/gleich ist
    public Result evaluateEnteredNumber(int enteredNumber) {
        Result result;

        counter++;

        if (number > enteredNumber) {
            result = Result.HIGHER;
        } else if (number < enteredNumber) {
            result = Result.LOWER;
        } else {
            result = Result.EQUALS;
        }
        return result;
    }


    //----------------------------------------------------//
    //Getter und Setter//

    //Setter und Getter für die Zufallszahl
    public void setNumber(int  newNumber) {
        this.number = newNumber;
    }
    public int getNumber() {
        return number;
    }
    //Setter und Getter für den Versuchzähler
    public void setCounter(int newCounter) {
        this.counter = newCounter;
    }
    public int getCounter() {
        return counter;
    }
    //Setter und Getter für Die maxhöhe der Zufallszahl
    public void setRandomBound(int newRandomBound) {
        randomBound = newRandomBound;
    }
    public int getRandomBound() {
        return randomBound;
    }
}

Scene 1:

<?xml version="1.0" encoding="UTF-8"?>

        <?import javafx.scene.control.Button?>
        <?import javafx.scene.control.Label?>
        <?import javafx.scene.layout.AnchorPane?>
        <?import javafx.scene.text.Font?>


<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
   <Button fx:id="exitButton" layoutX="505.0" layoutY="349.0" mnemonicParsing="false" onAction="#clickedOnExit" prefHeight="37.0" prefWidth="81.0" text="Exit" />
   <Button fx:id="playButton" layoutX="237.0" layoutY="163.0" mnemonicParsing="false" onAction="#clickedOnPlay" prefHeight="37.0" prefWidth="126.0" text="Play" />
   <Button fx:id="settingsButton" layoutX="237.0" layoutY="213.0" mnemonicParsing="false" onAction="#clickedOnSettings" prefHeight="37.0" prefWidth="126.0" text="Settings" />
   <Label layoutX="66.0" layoutY="14.0" prefHeight="117.0" prefWidth="469.0" text="GUESSING GAME">
      <font>
         <Font name="Arial Black" size="49.0" />
      </font>
   </Label>
</children>
</AnchorPane>

Scene 2

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <Label layoutX="72.0" prefHeight="20.0" prefWidth="457.0" text="GUESSING GAME">
         <font>
            <Font name="Arial Black" size="48.0" />
         </font>
      </Label>
      <Label layoutX="72.0" layoutY="187.0" text="Your guess:">
         <font>
            <Font name="Arial" size="22.0" />
         </font>
      </Label>
      <Label layoutX="395.0" layoutY="187.0" text="Attempts:">
         <font>
            <Font name="Arial" size="22.0" />
         </font>
      </Label>
      <TextField fx:id="textfield" layoutX="197.0" layoutY="188.0" onAction="#enteredTextfield" prefHeight="25.0" prefWidth="66.0" />
      <Label fx:id="countText" layoutX="496.0" layoutY="188.0" text="0">
         <font>
            <Font name="Arial" size="22.0" />
         </font>
      </Label>
      <Label layoutX="48.0" layoutY="71.0" text="My number is a random number up to 100! Try to guess it!">
         <font>
            <Font name="Arial Black" size="16.0" />
         </font>
      </Label>
      <Label fx:id="notification" layoutX="221.0" layoutY="120.0" text="Type a number!">
         <font>
            <Font name="Arial Black" size="22.0" />
         </font>
      </Label>
      <Label fx:id="textBetween" layoutX="72.0" layoutY="272.0" prefHeight="26.0" prefWidth="356.0" text="Your number is between 0 and 100">
         <font>
            <Font name="Arial Black" size="17.0" />
         </font>
      </Label>
      <Button fx:id="backToMenu" layoutX="485.0" layoutY="361.0" mnemonicParsing="false" onAction="#clickedBackToMenu" text="Back to Menu" />
   </children>
</AnchorPane>

Scene 3:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <Slider fx:id="sliderSettings" layoutY="200.0" max="1000.0" minorTickCount="4" onMouseReleased="#sliderSetValue" prefHeight="38.0" prefWidth="592.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="100.0" />
      <Label layoutX="4.0" layoutY="117.0" prefHeight="47.0" prefWidth="592.0" text="How High can the number you want to guess be?">
         <font>
            <Font name="Arial Black" size="22.0" />
         </font>
      </Label>
      <Button fx:id="backToMenuSettings" layoutX="497.0" layoutY="361.0" mnemonicParsing="false" onAction="#clickedBackToMenuSettings" text="Back to Menu" />
   </children>
</AnchorPane>

The problem now is: The random Bound number changes when you interact with the Slider but when you click on the Play Button the random bound goes back to 100 and also generates a number to 100... and not the amount the user decided to have (Slider)

Questioner
Mindmax
Viewed
88
jayaram S 2020-02-02 05:53

So add this to your Controller

 @FXML
public void initialize() {
    System.out.println(guessingGame);
}

In your output you will notice this

sample.GuessingGame@29794acb
sample.GuessingGame@6cc12f4f
sample.GuessingGame@757b7ff5

Essentially, since the same controller is configured in the fxml for each of the scenes, each will get its own instance and therefore its own instance of the GuessingGame.

There are a few ways to solve this - my personal recommendation would be to keep your controllers separated since fxml controllers can get out of hand quickly.

Either way, have the GuessingGame initialized outside of the controller and pass it in.

You could, of course, keep the single controller model and pass that into all three scenes. But then you will not be about to configure the actions into the fxml.

Hope this helps.