Creating a Singleton Controller class in JavaFX

做~自己de王妃 提交于 2019-12-12 01:41:49

问题


I am running into issues getting the below code to execute. All of it works except for the part in the Prompter that says This is my issue area. In that area i need to return the value of controller.getNoun().getText(); which works fine but returns null because i cant figure out how to call controller without initializing it. I tried a Singleton class based on another thread on this site but Controller never got initialized until i called it here so my Noun value was still getting nulled out.. My sole goal with this post is to get the value from the Noun Textfield and plug it in to the story the user has entered. What is your story? Use #noun# etc as placeholders for prompted words. should become What is your story? Use TextField Value etc as placeholders for prompted words.

package sample;

import java.util.*;

public class Prompter {
    private String finalStory;
    private Controller mController;

    public String getFinalStory() {
        return finalStory;
    }

    public void run (Template tmpl) {
        List<String> blanks;
            blanks = promptForWords(tmpl);
        //System.out.printf("%s", tmpl.render(blanks));
        finalStory = tmpl.render(blanks);
    }

    private List<String> promptForWords(Template tmpl) {
        List<String> words = new ArrayList<>();
        String word = "THIS IS MY ISSUE AREA";
        words.add(word);
        return words;
    }
}

package sample;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;

public class Controller {
    @FXML
    private TextField noun;
    @FXML
    private TextField age;
    @FXML
    private Text results;
    @FXML
    private HBox showWords;
    @FXML
    private HBox validateAge;
    @FXML
    private Button buttonFour;
    @FXML
    private TextArea treeStory;
    @FXML
    private Button buttonTwo;

    public int getAge() {
        return Integer.parseInt(age.getText());
    }

    public TextArea getTreeStory() {
        return treeStory;
    }

    public TextField getNoun() {
        return noun;
    }

    private String getToYoung() {
        return "Sorry you must be at least 13 to use this program.";
    }

    public void handleAge() {
        if (getAge() <= 12) {
            validateAge.setVisible(false);
            results.setText(getToYoung());
            new TimedExit();
        } else {
            validateAge.setVisible(false);
            treeStory.setVisible(true);
            buttonTwo.setVisible(true);
        }
    }

    public void handleStory() {
        showWords.setVisible(true);
        buttonFour.setVisible(true);
        treeStory.setVisible(false);
        buttonTwo.setVisible(false);
    }


    public void handleResults() {
        Prompter prompter = new Prompter();
        String story = getTreeStory().getText();
        Template tmpl = new Template(story);
        prompter.run(tmpl);
        results.setText(prompter.getFinalStory());
        showWords.setVisible(false);
        buttonFour.setVisible(false);
    }


}

回答1:


First, it's a really bad idea to expose controls from your controller. If you want to change, e.g. from a TextField to a TextArea, you will have a really difficult time doing so if the controls are publicly exposed. They should be considered implementation details of the view-controller pair. So I would expose only the data, e.g.

public class Controller {

    // ...

    public String getNoun() {
        return noun.getText();
    }

    // and if you need it:
    public void setNoun(String noun) {
        this.noun.setText(noun);
    }

    // ...
}

As for accessing the controller, surely all you need is to pass a reference to it to your Prompter class:

public class Prompter {
    private String finalStory;
    private Controller mController;

    public Prompter(Controller controller) {
        this.mController = controller ;
    }

    // ...

    private List<String> promptForWords(Template tmpl) {
        List<String> words = new ArrayList<>();
        String word = mController.getNoun();
        words.add(word);
        return words;
    }    

}

and then

public class Controller {

    // existing code...

    public void handleResults() {
        Prompter prompter = new Prompter(this);
        String story = getTreeStory().getText();
        Template tmpl = new Template(story);
        prompter.run(tmpl);
        results.setText(prompter.getFinalStory());
        showWords.setVisible(false);
        buttonFour.setVisible(false);
    }

}

Of course, if all you really need is the noun, you could just pass that to the Prompter instead:

public class Prompter {
    private String finalStory;

    public String getFinalStory() {
        return finalStory;
    }

    public void run (Template tmpl, String noun) {
        List<String> blanks;
        blanks = promptForWords(tmpl, noun);
        //System.out.printf("%s", tmpl.render(blanks));
        finalStory = tmpl.render(blanks);
    }

    private List<String> promptForWords(Template tmpl, String word) {
        List<String> words = new ArrayList<>();
        words.add(word);
        return words;
    }
}

and then just

public void handleResults() {
    Prompter prompter = new Prompter();
    String story = getTreeStory().getText();
    Template tmpl = new Template(story);
    prompter.run(tmpl, noun.getText());
    results.setText(prompter.getFinalStory());
    showWords.setVisible(false);
    buttonFour.setVisible(false);
}

A "singleton controller" (in this context) is an oxymoron, imho.



来源:https://stackoverflow.com/questions/35565917/creating-a-singleton-controller-class-in-javafx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!