主界面效果图
因为界面的设计可以借助
JavaFX Scene Builder 2.0
通过控件拖拽的形式进行,本文就不在详细描述拖拽和布局过程。
MainView.fxml
文件位置同样位于resources目录下的view目录下:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="650.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cn.oldsheep.javafx.view.MainViewController">
<top>
<MenuBar fx:id="menuBar" BorderPane.alignment="CENTER" />
</top>
<bottom>
<GridPane BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Separator prefWidth="200.0">
<opaqueInsets>
<Insets />
</opaqueInsets>
<GridPane.margin>
<Insets top="-20.0" />
</GridPane.margin>
</Separator>
<Label text="xxxxxx信息系统V1.0">
<GridPane.margin>
<Insets left="30.0" top="5.0" />
</GridPane.margin>
</Label>
<Label text=" ©xxxxx公司">
<GridPane.margin>
<Insets left="350.0" top="5.0" />
</GridPane.margin>
</Label>
</children>
</GridPane>
</bottom>
</BorderPane>
MainViewController类
package cn.oldsheep.javafx.view;
import cn.oldsheep.barcode.Main;
import cn.oldsheep.barcode.dao.JdbcTemplate;
import cn.oldsheep.barcode.model.BarCode;
import cn.oldsheep.barcode.utils.AlertUtil;
import cn.oldsheep.barcode.utils.DateUtil;
import cn.oldsheep.barcode.utils.GenerateUniqueID;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import org.apache.commons.codec.digest.DigestUtils;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Optional;
/**
* 登录后的主界面视图控制器,Menu菜单的所有的Action都在该视图控制中
* author : oldsheep
* qq|wechat: 64341393
* Create on 2020/12/27.
*/
public class MainViewController {
@FXML
private MenuBar menuBar;
private Main mainApp;
private JdbcTemplate jdbcTemplate;
public MainViewController() {
}
public void setMainApp(Main mainApp) {
this.mainApp = mainApp;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@FXML
private void initialize() {
// add generate bar code menu
Menu generateBarCodeMenu = new Menu();
final Label genBarCodeLabel = new Label("生成条形码");
genBarCodeLabel.setOnMouseClicked(event -> {
handleGenerateBarCode();
});
generateBarCodeMenu.setGraphic(genBarCodeLabel);
// add change password menu
Menu changePasswordMenu = new Menu();
final Label cpwdLabel = new Label("修改密码");
cpwdLabel.setOnMouseClicked(event -> {
handleChangePwd();
});
changePasswordMenu.setGraphic(cpwdLabel);
// add logout menu
Menu logoutAppMenu = new Menu();
final Label logoutAppMenuLabel = new Label("退出登录");
logoutAppMenuLabel.setOnMouseClicked(event -> {
handleLogout(null);
});
logoutAppMenu.setGraphic(logoutAppMenuLabel);
// add exit application menu
Menu exitMenu = new Menu();
final Label exitAppLabel = new Label("退出程序");
exitAppLabel.setOnMouseClicked(event -> handleExitApp());
exitMenu.setGraphic(exitAppLabel); //将标签设置到menu的graphic属性当中
menuBar.getMenus().add(generateBarCodeMenu);
menuBar.getMenus().add(changePasswordMenu);
menuBar.getMenus().add(logoutAppMenu);
menuBar.getMenus().add(exitMenu);
}
/**
* 修改密码 Create the custom dialog.
*/
private void handleChangePwd() {
Dialog<Boolean> dialog = new Dialog<>();
dialog.setTitle("修改密码");
dialog.setHeaderText("请输入正确的旧密码,并牢记您的新密码!");
// Set the button types.
ButtonType changeButtonType = new ButtonType("确认", ButtonBar.ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(changeButtonType, ButtonType.CANCEL);
// Create the old password and password labels and fields.
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));
PasswordField oldPassword = new PasswordField();
oldPassword.setPromptText("请输入您的旧密码");
PasswordField password = new PasswordField();
password.setPromptText("请输入您的新密码");
PasswordField repassword = new PasswordField();
repassword.setPromptText("请再次输入您的新密码");
grid.add(new Label("旧密码:"), 0, 0);
grid.add(oldPassword, 1, 0);
grid.add(new Label("新密码:"), 0, 1);
grid.add(password, 1, 1);
grid.add(new Label("确认密码:"), 0, 2);
grid.add(repassword, 1, 2);
// Enable/Disable ok button depending on whether a username was entered.
Node changeButton = dialog.getDialogPane().lookupButton(changeButtonType);
changeButton.setDisable(true);
// Do some validation (using the Java 8 lambda syntax).
oldPassword.textProperty().addListener((observable, oldValue, newValue) -> {
changeButton.setDisable(newValue.trim().isEmpty());
});
dialog.getDialogPane().setContent(grid);
changeButton.addEventFilter(ActionEvent.ACTION, event -> {
if (!mainApp.getUserLogin().getPwd().equals(DigestUtils.md5Hex(oldPassword.getText()))) {
AlertUtil.errorAlert(new StringBuffer("您输入的旧密码不正确!"));
changeButton.requestFocus();
event.consume(); // 让确认事件销毁,不起作用
} else if (!password.getText().equals(repassword.getText())) {
AlertUtil.errorAlert(new StringBuffer("您输入的新密码不一致!"));
repassword.requestFocus();
event.consume();
} else {
if (repassword.getText().length() >= 6 &&
jdbcTemplate.updatePwd(mainApp.getUserLogin().getUserAccount(), repassword.getText())) {
AlertUtil.successAlert(new StringBuffer("修改成功"));
mainApp.getUserLogin().setPwd(DigestUtils.md5Hex(repassword.getText())); // 更新下缓存
} else {
AlertUtil.errorAlert(new StringBuffer("新密码长度不能少于6位!"));
repassword.requestFocus();
event.consume();
}
}
});
dialog.showAndWait();
}
/**
* menu -> exit the application function
*/
@FXML
private void handleExitApp() {
Optional<ButtonType> result = AlertUtil.confirmAlert("您确定要关闭应用程序吗?");
if (result.get() == ButtonType.OK) {
System.exit(0);
}
}
/**
* menu -> generate bar code function
* Note: The result.isPresent() will return false if the user cancelled the dialog.
*/
@FXML
private boolean handleGenerateBarCode() {
Optional<String> result = AlertUtil.textDialogAlert("50", "请输入您要生成的条形码数量:");
if (result.isPresent()) {
int generateCount = 0;
try {
generateCount = Integer.parseInt(result.get());
if (generateCount > 0) {
final Map<String, Long> status = mainApp.getSTATUS();
if (!status.containsKey(DateUtil.getDate())) { // no today key, search max seq no from database
GenerateUniqueID.resetAtomicSeq(jdbcTemplate.getDBSeqId());
}
// get container current data
ObservableList<BarCode> codesData = mainApp.getBarCodesData();
for (int i = generateCount, j = 1 + codesData.size(); i > 0; i--, j++) {
codesData.add(new BarCode(String.valueOf(j),
GenerateUniqueID.nextId(), LocalDateTime.now(), false));
}
status.put(DateUtil.getDate(), GenerateUniqueID.getAtomicSeq()); // put today key, next operate not search db
}
} catch (NumberFormatException e) {
AlertUtil.errorAlert(new StringBuffer("请您输入正确的数字!"));
return handleGenerateBarCode(); // if input value is not number recursive
}
return true;
}
return false;
}
/**
* Menu -> logout function
*
* @param actionEvent
*/
@FXML
private void handleLogout(ActionEvent actionEvent) {
Optional<ButtonType> result = AlertUtil.confirmAlert("您确定要退出当前登录吗?");
if (result.get() == ButtonType.OK) {
mainApp.getBarCodesData().clear();
mainApp.getSTATUS().remove(DateUtil.getDate());
mainApp.showLoginView();
}
}
}
Main类
Main类中增加如下方法
/**
* Initializes the application main view
*/
public void showMainView() {
try {
FXMLLoader loader = viewLoader("MainView");
rootLayout = loader.load();
primaryStage.setResizable(true);
MainViewController controller = loader.getController();
controller.setMainApp(this);
controller.setJdbcTemplate(jdbcTemplate);
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
AlertUtil.exceptionAlert(e);
}
}
/**
* Initializes the application bar view
*/
public void showBarCodeView() {
try {
FXMLLoader loader = viewLoader("BarCodeView");
AnchorPane barCodeOverview = loader.load();
rootLayout.setCenter(barCodeOverview);
BarCodeViewController controller = loader.getController();
controller.setMainApp(this);
controller.setJdbcTemplate(jdbcTemplate);
} catch (IOException e) {
e.printStackTrace();
}
}
BarCodeView.fxml为主界面中的表格和右侧明细部分布局控件。
切换视图功能位于登录成功后动作。