本文是仿微信聊天程序专栏的第二篇文章,主要记录了【注册界面】的实现。
界面设计
仿微信聊天程序的注册界面,是一个表单,由三个输入框和一个按钮组成,具体UI展示如下图所示:
界面布局
页面布局使用fxml,采用VBox从上到下布局,中间的表单使用formsfx
,所以只需要预留一个StackPane给表单即可。
<VBox alignment="CENTER" prefHeight="350.0" prefWidth="480.0" spacing="10.0"
stylesheets="@/css/bootstrapfx.css"
xmlns:fx="http://javafx.com/fxml" fx:controller="michong.javafx.wx.view.register.RegisterController">
<children>
<HBox alignment="CENTER_LEFT">
<children>
<Label text="注册" styleClass="h3,b"/>
<Pane HBox.hgrow="ALWAYS"/>
<Label text="使用账号"/>
<Hyperlink text="登录" onAction="#onLoginClick"/>
</children>
<padding>
<Insets left="20.0" right="20.0"/>
</padding>
</HBox>
<StackPane fx:id="formStackPane"/>
<Button minWidth="120" text="注册" styleClass="btn-primary" onAction="#onRegisterClick"/>
</children>
<padding>
<Insets bottom="30.0" left="30.0" right="30.0" top="5.0"/>
</padding>
</VBox>
表单构建
表单使用的是开源库formfx
,其maven坐标如下:
<dependency>
<groupId>com.dlsc.formsfx</groupId>
<artifactId>formsfx-core</artifactId>
<version>1.3.1</version>
</dependency>
表单构建实现如下:
/**
* @author michong
*/
public class RegisterForm {
private final RegisterVO vo = new RegisterVO();
private Form form;
private FormRenderer renderer;
private RegisterForm() {
}
public static RegisterForm getInstance() {
RegisterForm rf = new RegisterForm();
rf.build();
return rf;
}
private void build() {
// @formatter:off
String nickname = "昵称";
String username = "账号";
String password = "密码";
String placeholderTextFmt = "请输入%s";
String requiredTextFmt = "%s必填";
form = Form.of(
Group.of(
Field.ofStringType(vo.nicknameProperty())
.label(nickname)
.placeholder(String.format(placeholderTextFmt, nickname))
.required(String.format(requiredTextFmt, nickname)),
Field.ofStringType(vo.usernameProperty())
.label(username)
.placeholder(String.format(placeholderTextFmt, username))
.required(String.format(requiredTextFmt, username)),
PasswordField.ofPasswordType(vo.passwordProperty())
.label(password)
.placeholder(String.format(placeholderTextFmt, password))
.required(String.format(requiredTextFmt, password))
)
);}
// @formatter:on
renderer = new FormRenderer(form);
}
}
这里的RegisterVO是一个普通的JavaBean,用于双向绑定表单数据:
public class RegisterVO {
private final StringProperty nickname = new SimpleStringProperty("");
private final StringProperty username = new SimpleStringProperty("");
private final StringProperty password = new SimpleStringProperty("");
public String getNickname() {
return nickname.get();
}
public StringProperty nicknameProperty() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname.set(nickname);
}
// 省略其他GETTER和SETTER
}
事件处理
在界面布局中,fxml绑定的controller为RegisterController,RegisterController主要负责UI的初始化和事件处理,其中:
- initializeUI():实现UI的初始化(其中部分UI直接使用变量绑定fxml的UI,如:formStackPane)
- initializeEvent():实现事件的初始化(其中部分事件使用方法绑定fxml的action,如onLoginClick和onRegisterClick)
public class RegisterController implements Initializable {
public StackPane formStackPane;
private RegisterForm form;
@Override
public void initialize(URL location, ResourceBundle resources) {
initializeUI();
initializeEvent();
}
void initializeUI() {
form = RegisterForm.getInstance();
formStackPane.getChildren().add(form.getRenderer());
}
void initializeEvent() {
}
public void onLoginClick(ActionEvent actionEvent) {
FX.error("功能开发中...");
}
public void onRegisterClick(ActionEvent actionEvent) {
form.getForm().persist();
if (form.getForm().isValid()) {
FX.info(form.getVO().getUsername() + "注册成功");
}
}
}
这里事件处理没有实现具体的业务,只是做一个提示,后续业务功能完善后,会继续改造这部分的功能。
启动流程
主程序实现:
public class App extends Application {
@Override
public void start(Stage primaryStage) {
AppStarter.start(primaryStage);
}
public static void main(String[] args) {
launch(args);
}
}
启动类实现:
/**
* @author michong
*/
public class AppStarter {
public static void start(Stage primaryStage) {
FXContext.setPrimaryStage(primaryStage);
Parent root = FX.fxml(RegisterController.class);
primaryStage.setScene(new Scene(root));
primaryStage.getIcons().clear();
primaryStage.getIcons().add(FXIcon.logo());
primaryStage.setResizable(false);
primaryStage.show();
}
}