是否可以结合使用fx:include和afterburner

时间:2014-07-21 21:47:11

标签: javafx fxml

我目前正在使用afterburner.fx来定制基于JavaFX的应用程序的组件。 现在我尝试在单独的fxml文件中移动组件以获得更舒适的维护。

要使用 fx:include 指令加载此类组件,该指令允许自动加载嵌套组件。

问题是,在自动加载时,我失去了从嵌套视图中获取演示者的可能性。

有没有办法组合自动加载,同时,能够使用来自父根的嵌套组件?

1 个答案:

答案 0 :(得分:1)

这两个似乎可以很好地协同工作。

Afterburner通过在FXML加载器上设置控制器工厂来工作,它负责实例化presenter类并将值注入其中。

加载包含的FXML时,<fx:include>元素将传播控制器工厂,因此您还可以将值注入到包含的FXML中定义的控制器中。因为加力燃烧室有效地使用单独的作用域进行注射,所以将使用相同的注入场实例。这意味着您可以在不同的演示者类之间轻松共享数据模型。

如果您想要访问与附带的FXML相关联的演示者,只需使用standard technique for "nested controllers"

所以,例如:

main.fxml:

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

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.geometry.Insets?>

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="application.MainPresenter">
    <center>
        <TableView fx:id="table">
            <columns>
                <TableColumn text="First Name" prefWidth="150">
                <cellValueFactory>
                    <PropertyValueFactory property="firstName" />
                    </cellValueFactory>
                </TableColumn>
                <TableColumn text="Last Name" prefWidth="150">
                <cellValueFactory>
                    <PropertyValueFactory property="lastName" />
                    </cellValueFactory>
                </TableColumn>
                <TableColumn text="Email" prefWidth="200">
                <cellValueFactory>
                    <PropertyValueFactory property="email" />
                    </cellValueFactory>
                </TableColumn>
            </columns>
        </TableView>
    </center>
    <bottom>
        <fx:include source="Editor.fxml" fx:id="editor">
            <padding>
                <Insets top="5" bottom="5" left="5" right="5"/>
            </padding>
        </fx:include>
    </bottom>
</BorderPane>

editor.fxml:

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

<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>

<GridPane xmlns:fx="http://javafx.com/fxml" hgap="5" vgap="10" fx:controller="application.EditorPresenter">
    <Label GridPane.rowIndex="0" GridPane.columnIndex="0" text="First Name:"/>
    <TextField fx:id="firstNameTextField" GridPane.rowIndex="0" GridPane.columnIndex="1"/>

    <Label GridPane.rowIndex="1" GridPane.columnIndex="0" text="Last Name"/>
    <TextField fx:id="lastNameTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>

    <Label GridPane.rowIndex="2" GridPane.columnIndex="0" text="Email"/>
    <TextField fx:id="emailTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>

    <HBox GridPane.rowIndex="3" GridPane.columnIndex="0" GridPane.columnSpan="2">
        <Button fx:id="addEditButton" onAction="#addEdit" />
    </HBox>

</GridPane>

MainPresenter.java:

package application;

import javax.inject.Inject;

import javafx.fxml.FXML;
import javafx.scene.control.TableView;

public class MainPresenter {
    @FXML
    private TableView<Person> table ;

    // This is the controller (presenter) for the included fxml
    // It is injected by the FXMLLoader; the rule is that "Controller" needs to be
    // appended to the fx:id attribute of the <fx:include> tag.
    // This is not used in this example but is here to demonstrate how to access it
    // if needed.
    @FXML
    private EditorPresenter editorController ;

    @Inject
    private DataModel dataModel ;

    public void initialize() {
        table.setItems(dataModel.getPeople());

        table.getSelectionModel().selectedItemProperty().addListener(
                (obs, oldPerson, newPerson) -> dataModel.setCurrentPerson(newPerson));

        dataModel.currentPersonProperty().addListener((obs, oldPerson, newPerson) -> {
            if (newPerson == null) {
                table.getSelectionModel().clearSelection();
            } else {
                table.getSelectionModel().select(newPerson);
            }
        });

        dataModel.getPeople().addAll(
            new Person("Jacob", "Smith", "jacob.smith@example.com"),
            new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
            new Person("Ethan", "Williams", "ethan.williams@example.com"),
            new Person("Emma", "Jones", "emma.jones@example.com"),
            new Person("Michael", "Brown", "michael.brown@example.com")
        );
    }
}

EditorPresenter.java:

package application;

import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

import javax.inject.Inject;

public class EditorPresenter {
    @FXML
    private TextField firstNameTextField ;
    @FXML
    private TextField lastNameTextField ;
    @FXML
    private TextField emailTextField ;
    @FXML
    private Button addEditButton ;

    @Inject
    private DataModel dataModel ;

    public void initialize() {
        addEditButton.textProperty().bind(
            Bindings.when(Bindings.isNull(dataModel.currentPersonProperty()))
                .then("Add")
                .otherwise("Update")
        );

        dataModel.currentPersonProperty().addListener((obs, oldPerson, newPerson) -> {
            if (newPerson == null) {
                firstNameTextField.setText("");
                lastNameTextField.setText("");
                emailTextField.setText("");
            } else {
                firstNameTextField.setText(newPerson.getFirstName());
                lastNameTextField.setText(newPerson.getLastName());
                emailTextField.setText(newPerson.getEmail());
            }
        });
    }

    @FXML
    private void addEdit() {
        Person person = dataModel.getCurrentPerson();
        String firstName = firstNameTextField.getText();
        String lastName = lastNameTextField.getText();
        String email = emailTextField.getText();
        if (person == null) {
            dataModel.getPeople().add(new Person(firstName, lastName, email));
        } else {
            person.setFirstName(firstName);
            person.setLastName(lastName);
            person.setEmail(email);
        }
    }
}

MainView.java:

package application;

import com.airhacks.afterburner.views.FXMLView;

public class MainView extends FXMLView {

}

Main.java(应用程序类):

package application;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

import com.airhacks.afterburner.injection.Injector;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        MainView mainView = new MainView();
        Scene scene = new Scene(mainView.getView(), 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        Injector.forgetAll();
    }

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

DataModel.java:

package application;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class DataModel {
    private final ObservableList<Person> people = FXCollections.observableArrayList();
    private final ObjectProperty<Person> currentPerson = new SimpleObjectProperty<>(this, "currentPerson");

    public ObservableList<Person> getPeople() {
        return people ;
    }

    public final Person getCurrentPerson() {
        return currentPerson.get();
    }

    public final void setCurrentPerson(Person person) {
        this.currentPerson.set(person);
    }

    public ObjectProperty<Person> currentPersonProperty() {
        return currentPerson ;
    }
}

通常的Person.java示例:

package application;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Person {
    private final StringProperty firstName = new SimpleStringProperty(this, "firstName");
    public final String getFirstName() {
        return firstName.get();
    }
    public final void setFirstName(String firstName) {
        this.firstName.set(firstName);
    }
    public StringProperty firstNameProperty() {
        return firstName ;
    }

    private final StringProperty lastName = new SimpleStringProperty(this, "lastName");
    public final String getLastName() {
        return lastName.get();
    }
    public final void setLastName(String lastName) {
        this.lastName.set(lastName);
    }
    public StringProperty lastNameProperty() {
        return lastName ;
    }

    private final StringProperty email = new SimpleStringProperty(this, "email");
    public final String getEmail() {
        return email.get();
    }
    public final void setEmail(String email) {
        this.email.set(email);
    }
    public StringProperty emailProperty() {
        return email ;
    }

    public Person(String firstName, String lastName, String email) {
        setFirstName(firstName);
        setLastName(lastName);
        setEmail(email);
    }
}