Skip to content

Instantly share code, notes, and snippets.

@manuel-mauky
Last active April 5, 2018 02:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save manuel-mauky/e8a7e4e58ce2ac12d088 to your computer and use it in GitHub Desktop.
Save manuel-mauky/e8a7e4e58ce2ac12d088 to your computer and use it in GitHub Desktop.
mvvmFX example implementing a registration form. Dependencies needed: `de.saxsys:mvvmfx` and `eu.lestard:advanced-bindings`
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import de.saxsys.mvvmfx.FluentViewLoader;
public class MvvmfxExampleApp extends Application {
public static void main(String... args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
final Parent root = FluentViewLoader.fxmlView(RegisterView.class).load().getView();
stage.setScene(new Scene(root));
stage.show();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:controller="RegisterView" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<children>
<VBox spacing="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label style="-fx-font-size: 2em; -fx-text-fill: #555;" text="Registrierungsformular" />
<Separator prefWidth="200.0" />
<GridPane hgap="5.0" vgap="5.0" VBox.vgrow="ALWAYS">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="185.0" minWidth="10.0" prefWidth="133.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="145.0" minWidth="10.0" prefWidth="145.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 minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Nutzername:" />
<Label text="Passwort:" GridPane.rowIndex="1" />
<Label text="Passwort bestätigen:" GridPane.rowIndex="2" />
<Button fx:id="registerButton" defaultButton="true" mnemonicParsing="false" text="Registrieren" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<TextField fx:id="usernameInput" GridPane.columnIndex="1" />
<PasswordField fx:id="passwordInput" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<PasswordField fx:id="confirmInput" GridPane.columnIndex="1" GridPane.rowIndex="2" />
</children>
</GridPane>
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>
</children>
</AnchorPane>
import de.saxsys.mvvmfx.FxmlView;
import de.saxsys.mvvmfx.InjectViewModel;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
public class RegisterView implements FxmlView<RegisterViewModel> {
@FXML
public TextField usernameInput;
@FXML
public PasswordField passwordInput;
@FXML
public PasswordField confirmInput;
@FXML
public Button registerButton;
@InjectViewModel
private RegisterViewModel viewModel;
public void initialize() {
usernameInput.textProperty().bindBidirectional(viewModel.usernameProperty());
passwordInput.textProperty().bindBidirectional(viewModel.passwordProperty());
confirmInput.textProperty().bindBidirectional(viewModel.confirmPasswordProperty());
registerButton.disableProperty().bind(viewModel.registerButtonEnabledProperty().not());
}
}
import de.saxsys.mvvmfx.ViewModel;
import eu.lestard.advanced_bindings.api.LogicBindings;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class RegisterViewModel implements ViewModel{
private StringProperty username = new SimpleStringProperty("");
private StringProperty password = new SimpleStringProperty("");
private StringProperty confirmPassword = new SimpleStringProperty("");
private ReadOnlyBooleanWrapper registerButtonEnabled = new ReadOnlyBooleanWrapper();
public RegisterViewModel() {
final BooleanBinding passwordsEqual = Bindings.createBooleanBinding(() -> {
final String pw = password.get() == null ? "" : password.get();
final String confirm = confirmPassword.get() == null ? "" : confirmPassword.get();
return pw.equals(confirm);
}, password, confirmPassword);
registerButtonEnabled.bind(
LogicBindings.and(
username.isNotEmpty(),
password.isNotEmpty(),
confirmPassword.isNotEmpty(),
passwordsEqual));
}
public StringProperty usernameProperty() {
return username;
}
public StringProperty passwordProperty() {
return password;
}
public StringProperty confirmPasswordProperty() {
return confirmPassword;
}
public ReadOnlyBooleanProperty registerButtonEnabledProperty() {
return registerButtonEnabled.getReadOnlyProperty();
}
}
import org.junit.Before;
import org.junit.Test;
import static eu.lestard.assertj.javafx.api.Assertions.assertThat;
public class RegisterViewModelTest {
RegisterViewModel viewModel;
@Before
public void setup() {
viewModel = new RegisterViewModel();
}
@Test
public void test() {
// initial values
assertThat(viewModel.usernameProperty()).hasValue("");
assertThat(viewModel.passwordProperty()).hasValue("");
assertThat(viewModel.confirmPasswordProperty()).hasValue("");
assertThat(viewModel.registerButtonEnabledProperty()).isFalse();
// entering username
viewModel.usernameProperty().setValue("manuel");
// still disabled
assertThat(viewModel.registerButtonEnabledProperty()).isFalse();
// enter password
viewModel.passwordProperty().set("geheim"); // no, that's not really my password ;-)
assertThat(viewModel.registerButtonEnabledProperty()).isFalse();
// confirm password
viewModel.confirmPasswordProperty().set("geheim");
// now register button is enabled
assertThat(viewModel.registerButtonEnabledProperty()).isTrue();
// change confirm password
viewModel.confirmPasswordProperty().set("secret");
// disabled again
assertThat(viewModel.registerButtonEnabledProperty()).isFalse();
viewModel.passwordProperty().set("secret");
// now both passwords are equal again
assertThat(viewModel.registerButtonEnabledProperty()).isTrue();
// when username is removed ...
viewModel.usernameProperty().setValue("");
// ... the button is disabled again
assertThat(viewModel.registerButtonEnabledProperty()).isFalse();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment