背景:每次创建新的界面,都需要重写初始化表格组件、初始化分页组件、获取组件数值查询、跳转修改界面、跳转新建界面、关闭舞台场景、刷新、删除等功能,很繁琐,感觉写代码意义,所以总结出一套代码,是要这些通用的功能;
使用框架:SpringBoot+Jpa+JavaFx
实现功能:
1.实现表格组件、分页组件初始化和联动,默认每页显示50条;
2.实现通用分页多条件查询功能,多条件查询会根绝规则获取组件数值作为查询条件;
3.实现通用跳转新建页面功能;
4.实现通用跳转修改页面功能;
5.实现通用删除功能;
6.实现通用关闭弹出界面功能;
7.允许另外设置表格组件列宽;
PageContext:页面上下文
import com.maxinhai.world.WorldApplication;
import com.maxinhai.world.component.MsgAlert;
import com.maxinhai.world.entity.ClientMsg;
import com.maxinhai.world.service.CommonService;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Callback;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ConfigurableApplicationContext;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @program: world
* @description: 页面上下文
* @author: XinHai.Ma
* @create: 2021-09-29 13:42
*/
@SuppressWarnings("all")
public class PageContext<T> {
/**
* 实现功能:
* 1. 根据固定参数初始化表格和分页组件,实现多条件、分页查询;
* 2. 实现跳转新增、修改页面;
* 3. 实现批量删除功能;
* 4. 实现关闭二级页面功能;
* 5. 实现弹窗功能;
*
* 前置条件:
* 1. 使用PageContext类里面提供的功能;
* 2. 业务层实现CommonService接口;
* 3. 作为查询条件的组件值,在放入PageContext组件时,key规则为condition-code,
* 这样框架可以识别该组件的值是要作为查询条件的;
* 4. 框架默认给tableView里的数据列设置宽度,有个性化需要可以使用setColumnWidth()方法
* 为每个页面的tableView数据列设置列宽;
*/
private ConfigurableApplicationContext springContext;
private Map<String, Integer> pageParams = new HashMap<>();
/**
* 页面上下文(页面->页面组件(组件名称->组件实体类))
*/
private static ConcurrentHashMap<String, Map<String, Object>> context = new ConcurrentHashMap<>();
/**
* 页面表格列宽集合(页面->列宽(列名->宽度))
*/
private static ConcurrentHashMap<String, Map<String, Double>> columnWidthMap = new ConcurrentHashMap<>();
/**
* 设置页面table梅列宽度
* @param pageName
* @param widthMap
*/
public void setColumnWidth(String pageName, Map<String, Double> widthMap) {
columnWidthMap.put(pageName, widthMap);
}
/**
* 设置默认初始页码
* @param pageIndex
*/
public void setPageIndex(Integer pageIndex) {
if(pageIndex == null || pageIndex < 0) {
pageIndex = 0;
}
pageParams.put("pageIndex", pageIndex);
}
/**
* 设置默认显示行数
* @param pageCount
*/
public void setPageCount(Integer pageCount) {
if(pageCount == null || pageCount < 0) {
pageCount = 50;
}
pageParams.put("pageSize", pageCount);
}
/**
* 封装好通用查询,新增、修改、删除方法
*/
public void initPage(String pageName, Map<String, Object> moduleMap) {
if(context.containsKey(pageName)) {
throw new RuntimeException("pageName[" + pageName + "]已存在!");
}
context.put(pageName, moduleMap);
}
/**
* 初始化表格(有分页组件)
* @param pageName
* @param columns
* @param delList
* @param updList
* @param commonService
*/
public void initTable(String pageName, LinkedHashMap<String, String> columns, List<Long> delList, List<Long> updList, CommonService commonService) {
// 获取页面组件
Map<String, Object> page = context.get(pageName);
TableView<T> tableView = (TableView<T>)page.get("tableView");
HBox parent = (HBox)page.get("parent");
Pagination pagination = (Pagination)page.get("pagination");
// 获取用户设置的其他列宽数据
Map<String, Double> widthMap = columnWidthMap.get(pageName);
if(null != widthMap && widthMap.size() > 0) { ModuleUtils.getDefaultWidthMap().putAll(widthMap); }
List<TableColumn> columnList = ModuleUtils.createColumnByAutoBaseEntity(true, columns, delList, updList);
HashMap<String, Object> params = new HashMap<>();
params.put("pageIndex", 0);
params.put("pageSize", 50);
Map<String, Object> result = commonService.search(params);
List<ClientMsg> dataList = (List<ClientMsg>)result.get("data");
ModuleUtils.createDynamicTable(parent, tableView, columnList, dataList);
// 初始化分页插件
pagination.setCurrentPageIndex(0);
pagination.setPageCount(Integer.valueOf(result.get("total").toString()));
pagination.setPageFactory(new Callback<Integer, Node>() {
@Override
public Node call(Integer pageIndex) {
return createPage(pageName, pageIndex, commonService);
}
});
// 分页插件宽度(不设置分页插件宽度表格宽度也无法随窗口变化)
WorldApplication.getScene().widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
pagination.setPrefWidth(newValue.doubleValue());
}
});
}
/**
* 表格分页切换
* @param pageIndex
* @return
*/
private TableView<T> createPage(String pageName, int pageIndex, CommonService commonService) {
// 获取页面组件
Map<String, Object> page = context.get(pageName);
TableView<T> tableView = (TableView<T>)page.get("tableView");
HashMap<String, Object> params = new HashMap<>();
params.put("pageIndex", pageIndex);
params.put("pageSize", 50);
Map<String, Object> result = commonService.search(params);
List<T> dataList = (List)result.get("data");
ObservableList<T> items = FXCollections.observableArrayList(dataList);
tableView.setItems(items);
return tableView;
}
/**
* 通用查询方法
* @param pageName
* @param commonService
*/
public void select(String pageName, CommonService commonService) {
// 获取页面组件
Map<String, Object> page = context.get(pageName);
TableView<T> tableView = (TableView<T>)page.get("tableView");
Pagination pagination = (Pagination)page.get("pagination");
HashMap<String, Object> params = new HashMap<>();
page.forEach((k,v) -> {
if(k.startsWith("condition")) {
if(v instanceof TextArea) {
TextArea textArea = (TextArea)v;
if(StringUtils.isNotEmpty(textArea.getText())) {
params.put(k.split("-")[1], textArea.getText());
}
}
if(v instanceof TextField) {
TextField textField = (TextField)v;
if(StringUtils.isNotEmpty(textField.getText())) {
params.put(k.split("-")[1], textField.getText());
}
}
if(v instanceof DatePicker) {
DatePicker datePicker = (DatePicker)v;
if(null != datePicker.getValue()) {
params.put(k.split("-")[1], datePicker.getValue());
}
}
if(v instanceof ComboBox) {
ComboBox<String> comboBox = (ComboBox<String>)v;
if(StringUtils.isNotEmpty(comboBox.getValue())) {
params.put(k.split("-")[1], comboBox.getValue());
}
}
if(v instanceof ChoiceBox) {
ChoiceBox<String> choiceBox = (ChoiceBox<String>)v;
if(StringUtils.isNotEmpty(choiceBox.getValue())) {
params.put(k.split("-")[1], choiceBox.getValue());
}
}
}
});
params.put("pageIndex", 0);
params.put("pageSize", 50);
Map<String, Object> result = commonService.search(params);
List<T> dataList = (List<T>)result.get("data");
ObservableList<T> items = FXCollections.observableArrayList(dataList);
tableView.setItems(items);
pagination.setPageCount(Integer.valueOf(result.get("total").toString()));
}
/**
* 根据pageName跳转创建页面
* @param pageName
*/
public void toCreate(String pageName, String toPageName) {
// 获取页面组件
Map<String, Object> page = context.get(pageName);
TableView<T> tableView = (TableView<T>)page.get("tableView");
Pagination pagination = (Pagination)page.get("pagination");
// 创建
Map<String, Object> pageData = new HashMap<>();
pageData.put("isSave", "0");
pageData.put("tableView", tableView);
pageData.put("pagination", pagination);
CacheManager.putPageData(toPageName, pageData);
toPage(toPageName, "0");
}
/**
* 根据pageName和dis跳转修改页面
* @param pageName
* @param ids
*/
public void toEdit(String pageName, String toPageName, List<Long> ids) {
if(null != ids && ids.size() > 0) {
throw new RuntimeException("请选择一条数据修改!");
}
// 获取页面组件
Map<String, Object> page = context.get(pageName);
TableView<T> tableView = (TableView<T>)page.get("tableView");
Pagination pagination = (Pagination)page.get("pagination");
if (ids.size() != 1) {
MsgAlert.alert("请选择单条修改数据!");
return;
}
Map<String, Object> pageData = new HashMap<>();
pageData.put("isSave", "1");
pageData.put("tableView", tableView);
pageData.put("pagination", pagination);
pageData.put("gid", ids.get(0));
CacheManager.putPageData(toPageName, pageData);
toPage(toPageName, "1");
}
/**
* 根据isSave确定跳转修改或新增页面
*
* @param filePath fxml文件
* @param isSave 修改或保存标志
*/
protected void toPage(String filePath, String isSave) {
Platform.runLater(() -> {
try {
String title = "添加数据";
if (isSave.equals("1")) {
title = "编辑数据";
}
Stage stage = CacheManager.getStage(filePath);
if (Objects.isNull(stage)) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(filePath));
fxmlLoader.setControllerFactory(springContext::getBean);
Parent pane = fxmlLoader.load();
Scene scene = new Scene(pane);
stage = new Stage();
stage.setScene(scene);
stage.setTitle(title);
stage.initStyle(StageStyle.TRANSPARENT);
stage.show();
// 新增保存场景,编辑保存场景
if ("0".equals(isSave) || "1".equals(isSave)) {
CacheManager.putStage(filePath, stage);
}
}
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
});
}
/**
* 方法描述:刷新
*/
public void refresh(String pageName, CommonService commonService) {
Map<String, Object> data = CacheManager.getPageData(pageName);
TableView<T> tableView = (TableView<T>) data.get("tableView");
ObservableList<T> items = tableView.getItems();
items.removeAll(items);
HashMap<String, Object> params = new HashMap<>();
params.put("pageIndex", 0);
params.put("pageSize", 50);
Map<String, Object> result = commonService.search(params);
List<T> dataList = (List<T>)result.get("data");
items.addAll(dataList);
Pagination pagination = (Pagination) data.get("pagination");
pagination.setPageCount(Integer.valueOf(result.get("total").toString()));
}
/**
* 关闭页面
* @param pageName
*/
public void cancel(String pageName) {
// 清除组件里的数据
Map<String, Object> page = context.get(pageName);
page.forEach((k, v) -> {
if(v instanceof ComboBox) {
ComboBox<String> comboBox = (ComboBox<String>)v;
comboBox.setValue(null);
}
if(v instanceof ChoiceBox) {
ChoiceBox<String> choiceBox = (ChoiceBox<String>)v;
choiceBox.setValue(null);
}
if(v instanceof TextField) {
TextField textField = (TextField)v;
textField.setText(null);
}
if(v instanceof TextArea) {
TextArea textArea = (TextArea)v;
textArea.setText(null);
}
});
// 关闭舞台
Map<String, Object> pageData = CacheManager.getPageData(pageName);
String isSave = pageData.get("isSave").toString();
Stage stage = CacheManager.getStage(pageName);
// 编辑
if (isSave.equals("1") && Objects.nonNull(stage)) {
stage.close();
CacheManager.clearStage(pageName);
}
// 新增,直接关闭舞台
if (isSave.equals("0") && Objects.nonNull(stage)) {
stage.close();
}
}
/**
* 批量删除(未完成)
* @param pageName
* @param ids
* @param commonService
*/
public void remove(String pageName, List<Long> ids, CommonService<T> commonService) {
if (ids != null && ids.size() > 0) {
commonService.remove(ids);
refresh(pageName, commonService);
} else {
// 请选择要删除的数据
MsgAlert.alert("请选择要删除的数据!");
}
}
/**
* springContext在类里面注入不进去,改用赋值方式
* @param springContext
*/
public PageContext(ConfigurableApplicationContext springContext) {
this.springContext = springContext;
}
}
ModuleUtils:组件初始化工具类
import com.maxinhai.world.WorldApplication;
import com.maxinhai.world.component.IDCell;
import com.maxinhai.world.component.MsgAlert;
import com.maxinhai.world.entity.AutoBaseEntity;
import com.maxinhai.world.entity.BaseEntity;
import com.maxinhai.world.entity.ClientLoginRecord;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Pane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.text.Text;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.Duration;
import javafx.util.StringConverter;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
/**
* 组件工具类
*/
@SuppressWarnings("all")
public class ModuleUtils {
//====================================================对tableView代码提取===========================================
/**
* 根据columnList(表头集合)、dataList(数据集合)初始化tableView
*
* @param tableView tableView对象
* @param columnList 表格字段集合
* @param dataList 表格数据集合
*/
public static void createTable(TableView tableView, List<TableColumn> columnList, List dataList) {
AssertUtils.assertTrue(Objects.isNull(tableView), "Component is Null!");
// 设置表格可编辑
tableView.setEditable(true);
// 设置多选
tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// 去掉空白多于列
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
// 设置表头
tableView.getColumns().addAll(columnList);
// 更新表格数据
ObservableList<ClientLoginRecord> data = FXCollections.observableArrayList(dataList);
tableView.setItems(data);
// 使tableView随窗口变化而变化
WorldApplication.getScene().heightProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
tableView.setPrefHeight(newValue.doubleValue());
}
});
WorldApplication.getScene().widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
tableView.setPrefWidth(newValue.doubleValue());
}
});
}
/**
* 方法描述:根据columnList(表头集合)、dataList(数据集合)初始化tableView
* 注意:设置TableView的宽高去适应界面的大小行不通,只能设置父元素的大小,让TableView自适应
*
* @param parentNode 父容器
* @param tableView tableView对象
* @param columnList 表格字段集合
* @param dataList 表格数据集合
*/
public static void createDynamicTable(Pane parentNode, TableView tableView, List<TableColumn> columnList, List dataList) {
AssertUtils.assertTrue(Objects.isNull(tableView), "Component is Null!");
// 设置表格可编辑
tableView.setEditable(true);
// 设置多选
tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// 去掉空白多于列
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
// 设置表头
tableView.getColumns().addAll(columnList);
// 更新表格数据
ObservableList<ClientLoginRecord> data = FXCollections.observableArrayList(dataList);
tableView.setItems(data);
// 拖动行
tableView.setRowFactory(value -> {
TableRow<ObservableList<String>> row = new TableRow<>();
row.setOnMouseClicked(event -> {
if(event.getClickCount() == 2 && !row.isEmpty()) {
ObservableList items = tableView.getItems();
int rowIndex = row.getIndex();
System.out.println("行数据:" + items.get(rowIndex));
}
});
row.setOnDragDetected(event -> {
if (!row.isEmpty()) {
Integer index = row.getIndex();
Dragboard db = row.startDragAndDrop(TransferMode.MOVE);
db.setDragView(row.snapshot(null, null));
ClipboardContent cc = new ClipboardContent();
cc.put(DataFormat.PLAIN_TEXT, index);
db.setContent(cc);
event.consume();
}
});
row.setOnDragOver(event -> {
Dragboard db = event.getDragboard();
if (db.hasContent(DataFormat.PLAIN_TEXT)) {
if (row.getIndex() != ((Integer) db.getContent(DataFormat.PLAIN_TEXT)).intValue()) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
event.consume();
}
}
});
row.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
if (db.hasContent(DataFormat.PLAIN_TEXT)) {
int draggedIndex = (Integer) db.getContent(DataFormat.PLAIN_TEXT);
ObservableList<String> draggedPerson = (ObservableList<String>)tableView.getItems().remove(draggedIndex);
int dropIndex;
if (row.isEmpty()) {
dropIndex = tableView.getItems().size();
} else {
dropIndex = row.getIndex();
}
tableView.getItems().add(dropIndex, draggedPerson);
event.setDropCompleted(true);
tableView.getSelectionModel().select(dropIndex);
event.consume();
}
});
return row;
});
// 使tableView随窗口变化而变化
WorldApplication.getScene().heightProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
parentNode.setPrefHeight(newValue.doubleValue());
}
});
WorldApplication.getScene().widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
tableView.setPrefWidth(newValue.doubleValue());
}
});
}
/**
* 根据isCheckBox、columns创建表格表头(BaseEntity)
*
* @param isCheckBox 是否创建多选列
* @param columns bean字段对应中文集合
* @return
*/
public static List<TableColumn> createColumn(boolean isCheckBox, LinkedHashMap<String, String> columns, List<String> delList, List<String> updList) {
List<TableColumn> columnList = new ArrayList<>();
// 多选框
if (isCheckBox) {
TableColumn<BaseEntity, CheckBox> checkCol = new TableColumn("单选框");
checkCol.setMinWidth(50);
checkCol.setPrefWidth(50);
checkCol.setResizable(false);
checkCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<BaseEntity, CheckBox>, ObservableValue<CheckBox>>() {
@Override
public ObservableValue<CheckBox> call(TableColumn.CellDataFeatures<BaseEntity, CheckBox> param) {
CheckBox checkBox = new CheckBox();
// 设置checkBox居中,貌似没用
checkBox.setAlignment(Pos.CENTER);
checkBox.setOnAction(event -> {
boolean selected = checkBox.isSelected();
String gid = param.getValue().getGid();
if (selected) {
delList.add(gid);
updList.removeAll(updList);
updList.add(gid);
System.out.println("选中: " + gid);
} else {
delList.remove(gid);
updList.remove(gid);
System.out.println("取消选中: " + gid);
}
});
return new ReadOnlyObjectWrapper<CheckBox>(checkBox);
}
});
columnList.add(checkCol);
}
// 序号列
TableColumn seqCol = new TableColumn("序号");
seqCol.setMinWidth(50);
seqCol.setPrefWidth(50);
seqCol.setResizable(false);
seqCol.setCellFactory(new IDCell<>());
columnList.add(seqCol);
Map<String, Double> defaultWidthMap = getDefaultWidthMap();
// 创建其他表头
columns.forEach((k, v) -> {
TableColumn column = new TableColumn(v);
if ("gid".equals(k)) {
column.setVisible(false);
}
if (getDateColSet().contains(k)) {
formatDateTimeCol(column);
}
if (Objects.isNull(defaultWidthMap.get(k))) {
// 没有默认长度,设置100宽度
column.setMinWidth(100);
column.setPrefWidth(100);
} else {
column.setMinWidth(defaultWidthMap.get(k));
column.setPrefWidth(defaultWidthMap.get(k));
}
column.setResizable(false);
column.setCellValueFactory(new PropertyValueFactory<BaseEntity, String>(k));
columnList.add(column);
});
return columnList;
}
/**
* 根据isCheckBox、columns创建表格表头(AutoBaseEntity)
*
* @param isCheckBox 是否创建多选列
* @param columns bean字段对应中文集合
* @return
*/
public static List<TableColumn> createColumnByAutoBaseEntity(boolean isCheckBox, LinkedHashMap<String, String> columns, List<Long> delList, List<Long> updList) {
List<TableColumn> columnList = new ArrayList<>();
// 多选框
if (isCheckBox) {
TableColumn<AutoBaseEntity, CheckBox> checkCol = new TableColumn("单选框");
checkCol.setMinWidth(50);
checkCol.setPrefWidth(50);
checkCol.setResizable(false);
checkCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<AutoBaseEntity, CheckBox>, ObservableValue<CheckBox>>() {
@Override
public ObservableValue<CheckBox> call(TableColumn.CellDataFeatures<AutoBaseEntity, CheckBox> param) {
CheckBox checkBox = new CheckBox();
// 设置checkBox居中,貌似没用
checkBox.setAlignment(Pos.CENTER);
checkBox.setOnAction(event -> {
boolean selected = checkBox.isSelected();
Long gid = param.getValue().getGid();
if (selected) {
delList.add(gid);
updList.removeAll(updList);
updList.add(gid);
System.out.println("选中: " + gid);
} else {
delList.remove(gid);
updList.remove(gid);
System.out.println("取消选中: " + gid);
}
});
return new ReadOnlyObjectWrapper<CheckBox>(checkBox);
}
});
columnList.add(checkCol);
}
// 序号列
TableColumn seqCol = new TableColumn("序号");
seqCol.setMinWidth(50);
seqCol.setPrefWidth(50);
seqCol.setCellFactory(new IDCell<>());
seqCol.setResizable(false);
columnList.add(seqCol);
Map<String, Double> defaultWidthMap = getDefaultWidthMap();
// 创建其他表头
columns.forEach((k, v) -> {
TableColumn column = new TableColumn(v);
if ("gid".equals(k)) {
column.setVisible(false);
}
if (getDateColSet().contains(k)) {
formatDateTimeCol(column);
}
if (Objects.isNull(defaultWidthMap.get(k))) {
// 没有默认长度,设置100宽度
column.setMinWidth(150);
column.setPrefWidth(150);
} else {
column.setMinWidth(defaultWidthMap.get(k));
column.setPrefWidth(defaultWidthMap.get(k));
}
column.setResizable(false);
column.setCellValueFactory(new PropertyValueFactory<AutoBaseEntity, String>(k));
// column.setCellFactory(col -> {
// TableCell<Music, String> cell = new TableCell<>();
// Text text = new Text();
// cell.setGraphic(text);
// text.wrappingWidthProperty().bind(column.widthProperty());
// text.textProperty().bind(cell.textProperty());
// return cell;
// });
columnList.add(column);
});
return columnList;
}
/**
* 格式化时间字段(Java8)
*
* @param column
*/
public static void formatDateTimeCol(TableColumn column) {
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
column.setCellFactory(data -> {
TableCell<Object, LocalDateTime> cell = new TableCell<Object, LocalDateTime>() {
@Override
protected void updateItem(LocalDateTime item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null)
this.setText(format.format(item));
}
}
};
return cell;
});
}
/**
* 格式化时间字段(Java7)
*
* @param column
*/
public static void formatDateCol(TableColumn column) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
column.setCellFactory(data -> {
TableCell<Object, Date> cell = new TableCell<Object, Date>() {
@Override
protected void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null)
this.setText(format.format(item));
}
}
};
return cell;
});
}
/**
* 获取时间字段集合
*
* @return
*/
public static Set<String> getDateColSet() {
Set<String> colSet = new HashSet<>();
colSet.add("createTime");
colSet.add("editTime");
return colSet;
}
/**
* 刷新tableView
*
* @param tableView
* @param dataList
*/
public static void refresh(TableView tableView, List dataList) {
ObservableList items = tableView.getItems();
items.removeAll(items);
items.addAll(dataList);
tableView.refresh();
}
private static Map<String, Double> columnWidthMap = new HashMap<>();
static {
columnWidthMap.put("gid", 350.00);
columnWidthMap.put("account", 100.00);
columnWidthMap.put("code", 100.00);
columnWidthMap.put("name", 100.00);
columnWidthMap.put("description", 100.00);
columnWidthMap.put("remark", 100.00);
columnWidthMap.put("createBy", 100.00);
columnWidthMap.put("createTime", 200.00);
columnWidthMap.put("editBy", 100.00);
columnWidthMap.put("editTime", 200.00);
columnWidthMap.put("username", 200.00);
columnWidthMap.put("password", 200.00);
}
/**
* 获取默认字段对应长度集合
*
* @return
*/
public static Map<String, Double> getDefaultWidthMap() {
return columnWidthMap;
}
//====================================================对tableView代码提取===========================================
/**
* 初始化下拉框
*
* @param choiceBox 下拉框对象
* @param dataList 下拉框数据
*/
public static void createChoiceBox(ChoiceBox choiceBox, List dataList) {
dataList.add("");
AssertUtils.assertTrue(Objects.isNull(choiceBox), "Component is Null!");
// 下拉框数据
ObservableList observableList = FXCollections.observableArrayList(dataList);
// 装填数据
choiceBox.setItems(observableList);
// 选择监听事件
choiceBox.getSelectionModel().selectedIndexProperty().addListener((ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> {
//System.out.println("选择了: " + dataList.get(new_val.intValue()));
});
}
/**
* 初始化下拉框
*
* @param choiceBox 下拉框对象
* @param dataList 下拉框数据
*/
public static void createChomboBox(ComboBox choiceBox, List dataList) {
dataList.add("");
AssertUtils.assertTrue(Objects.isNull(choiceBox), "Component is Null!");
// 下拉框数据
ObservableList observableList = FXCollections.observableArrayList(dataList);
// 装填数据
choiceBox.setItems(observableList);
// 选择监听事件
choiceBox.getSelectionModel().selectedIndexProperty().addListener((ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> {
//System.out.println("选择了: " + dataList.get(new_val.intValue()));
});
}
/**
* 根据dataList、config初始化listView组件
*
* @param listView listView组件
* @param dataList 数据
* @param config 组件配置
*/
public static void createListView(ListView<String> listView, List<String> dataList, Map<String, Object> config) {
AssertUtils.assertTrue(Objects.isNull(listView), "Component is Null!");
// 设置组件宽高
Object width = config.get("width");
Object height = config.get("height");
if (Objects.nonNull(width)) {
double widthValue = Double.parseDouble(width.toString());
listView.setPrefWidth(widthValue);
}
if (Objects.nonNull(height)) {
double heightValue = Double.parseDouble(height.toString());
listView.setPrefHeight(heightValue);
}
// 装填数据
ObservableList<String> items = FXCollections.observableArrayList(dataList);
listView.setItems(items);
// 绑定选中事件
listView.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends String> ov, String old_val, String new_val) -> {
System.out.println(new_val);
});
}
//====================================================对fileChooser代码提取=========================================
/**
* 创建文件选择器
*
* @param stage
* @param fileChooser
* @return
*/
public static File createFileChoose(Stage stage, FileChooser fileChooser) {
AssertUtils.assertTrue(Objects.isNull(fileChooser), "Component is Null!");
fileChooser.setTitle("Open Resource File");
File file = fileChooser.showOpenDialog(stage);
return file;
}
/**
* 创建多文件选择器
*
* @param stage
* @param fileChooser
* @return
*/
public static List<File> createMultipleFileChooser(Stage stage, FileChooser fileChooser) {
AssertUtils.assertTrue(Objects.isNull(fileChooser), "Component is Null!");
fileChooser.setTitle("Open Resource File");
List<File> fileList = fileChooser.showOpenMultipleDialog(stage);
return fileList;
}
/**
* 创建文件夹选择器
*
* @param stage
* @param directoryChooser
* @return
*/
public static File createDirectoryChooser(Stage stage, DirectoryChooser directoryChooser) {
AssertUtils.assertTrue(Objects.isNull(directoryChooser), "Component is Null!");
directoryChooser.setTitle("Open Resource File");
File file = directoryChooser.showDialog(stage);
return file;
}
//====================================================对DatePicker代码提取==========================================
/**
* 初始化日期选择器
*
* @param datePicker
*/
public static void createDatePicker(DatePicker datePicker) {
AssertUtils.assertTrue(Objects.isNull(datePicker), "Component is Null!");
String pattern = "yyyy-MM-dd";
StringConverter<LocalDate> converter = new StringConverter<LocalDate>() {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
@Override
public String toString(LocalDate date) {
if (date != null) {
return dateFormatter.format(date);
} else {
return "";
}
}
@Override
public LocalDate fromString(String string) {
if (string != null && !string.isEmpty()) {
return LocalDate.parse(string, dateFormatter);
} else {
return null;
}
}
};
datePicker.setConverter(converter);
datePicker.setPromptText(pattern.toLowerCase());
}
/**
* 监听日期选择器(开始时间选择后结束时间不能超过开始时间)
*
* @param beginTime
* @param endTime
*/
public static void enableRange(DatePicker beginTime, DatePicker endTime) {
if(Objects.isNull(beginTime.getValue())) {
beginTime.setValue(LocalDate.now().minusDays(1));
}
if(Objects.isNull(endTime.getValue())) {
endTime.setValue(LocalDate.now());
}
Callback<DatePicker, DateCell> endTimeCallback = new Callback<DatePicker, DateCell>() {
@Override
public DateCell call(DatePicker param) {
return new DateCell() {
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
if(Objects.nonNull(beginTime)) {
if(item.isBefore(beginTime.getValue().plusDays(1))) {
setDisable(true);
}
}
}
};
}
};
Callback<DatePicker, DateCell> beginTimeCallback = new Callback<DatePicker, DateCell>() {
@Override
public DateCell call(DatePicker param) {
return new DateCell() {
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
if(Objects.nonNull(endTime)) {
if(item.isAfter(endTime.getValue().minusDays(1))) {
setDisable(true);
}
}
}
};
}
};
beginTime.setDayCellFactory(beginTimeCallback);
endTime.setDayCellFactory(endTimeCallback);
// 时间选择器监听器,监听用户选择日期
beginTime.valueProperty().addListener(new ChangeListener<LocalDate>() {
@Override
public void changed(ObservableValue<? extends LocalDate> observable, LocalDate oldValue, LocalDate newValue) {
LocalDate endTimeValue = endTime.getValue();
if(Objects.nonNull(endTimeValue)) {
if(newValue.isAfter(endTimeValue) || newValue.isEqual(endTimeValue)) {
MsgAlert.alert("选择时间不能大于等于结束时间!");
}
}
}
});
endTime.valueProperty().addListener(new ChangeListener<LocalDate>() {
@Override
public void changed(ObservableValue<? extends LocalDate> observable, LocalDate oldValue, LocalDate newValue) {
LocalDate beginTimeValue = beginTime.getValue();
if(Objects.nonNull(beginTimeValue)) {
if(newValue.isBefore(beginTimeValue) || newValue.isEqual(beginTimeValue)) {
MsgAlert.alert("选择时间不能小于等于开始时间!");
}
}
}
});
}
//======================================================对进度条代码提取============================================
private static ReentrantLock lock = new ReentrantLock();
/**
* 初始化进度条
*
* @param progressBar
*/
public static void createProgressBar(ProgressBar progressBar) {
progressBar.progressProperty().unbind();
progressBar.progressProperty().bind(null);
}
/**
* 更新进度条
*
* @param progressBar
*/
public static void updateVal(ProgressBar progressBar) {
lock.lock();
try {
progressBar.setProgress(1);
} finally {
lock.unlock();
}
}
/**
* 清空进度条
*
* @param progressBar
*/
public static void clear(ProgressBar progressBar) {
progressBar.setProgress(0);
}
/**
* 方法描述:初始化视频、音乐播放器
* @param filePath 播放文件
* @param mediaPlayer 播放器(没有这个参数)
* @param videoSlider 视频、音乐进度条
* @param volumeSlider 音量进度条
* @param playBtn 播放、暂停按钮
* @param currentTimeLabel 当前时间
* @param totalTimeLabel 视频、音乐总时间
* @param HashMap 播放器配置(宽、高、初始化音量)
*/
public static void initMediaPlayer(String filePath, Slider videoSlider, Slider volumeSlider, Button playBtn, Label currentTimeLabel, Label totalTimeLabel, HashMap<String, String> config) {
// 初始化播放器
String url = new File("E:\CloudMusic\陈光荣 - Lost Good Things.mp3").getAbsoluteFile().toURI().toString();
Media media = new Media(url);
MediaPlayer mediaPlayer = new MediaPlayer(media);
// 音量监听器
mediaPlayer.volumeProperty().bind(volumeSlider.valueProperty().divide(100));
// 进度条改变,音乐播放进度也改变
videoSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if(videoSlider.isValueChanging()) {
mediaPlayer.seek(mediaPlayer.getTotalDuration().multiply(videoSlider.getValue() / 100));
}
}
});
// 播放按钮绑定事件
playBtn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// 设置音乐总时间
double seconds = mediaPlayer.getTotalDuration().toSeconds();
Long value = null;
try {
value = new Double(seconds).longValue();
} catch (NumberFormatException e) {
e.printStackTrace();
}
totalTimeLabel.setText(formatDateTime(value));
String text = playBtn.getText();
if("暂停".equals(text)) {
playBtn.setText("播放");
mediaPlayer.pause();
}
if("播放".equals(text)) {
// 开始播放音乐
playBtn.setText("暂停");
mediaPlayer.play();
// 设置播放进度条
videoSlider.setMin(0.0);
videoSlider.setMax(mediaPlayer.getTotalDuration().toSeconds());
mediaPlayer.currentTimeProperty().addListener(new ChangeListener<Duration>() {
@Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
videoSlider.setValue(newValue.toSeconds());
// 更新当前时间
double currentSecond = newValue.toSeconds();
long currentValue = new Double(currentSecond).longValue();
currentTimeLabel.setText(formatDateTime(currentValue));
}
});
// 进度条改变,播放进度也改变
videoSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if(videoSlider.isValueChanging()) {
mediaPlayer.seek(mediaPlayer.getTotalDuration().multiply(videoSlider.getValue() / 100));
}
}
});
}
}
});
}
private static String formatDateTime(long mss) {
String time = null;
long minutes = (mss % ( 60 * 60)) /60;
long seconds = mss % 60;
String minutesValue = null;
if(String.valueOf(minutes).length() > 1) {
minutesValue = String.valueOf(minutes);
} else {
minutesValue = String.valueOf("0" + minutes);
}
String secondsValue= null;
if(String.valueOf(seconds).length() > 1) {
secondsValue = String.valueOf(seconds);
} else {
secondsValue = String.valueOf("0" + seconds);
}
time = minutesValue + ":" + secondsValue;
return time;
}
}
ClientMusicController:使用示例
import com.maxinhai.world.entity.Music;
import com.maxinhai.world.service.impl.ClientMusicServiceImpl;
import com.maxinhai.world.utils.PageContext;
import de.felixroske.jfxsupport.FXMLController;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import java.net.URL;
import java.util.*;
/**
* 辅助密码设置控制器
*/
@FXMLController
public class ClientMusicController extends BaseController implements Initializable {
@FXML
private TextField codeField;
@FXML
private TextField nameFiled;
@FXML
private TableView<Music> tableView;
@FXML
private Pagination pagination;
@Autowired
private ClientMusicServiceImpl musicService;
@FXML
private HBox parent;
// 删除集合
private List<Long> deleteList = new ArrayList<>();
// 编辑集合
private List<Long> updateList = new ArrayList<>();
@Autowired
private ConfigurableApplicationContext springContext;
@Override
public void initialize(URL location, ResourceBundle resources) {
PageContext<Music> pageContext = new PageContext<>(springContext);
Map<String, Object> moduleMap = new HashMap<>();
moduleMap.put("condition-code", codeField);
moduleMap.put("condition-name", nameFiled);
moduleMap.put("tableView", tableView);
moduleMap.put("pagination", pagination);
moduleMap.put("parent", parent);
pageContext.initPage("/fxml/client_music.fxml", moduleMap);
// 设置列宽
Map<String, Double> widthMap = new HashMap<>();
widthMap.put("fileHash", 300.00);
widthMap.put("SQFileHash", 300.00);
widthMap.put("HQFileHash", 300.00);
widthMap.put("networkUrl", 300.00);
widthMap.put("coverUrl", 300.00);
pageContext.setColumnWidth("/fxml/client_music.fxml", widthMap);
// 初始化表格
LinkedHashMap<String, String> columns = new LinkedHashMap<>();
columns.put("code", "歌曲编号");
columns.put("name", "歌曲名称");
columns.put("author", "作者");
columns.put("fileHash", "标准Hash");
columns.put("fileSize", "标准大小");
columns.put("SQFileHash", "高品质Hash");
columns.put("sqFileSize", "高品质大小");
columns.put("HQFileHash", "超品质Hash");
columns.put("hqFileSize", "超品质大小");
columns.put("networkUrl", "网络地址");
columns.put("coverUrl", "封面地址");
columns.put("createBy", "创建者");
columns.put("createTime", "创建时间");
columns.put("editBy", "编辑者");
columns.put("editTime", "编辑时间");
pageContext.initTable("/fxml/client_music.fxml", columns, deleteList, updateList, musicService);
}
/**
* 查询
*/
@FXML
public void select() {
PageContext<Music> pageContext = new PageContext<>(springContext);
pageContext.select("/fxml/client_music.fxml", musicService);
}
/**
* 保存辅助密码
*/
@FXML
public void create() {
PageContext<Music> pageContext = new PageContext<>(springContext);
pageContext.toCreate("/fxml/client_music.fxml", "/fxml/client_music_item.fxml");
}
/**
* 保存辅助密码
*/
@FXML
public void edit() {
PageContext<Music> pageContext = new PageContext<>(springContext);
pageContext.toEdit("/fxml/client_music.fxml","/fxml/client_music_item.fxml", updateList);
}
/**
* 保存辅助密码
*/
@FXML
public void remove() {
// PageContext<Music> pageContext = new PageContext<>(springContext);
// pageContext.remove("/fxml/client_music.fxml", deleteList, musicService);
}
/**
* 取消
*/
@FXML
public void cancel() {
PageContext<Music> pageContext = new PageContext<>(springContext);
pageContext.cancel("/fxml/client_music_item.fxml");
}
}
CommonService:通用业务层接口
必须实现这个接口,PageContext是根据多态去寻找CommonService接口实现类;
package com.maxinhai.world.service;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* 业务层通用方法
*/
public interface CommonService<T> {
JpaRepository<T, Long> getRepository();
/**
* 根据条件查询数据
* @param params
* @return
*/
Map<String, Object> search(Map<String, Object> params);
/**
* 根据参数创建记录
* @param params
* @return
*/
Map<String, Object> create(Map<String, Object> params);
/**
* 根据参数修改记录
* @param params
* @return
*/
Map<String, Object> modify(Map<String, Object> params);
/**
* 根据ids删除多条数据
* @param ids
* @return
*/
Map<String, Object> remove(List<Long> ids);
/**
* 根据id查询唯一一条数据
* @param id
* @return
*/
Optional<T> selectById(Long id);
/**
* 根据ids查询多条数据
* @param ids
* @return
*/
List<T> selectByIds(List<Long> ids);
}
ClientMusicServiceImpl:业务层实现类
package com.maxinhai.world.service.impl;
import com.maxinhai.world.entity.Music;
import com.maxinhai.world.repository.ClientMusicRepository;
import com.maxinhai.world.service.CommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* @program: world
* @description: 系统消息业务层
* @author: XinHai.Ma
* @create: 2021-09-26 16:46
*/
@Transactional
@Service
public class ClientMusicServiceImpl extends BaseService implements CommonService {
@Autowired
private ClientMusicRepository musicRepository;
/**
* 获取dao层
* @return
*/
@Override
public JpaRepository getRepository() {
return musicRepository;
}
@Override
public Map<String, Object> search(Map params) {
String pageIndex = params.get("pageIndex").toString();
String pageSize = params.get("pageSize").toString();
PageRequest page = PageRequest.of(Integer.valueOf(pageIndex), Integer.valueOf(pageSize), Sort.Direction.DESC, "createTime", "code");
Page<Music> recordPage = musicRepository.findAll(new Specification<Music>() {
@Override
public Predicate toPredicate(Root<Music> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> condition = new ArrayList<Predicate>();
condition.add(criteriaBuilder.equal(root.get("isDelete").as(Integer.class), 0));
condition.add(criteriaBuilder.equal(root.get("isActive").as(Integer.class), 0));
// 编码
if (Objects.nonNull(params.get("code"))) {
condition.add(criteriaBuilder.equal(root.get("code").as(String.class), params.get("code").toString()));
}
// 名称
if (Objects.nonNull(params.get("name"))) {
condition.add(criteriaBuilder.equal(root.get("name").as(String.class), params.get("name").toString()));
}
// 开始、结束时间
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
if (Objects.nonNull(params.get("beginTime")) && Objects.nonNull(params.get("endTime"))) {
// 开始时间和结束时间之内
String beginTime = params.get("beginTime").toString() + " 00:00:00";
String endTime = params.get("endTime").toString() + " 23:59:59";
condition.add(criteriaBuilder.between(root.<LocalDateTime>get("createTime"), LocalDateTime.parse(beginTime, formatter), LocalDateTime.parse(endTime, formatter)));
} else if (Objects.nonNull(params.get("beginTime"))) {
// 大于开始时间
String beginTime = params.get("beginTime").toString() + " 00:00:00";
condition.add(criteriaBuilder.greaterThanOrEqualTo(root.<LocalDateTime>get("createTime"), LocalDateTime.parse(beginTime, formatter)));
} else if (Objects.nonNull(params.get("endTime"))) {
// 小于结束时间
String beginTime = params.get("endTime").toString() + " 23:59:59";
condition.add(criteriaBuilder.lessThanOrEqualTo(root.<LocalDateTime>get("createTime"), LocalDateTime.parse(beginTime, formatter)));
}
Predicate[] p = new Predicate[condition.size()];
return criteriaBuilder.and(condition.toArray(p));
}
}, page);
Map<String, Object> result = new HashMap<>();
result.put("data", recordPage.get().collect(Collectors.toList()));
result.put("total", recordPage.getTotalPages());
return result;
}
@Override
public Map<String, Object> create(Map params) {
Map<String, Object> result = new HashMap<>();
try {
String code = Objects.isNull(params.get("code")) ? "" : params.get("code").toString();
String name = Objects.isNull(params.get("name")) ? "" : params.get("name").toString();
// String sender = Objects.isNull(params.get("sender")) ? "" : params.get("sender").toString();
// String receiver = Objects.isNull(params.get("receiver")) ? "" : params.get("receiver").toString();
// String sourceId = Objects.isNull(params.get("sourceId")) ? "" : params.get("sourceId").toString();
// String sourceModule = Objects.isNull(params.get("sourceModule")) ? "" : params.get("sourceModule").toString();
// String sourceFunction = Objects.isNull(params.get("sourceFunction")) ? "" : params.get("sourceFunction").toString();
// String clientId = Objects.isNull(params.get("clientId")) ? "" : params.get("clientId").toString();
Music music = new Music();
music.setCode(code);
music.setName(name);
musicRepository.save(music);
result.put("code", 200);
result.put("msg", "创建成功");
} catch (Exception e) {
result.put("code", 500);
result.put("msg", "创建失败!" + e.getMessage());
}
return result;
}
@Override
public Map<String, Object> modify(Map params) {
return null;
}
@Override
public Map<String, Object> remove(List ids) {
Map<String, Object> result = new HashMap<>();
try {
List<Music> musicList = selectByIds(ids);
for (Music music : musicList) {
music.setIsDelete(1);
music.setEditTime(LocalDateTime.now());
}
musicRepository.saveAll(musicList);
result.put("code", 200);
result.put("msg", "删除成功");
} catch (Exception e) {
result.put("code", 500);
result.put("msg", "删除失败!" + e.getMessage());
}
return result;
}
@Override
public Optional selectById(Long id) {
return musicRepository.findById(id);
}
@Override
public List selectByIds(List ids) {
List<Music> msgList = musicRepository.findAllById(ids);
return msgList;
}
}