StringProperty和Switch语句Javafx

时间:2017-07-17 05:57:35

标签: button javafx properties switch-statement listener

我的大脑即将爆炸。我是java的新手,到目前为止自学成才,但我真的想让这段代码工作。我也不是最了解java文档的人。

我正在尝试创建一个游戏循环,用户可以通过单击按钮自由遍历switch语句。

但是,之前,当我的gameloop方法被调用时,它使用当前设置运行代码,而不让我使用按钮来遍历switch语句。

我认为这是因为我的“选择”变量没有附加动作监听器(因为监听器会使程序坐在项目上,等待某事发生?)。不幸的是,我的选择变量是一个String变量,你不能将actionlistener附加到String变量。 现在我尝试使用StringProperty类创建一个字符串对象,以便能够将动作侦听器附加到它。

但现在我甚至不知道如何将StringProperty与switch语句一起使用,我只是觉得我在错误的轨道上。

我想要完成的是否有意义? 有人可以帮我创建一个游戏循环,用户可以通过单击按钮自由遍历switch语句吗? ♥♥♥!

这是我的代码:

控制器:

package sample;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
import static java.lang.System.out;

public class Controller implements Initializable {

    public String question;
    public StringProperty choice = new SimpleStringProperty(this, "choice", "");

    // this code starts when the XML file is loaded.
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        question = "0";
        gameloop();

    } public String getChoice() {
        return choice.get();
    }

    public StringProperty choiceProperty() {
        return choice;
    }

    public void setChoice(String choice) {
        this.choice.set(choice);
    }
    // public String choice = "";

    public Controller() {
    }

    // Here are the buttons trying to add an actionlistener to the choice object.
    // Maybe wrong path to go
    @FXML
    public void button1() {
        choiceProperty().addListener((v, oldValue, newValue) ->{setChoice("c1");});


    }

    @FXML
    public void button2() {
        choiceProperty().addListener((v, oldValue, newValue) ->{setChoice("c2");});
        out.println(choice); //think this prints out where it is stored in the memory

    }

    @FXML
    public void button3() {
        choiceProperty().addListener((v, oldValue, newValue) ->{setChoice("c3");});
        out.println(choice);

    }

    //this block of code does not work because of the switch (choice) statement.
    //Where "c1","c2","c3" have incompatible a type error.
    public void gameloop() {
        switch (question) {
            case "0":
                switch (choice) {
                    case "c1":
                        out.println("you chose 1");
                        question = "1";
                        break;
                    case "c2":
                        out.println("you chose 2");
                        break;
                    case "c3":
                        out.println("you chose 3");
                        break;
                }
            case "1":
                switch (choice) {
                    case "c1":
                        out.println("you chose a");
                        question = "0";
                        break;
                    case "c2":
                        out.println("you chose b");
                        break;
                    case "c3":
                        out.println("you chose c");
                        break;
                }
        }
    }
}

FXML:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
    <children>
        <BorderPane layoutX="163.0" layoutY="82.0" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: black;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
            <bottom>
                <GridPane BorderPane.alignment="CENTER">
                    <columnConstraints>
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                    </columnConstraints>
                    <rowConstraints>
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                    </rowConstraints>
                    <children>
                        <Button fx:id="button1"  maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button1" onMouseClicked="#button1" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" />
                        <Button fx:id="button2" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button2" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="1" />
                        <Button fx:id="button3" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button3" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="2" />
                    </children>
                </GridPane>
            </bottom>
            <center>
                <TextArea fx:id="textArea" editable="false" prefHeight="200.0" prefWidth="200.0" promptText="..." style="-fx-border-color: grey;" wrapText="true" BorderPane.alignment="CENTER" />
            </center>
            <top>
                <Label fx:id="label" text="Chapter 1" textFill="WHITE" BorderPane.alignment="CENTER" />
            </top>
            <left>
                <ImageView fx:id="image1" fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
            </left>
            <right>
                <ImageView fx:id="image2" fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
            </right></BorderPane>
    </children>
</AnchorPane>

主:

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("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 800, 500));
        primaryStage.show();
    }


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

1 个答案:

答案 0 :(得分:1)

在按钮事件处理程序中注册侦听器是无稽之谈。使用侦听器来修改他们听到的属性更糟糕。传递属性作为switch的参数甚至都不会编译。

在这种情况下,进行此项工作的最小修改是在initialize方法中注册单个侦听器,从此侦听器调用gameloop方法并使用存储在属性中的值作为参数开关。

@Override
public void initialize(URL location, ResourceBundle resources) {
    question = "0";
    gameloop();

    choiceProperty().addListener((observable, oldValue, newValue) -> gameloop());
}

...

@FXML
private void button1() {
    setChoice("c1");
}

...

public void gameloop() { 
    switch (question) {
        case "0":
            switch (choice.get()) {
                ...
            }
        ...
    }
}

但请注意,您将以这种方式获得大量重复代码。最好提出一种数据结构来存储游戏数据,而不是硬编码一切。

E.g。

public class GameData {

    private final ReadOnlyObjectWrapper<Question> question;

    public ReadOnlyObjectProperty<Question> questionProperty() {
        return question.getReadOnlyProperty();
    }

    public Question getQuestion() {
        return question.get();
    }

    private final Map<Integer, Question> questions;

    public Map<Integer, Question> getQuestions() {
        return questions;
    }

    public GameData(int initialQuestion, Map<Integer, Question> questions) {
        this.questions = questions;
        this.question = new ReadOnlyObjectWrapper(questions.get(initialQuestion));
    }

    public void activateChoice(Choice choice) {
        question.set(questions.get(choice.getNextQuestion()));
    }
}
public class Question {

    private final String text;

    public String getText() {
        return text;
    }

    public Question(String text, Choice... choices) {
        this.text = text;
        this.choices = Collections.unmodifiableList(new ArrayList(Arrays.asList(choices)));
    }

    private final List<Choice> choices;

    public List<Choice> getChoices() {
        return choices;
    }

}
public class Choice {

    private final String text;
    private final int nextQuestion;

    public Choice(int nextQuestion, String text) {
        this.text = text;
        this.nextQuestion = nextQuestion;
    }

    public String getText() {
        return text;
    }

    public int getNextQuestion() {
        return nextQuestion;
    }

}
public class Controller {

    private GameData gameData;

    @FXML
    private Button button1, button2, button3;

    private Button[] buttons;

    @FXML
    private void initialize() {
        buttons = new Button[]{button1, button2, button3};
    }

    public void setGameData(GameData gameData) {
        this.gameData = gameData;
        gameData.questionProperty().addListener((observable, oldValue, newValue) -> setQuestion(newValue));
        setQuestion(gameData.getQuestion());
    }

    private void setQuestion(Question question) {
        System.out.println(question.getText());
        for (Button b : buttons) {
            b.setVisible(false);
        }

        for (int i = 0, max = Math.min(buttons.length, question.getChoices().size()); i < max; i++) {
            Button b = buttons[i];
            Choice c = question.getChoices().get(i);
            b.setUserData(c);
            b.setText(c.getText());
            b.setVisible(true);
        }
    }

    @FXML
    private void button(ActionEvent evt) {
        Node source = (Node) evt.getSource();
        Choice choice = (Choice) source.getUserData();

        out.println("You've chosen " + choice.getText());

        gameData.activateChoice(choice);
    }

}
...
<Button fx:id="button1"  maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" />
<Button fx:id="button2" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="1" />
<Button fx:id="button3" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="2" />
...
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();

Map<Integer, Question> questions = new HashMap<>();

questions.put(0, new Question("0",
        new Choice(1, "1"),
        new Choice(0, "2"),
        new Choice(0, "3")
));
questions.put(1, new Question("1",
        new Choice(0, "a"),
        new Choice(1, "b"),
        new Choice(1, "c")
));

GameData data = new GameData(0, questions);

loader.<Controller>getController().setGameData(data);