问题
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