手动使用JavaFX Fire TextField ActionEvent编程

时间:2017-01-10 18:34:03

标签: java events javafx

我知道一些方法可以避免这种情况,比如在不同的节点中添加相同的ActionHandler:

        // Custom Event Handler
        EventHandler<ActionEvent> myHandler = e -> {

             //code

        };

        inputField.setOnAction(myHandler);

        // okButton
        okButton.setOnAction(myHandler);

但是我可以在Node类中看到一个方法fireEvent(Event)。问题是我有多个TextFields,当Button名为okButton被按下时我想要立即解雇他们。

怎么做?如果不是对你没有多大意义的东西,请说出于研究原因我想要它:)。

2 个答案:

答案 0 :(得分:2)

我真的没有看到这样做的任何正当理由:你基本上要求控制器在视图上调用用户事件,而不是像往常那样做并更新模型。

所以我想我能想到的最接近的事情就是这样。假设您(使用规范的JavaFX示例),Person类:

public class Person {

    private final StringProperty firstName = new SimpleStringProperty() ;
    private final StringProperty lastName = new SimpleStringProperty() ;
    private final StringProperty email = new SimpleStringProperty() ;

    public StringProperty firstNameProperty() {
        return firstName ;
    }

    public final String getFirstName() {
        return firstNameProperty().get();
    }

    public final void setFirstName(String firstName) {
        firstNameProperty().set(firstName);
    }

    // etc etc
}

然后是某种编辑。您可以在编辑器中创建映射,将每个文本字段映射到要执行的操作,然后向每个调用相应操作的文本字段注册单个事件处理程序。您的按钮可以遍历地图并调用所有操作:

public class PersonEditor {

     private TextField firstNameTextField ;
     private TextField lastNameTextField ;
     private TextField emailTextField ;

     private Button okButton ;


     public PersonEditor(Person person) {

         // create controls, do layout, etc etc...

         // map textfields to an action on the person:
         Map<TextField, Consumer<String>> actions = new HashMap<>();
         actions.put(firstNameTextField, person::setFirstName);             
         actions.put(lastNameTextField, person::setLastName);             
         actions.put(emailTextField, person::setEmail);

         // set individual event handlers on each text field:
         actions.entrySet().forEach(entry -> {
             TextField tf = entry.getKey();
             tf.setOnAction(e -> entry.getValue().accept(tf.getText()));
         });

         // event handler for button:
         okButton.setOnAction(e -> {
             // invoke action on each text field:
             actions.entrySet().forEach(entry -> entry.getValue().accept(entry.getKey().getText()));
             // do other stuff if needed...
         }

    }

}

答案 1 :(得分:2)

根据OP的要求,我正在添加我的评论作为答案。

您可以使用.fireEvent(new ActionEvent())触发TextField操作处理程序。

我完成此操作的方法是存储/获取所有TextField s,然后当按下Button时,迭代每一个.fireEvent(new ActionEvent());。下面的小控制器示例。 VBox来自FXML文件。

public class Controller {

    @FXML private VBox root;
    private List<TextField> all = new ArrayList<>();

    public Controller(){}
    @FXML
    public void initialize(){
        EventHandler<ActionEvent> customEvent = e -> {
            if(e.getSource().getClass() == Button.class){
                all.forEach(t -> t.fireEvent(new ActionEvent()));
            }else {
                System.out.println(((TextField) e.getSource()).getText());
            }
        };

        for(int i=0; i < 10; i++){
            TextField tf = new TextField(Integer.toString(i));
            tf.setOnAction(customEvent);
            all.add(tf);
            root.getChildren().add(tf);
        }
        Button btn = new Button();
        btn.setOnAction(customEvent);
        root.getChildren().add(btn);
    }

}