背景:每次创建新的界面,都需要重写初始化表格组件、初始化分页组件、获取组件数值查询、跳转修改界面、跳转新建界面、关闭舞台场景、刷新、删除等功能,很繁琐,感觉写代码意义,所以总结出一套代码,是要这些通用的功能;
使用框架: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; } }