用JavaFX写了一个简易的管理系统

文章目录

  • 前言
  • 正文
    • 一、最终效果
      • 1.1 主页面
      • 1.2 动物管理页面-初始化
      • 1.3 动物管理页面-修改&新增
      • 1.4 动物管理页面-删除&批量删除
    • 二、核心代码展示
      • 2.1 启动类
      • 2.2 数据库配置-db.setting
      • 2.3 日志文本域组件
      • 2.4 自定义表格视图组件
      • 2.5 自定义分页组件
      • 2.6 动物管理页面
      • 2.7 页面工厂
  • 附录
    • 附1:sql脚本

前言

自学一下Java FX ,用Java代码写一个简易的客户端。

本文项目是Maven项目,使用了Java17,以及mysql。
代码仓库:https://gitee.com/fengsoshuai/java-fx-management-system-demo/tree/dev-with-db/

正文

一、最终效果

1.1 主页面

启动项目后,自动展示主页面。
在这里插入图片描述

1.2 动物管理页面-初始化

支持分页查询,搜索,新增,修改,删除,批量删除等功能。
整体分为以下几层:

  • 操作按钮,包含新增,修改,删除,刷新列表;
  • 搜索框,支持搜索动物的几个常用信息;
  • 列表,展示动物数据(分页);
  • 分页功能相关按钮,支持首页,下一页,最后一页,跳转到指定页,切换每页大小;
  • 操作记录,记录操作日志,内存存储(有兴趣的可以改为数据库存储),支持清空记录;

在这里插入图片描述

1.3 动物管理页面-修改&新增

在这里插入图片描述

1.4 动物管理页面-删除&批量删除

使用ctrl+鼠标左键选择要删除的数据。然后点击删除按钮。
出现弹窗后,点击确定,即可删除。
在这里插入图片描述

二、核心代码展示

2.1 启动类

渲染主页,左侧菜单栏,以及基本的布局。

package org.feng.demofx;import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
import org.feng.demofx.pages.AnimalManagePage;
import org.feng.demofx.pages.MainPage;
import org.feng.demofx.sys.*;
import org.feng.demofx.util.ArrayUtil;
import org.feng.demofx.util.StyleUtil;import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** 启动类** @author feng*/
public class StartApplication extends Application {/*** 屏幕宽度*/public static final Double SCREEN_WIDTH;/*** 屏幕高度*/public static final Double SCREEN_HEIGHT;/*** 左侧菜单宽度*/public static final Double LEFT_MENU_WIDTH;/*** root容器,使用HBox类型*/private HBox root;/*** 左侧菜单栏*/private VBox leftMenu;/*** 当前页的节点*/private Node currentPageNode;/*** 左侧菜单的当前索引*/private Integer currentMenuIndex;/*** 左侧菜单的临时索引,选中时的菜单项索引*/private Integer tempIndex;/*** 左侧菜单面板背景颜色*/private static final Color LEFT_MENU_BACKGROUND_COLOR = Color.web("#FFF8DC");/*** 左侧菜单按钮背景颜色*/private static final Color LEFT_MENU_BUTTON_BACKGROUND_COLOR = Color.web("#DEB887");/*** 左侧菜单按钮hover时(鼠标移动到按钮上)的颜色*/private static final Color LEFT_MENU_BUTTON_HOVER_BACKGROUND_COLOR = Color.web("D2691E");/*** 左侧菜单按钮点击时的字体颜色*/private static final Color LEFT_MENU_BUTTON_CLICK_BACKGROUND_COLOR = Color.web("#6495ed");static {SCREEN_WIDTH = Screen.getPrimary().getBounds().getWidth();SCREEN_HEIGHT = Screen.getPrimary().getBounds().getHeight();LEFT_MENU_WIDTH = 240.0;}@Overridepublic void start(Stage stage) throws Exception {// 注册页面渲染器registerPageNodeRender();root = new HBox();// 渲染左侧菜单栏leftMenu = renderLeftMenu(root);root.getChildren().add(leftMenu);// 主面板currentPageNode = routePage(root, MainPage.PAGE_KEY);HBox.setHgrow(currentPageNode, Priority.ALWAYS);root.getChildren().add(currentPageNode);StyleUtil.setPaneBackground(root, Color.WHITE);Scene scene = new Scene(root, SCREEN_WIDTH * 0.8, SCREEN_HEIGHT * 0.8);// 窗口的标题stage.setTitle("管理系统");stage.setScene(scene);// 禁止拖拽窗口大小stage.setResizable(false);stage.show();}private VBox renderLeftMenu(HBox root) {VBox vbox = new VBox();vbox.setMinHeight(root.getPrefHeight());vbox.setMinWidth(LEFT_MENU_WIDTH);StyleUtil.setPaneBackground(vbox, LEFT_MENU_BACKGROUND_COLOR);// 增加菜单中的项目vbox.getChildren().addAll(getLeftMenuItemList());return vbox;}/*** 生成左侧菜单按钮*/private List<Button> getLeftMenuItemList() {double buttonHeight = 30;List<Button> buttonList = new ArrayList<>(3);Map<String, String> pageNameMap = PageNodeRenderFactory.getPageNameMap();String[] itemNames = pageNameMap.values().toArray(new String[0]);for (String name : itemNames) {Button button = new Button(name);button.setMinWidth(LEFT_MENU_WIDTH);button.setMinHeight(buttonHeight);StyleUtil.setButtonBackground(button, LEFT_MENU_BUTTON_BACKGROUND_COLOR, Color.WHITE);// 增加鼠标移动到菜单上到hover效果button.setOnMouseMoved(event -> {StyleUtil.setButtonBackground(button, LEFT_MENU_BUTTON_HOVER_BACKGROUND_COLOR, Color.WHITE);StyleUtil.setFont(button, Color.web("#E6A23C"), -1);});button.setOnMouseExited(event -> {if (currentMenuIndex == null || !button.getText().equals(itemNames[currentMenuIndex])) {StyleUtil.setButtonBackground(button, LEFT_MENU_BUTTON_BACKGROUND_COLOR, Color.WHITE);} else {StyleUtil.setButtonBackground(button, LEFT_MENU_BUTTON_BACKGROUND_COLOR, Color.WHITE);}});button.setOnMouseClicked(event -> {currentMenuIndex = ArrayUtil.getIndexForArray(itemNames, button.getText());currentPageNode = routePage(root, PageNodeRenderFactory.getPageKeyByName(name));root.getChildren().remove(1);    //清除右侧页面路由组件节点HBox.setHgrow(currentPageNode, Priority.ALWAYS);root.getChildren().add(currentPageNode);StyleUtil.setFont(button, Color.WHITE, -1);// 选中状态逻辑if (tempIndex != null) {Button node = (Button) leftMenu.getChildren().get(tempIndex);// 清空选中状态样式StyleUtil.setFont(node, Color.WHITE, -1);StyleUtil.setButtonBackground(node, LEFT_MENU_BUTTON_BACKGROUND_COLOR, Color.WHITE);}// 设置选中样式StyleUtil.setFont(button, LEFT_MENU_BUTTON_CLICK_BACKGROUND_COLOR, -1);tempIndex = currentMenuIndex;});buttonList.add(button);}return buttonList;}/*** 右侧页面路由*/private Node routePage(Pane root, String pageKey) {return PageNodeRenderFactory.newInstance(pageKey).render(root);}private void registerPageNodeRender() {PageNodeRenderFactory.registerNodeRender(MainPage.class);PageNodeRenderFactory.registerNodeRender(AnimalManagePage.class);PageNodeRenderFactory.fillPageNameMap();}public static void main(String[] args) {launch();}
}

2.2 数据库配置-db.setting

在这里插入图片描述

#------------------------------------------------------------------------------------------
## 基本配置信息
# JDBC URL,根据不同的数据库,使用相应的JDBC连接字符串
url = jdbc:mysql://localhost:3306/fx_demo?useUnicode=true&serverTimezone=UTC
# 用户名,此处也可以使用 user 代替
username = root
# 密码,此处也可以使用 pass 代替
password = root
# JDBC驱动名,可选(Hutool会自动识别)
# driver = com.mysql.jdbc.Driver## 可选配置
# 是否在日志中显示执行的SQL
showSql = true
# 是否格式化显示的SQL
formatSql = false
# 是否显示SQL参数
showParams = true
# 打印SQL的日志等级,默认debug
sqlLevel = debug
#------------------------------------------------------------------------------------------

2.3 日志文本域组件

对应于效果中的“操作记录”文本域。

package org.feng.demofx.pages;import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import lombok.Getter;
import org.feng.demofx.util.ControlUtil;
import org.feng.demofx.util.TimeUtil;import java.time.LocalDateTime;/*** 日志文本域组件** @author feng*/
@Getter
public class LogTextAreaComponent {private final TextArea textArea;private final VBox logBox;public LogTextAreaComponent(double height, double width) {// 控制台输入操作记录textArea = new TextArea();textArea.setScrollTop(Double.MAX_VALUE);textArea.setMaxHeight(height);textArea.setMaxWidth(width);textArea.setEditable(false);textArea.setStyle("-fx-text-fill: red");// 日志盒子logBox = new VBox();logBox.setMaxWidth(width);logBox.getChildren().add(new Label(""));Label operLogLabel = new Label("操作记录:");operLogLabel.setFont(Font.font(null, FontWeight.BOLD, 15));operLogLabel.setPadding(new Insets(5, 0, 5, 0));logBox.getChildren().add(operLogLabel);logBox.getChildren().add(textArea);// 清空日志记录按钮logBox.getChildren().add(new Label(""));Button clearLog = ControlUtil.genClearLogButton();logBox.getChildren().add(clearLog);clearLog.setOnMouseClicked(event -> {textArea.setText("");});}/*** 记录日志** @param text 日志内容*/public void log(String text) {textArea.appendText("【" + TimeUtil.parse(LocalDateTime.now()) + "】" + text + "\r\n");}
}

2.4 自定义表格视图组件

package org.feng.demofx.pages;import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableView;
import lombok.Data;
import org.feng.demofx.StartApplication;
import org.feng.demofx.util.TableColumnUtil;
import org.feng.demofx.vo.AnimalVo;import java.util.List;/*** 自定义表格视图组件** @author 01434188*/
@Data
public class CustomTableViewComponent<T> {/*** 表格视图*/private TableView<T> tableView;private ObservableList<T> data;public CustomTableViewComponent(Class<T> beanClass, List<T> dataList) {tableView = new TableView<>();// 设置可编辑tableView.setEditable(true);// 表格宽度tableView.setMaxWidth(((StartApplication.SCREEN_WIDTH * 0.8) - StartApplication.LEFT_MENU_WIDTH) * 0.8);// 设置可选择多行数据tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);// 解析表头和列信息TableColumnUtil.parseColumnsByClass(tableView.getColumns(), beanClass);// 添加表格数据data = FXCollections.observableArrayList();data.addAll(dataList);tableView.setItems(data);}public void resetData(List<T> newDataList) {ObservableList<T> list = FXCollections.observableArrayList();list.addAll(newDataList);data = list;tableView.setItems(list);}
}

2.5 自定义分页组件

package org.feng.demofx.pages;import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import lombok.Data;
import org.feng.demofx.util.ControlUtil;/*** 自定义分页组件** @author feng*/
@Data
public class CustomPagingComponent {/*** 每页条数*/private ComboBox<String> pageSize;/*** 当前页*/private TextField currentPage;/*** 上一页*/private Button lastPageButton;/*** 下一页*/private Button nextPageButton;/*** 跳转*/private Button skipPageButton;/*** 首页*/private Button firstPageButton;/*** 最后一页*/private Button finallyPageButton;/*** 分页面板*/private GridPane pagingGridPane;/*** 总页数*/private Label pageCount;public CustomPagingComponent(double width, double height) {this(width, height, null, null);}public CustomPagingComponent(double width, double height, Integer pageCount, Integer pageSize) {pagingGridPane = new GridPane();pagingGridPane.setMaxWidth(width);pagingGridPane.setMinWidth(width);pagingGridPane.setMaxHeight(height);pagingGridPane.setMinHeight(height);pagingGridPane.setPadding(new Insets(8, 0, 8, 0));// 设置下拉框,选择每页条数;默认15条this.pageSize = new ComboBox<>();this.pageSize.getItems().addAll("10", "15", "30", "50", "100");this.pageSize.setValue(pageSize == null ? "15" : String.valueOf(pageSize));// 当前页默认设置为1currentPage = new TextField();currentPage.setText("1");currentPage.setMaxWidth(35);// 上一页,下一页lastPageButton = ControlUtil.pagingButton("上一页");nextPageButton = ControlUtil.pagingButton("下一页");skipPageButton = ControlUtil.pagingButton("跳转");firstPageButton = ControlUtil.pagingButton("首页");finallyPageButton = ControlUtil.pagingButton("最后一页");// 总页数this.pageCount = new Label(String.format(" %s ", pageCount == null ? "0" : String.valueOf(pageCount)));// 设置垂直间距,水平间距pagingGridPane.setVgap(5);pagingGridPane.setHgap(3);pagingGridPane.add(new Label("总页数:"), 0, 0);pagingGridPane.add(this.pageCount, 1, 0);Node spacer1 = new Region();HBox.setHgrow(spacer1, Priority.ALWAYS);pagingGridPane.add(spacer1, 2, 0);pagingGridPane.add(firstPageButton, 3, 0);pagingGridPane.add(lastPageButton, 4, 0);pagingGridPane.add(currentPage, 5, 0);pagingGridPane.add(nextPageButton, 6, 0);pagingGridPane.add(finallyPageButton, 7, 0);pagingGridPane.add(skipPageButton, 8, 0);Node spacer2 = new Region();HBox.setHgrow(spacer2, Priority.ALWAYS);pagingGridPane.add(spacer2, 9, 0);pagingGridPane.add(this.pageSize, 10, 0);}public int getCurrentPageValue() {return Integer.parseInt(this.getCurrentPage().getText());}public void setCurrentPageValue(int currentPageValue) {this.getCurrentPage().setText(String.valueOf(currentPageValue));}public int getPageSizeValue() {return Integer.parseInt(this.getPageSize().getValue());}public void setPageSizeValue(int pageSizeValue) {this.getPageSize().setValue(String.valueOf(pageSizeValue));}public void setPageCountValue(int pageCountValue) {this.getPageCount().setText(String.valueOf(pageCountValue));}
}

2.6 动物管理页面

package org.feng.demofx.pages;import cn.hutool.core.bean.BeanUtil;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import lombok.Data;
import org.feng.demofx.StartApplication;
import org.feng.demofx.dao.impl.AnimalDao;
import org.feng.demofx.entity.bo.AnimalBO;
import org.feng.demofx.enums.AnimalSexEnum;
import org.feng.demofx.enums.AnimalTypeEnum;
import org.feng.demofx.service.AnimalService;
import org.feng.demofx.service.impl.AnimalServiceImpl;
import org.feng.demofx.sys.PageNodeKey;
import org.feng.demofx.sys.PageNodeRender;
import org.feng.demofx.util.*;
import org.feng.demofx.vo.AnimalVo;import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;/*** 动物管理界面** @author feng*/
@PageNodeKey(value = AnimalManagePage.PAGE_KEY, pageName = "动物管理")
public class AnimalManagePage implements PageNodeRender {public static final String PAGE_KEY = "animalManage";private final AnimalService animalService;public AnimalManagePage() {animalService = new AnimalServiceImpl(new AnimalDao());}@Overridepublic Node render(Pane pane) {VBox vbox = new VBox();// 当前容器内,布局居中,局上vbox.setAlignment(Pos.TOP_CENTER);// 当前面板背景颜色StyleUtil.setPaneBackground(vbox, Color.web("#fffff0"));// 页面标题vbox.getChildren().add(genPageTitle("动物管理页面"));final double width = ((StartApplication.SCREEN_WIDTH * 0.8) - StartApplication.LEFT_MENU_WIDTH) * 0.8;// 操作按钮,VBox oper = new VBox();HBox hBox = new HBox();hBox.setMaxWidth(250);oper.getChildren().add(hBox);Button addButton = ControlUtil.genAddButton();Button updateButton = ControlUtil.genUpdateButton();Button deleteButton = ControlUtil.genDeleteButton();Button refreshButton = ControlUtil.genRefreshButton();// 设置外边距,上、右,下,左oper.setPadding(new Insets(10, 0, 12, 0));oper.setAlignment(Pos.TOP_LEFT);oper.setMaxWidth(width);oper.setMaxHeight(200);Node spacer1 = new Region();HBox.setHgrow(spacer1, Priority.ALWAYS);Node spacer2 = new Region();HBox.setHgrow(spacer2, Priority.ALWAYS);Node spacer3 = new Region();HBox.setHgrow(spacer3, Priority.ALWAYS);hBox.getChildren().add(addButton);hBox.getChildren().add(spacer1);hBox.getChildren().add(updateButton);hBox.getChildren().add(spacer2);hBox.getChildren().add(deleteButton);hBox.getChildren().add(spacer3);hBox.getChildren().add(refreshButton);vbox.getChildren().add(oper);//  搜索面板SearchAnimalPane searchAnimalPane = new SearchAnimalPane(oper.getMaxWidth());vbox.getChildren().add(searchAnimalPane.getSearchPane());// 分页组件CustomPagingComponent customPagingComponent = new CustomPagingComponent(width, 60);// 控制台输入操作记录LogTextAreaComponent logger = new LogTextAreaComponent(400, width);// 表格视图PageBean<AnimalVo> pageBean = new PageBean<>(customPagingComponent.getPageSizeValue(),customPagingComponent.getCurrentPageValue(), 0);animalService.listPage(searchAnimalPane.genAnimalBo(), pageBean);customPagingComponent.setPageCountValue(pageBean.getSumPageCount());CustomTableViewComponent<AnimalVo> tableViewComponent = new CustomTableViewComponent<>(AnimalVo.class, pageBean.getData());TableView<AnimalVo> animalTableView = tableViewComponent.getTableView();// 表格展示数据+分页vbox.getChildren().add(animalTableView);vbox.getChildren().add(customPagingComponent.getPagingGridPane());// 分隔线vbox.getChildren().add(ControlUtil.separator(animalTableView.getMaxWidth()));// 操作记录vbox.getChildren().add(logger.getLogBox());// 注册刷新refreshButton.setOnAction(event -> {ControlUtil.refreshTableView(animalTableView, logger);});// 更改每页大小-事件处理customPagingComponent.getPageSize().setOnAction(event -> {int pageSize = customPagingComponent.getPageSizeValue();logger.log(String.format("修改每页大小为:%s,重新刷新列表!", pageSize));// 设置每页大小pageBean.setPageSize(pageSize);// 重新分页查询第一页数据refreshToFirstPage(pageBean, searchAnimalPane, customPagingComponent);// 刷新列表tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);});// 上一页customPagingComponent.getLastPageButton().setOnAction(event -> {// 当前页int currentPage = customPagingComponent.getCurrentPageValue();String canQuery = pageBean.setCurrentPageNo(currentPage - 1);if (StringUtil.isNotEmpty(canQuery)) {logger.log(canQuery);return;}animalService.listPage(searchAnimalPane.genAnimalBo(), pageBean);customPagingComponent.setPageCountValue(pageBean.getSumPageCount());customPagingComponent.setCurrentPageValue(currentPage - 1);// 刷新列表tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);});// 下一页customPagingComponent.getNextPageButton().setOnAction(event -> {// 当前页int currentPage = customPagingComponent.getCurrentPageValue();String canQuery = pageBean.setCurrentPageNo(currentPage + 1);if (StringUtil.isNotEmpty(canQuery)) {logger.log(canQuery);return;}animalService.listPage(searchAnimalPane.genAnimalBo(), pageBean);customPagingComponent.setCurrentPageValue(currentPage + 1);customPagingComponent.setPageCountValue(pageBean.getSumPageCount());// 刷新列表tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);});// 首页事件customPagingComponent.getFirstPageButton().setOnAction(event -> {refreshToFirstPage(pageBean, searchAnimalPane, customPagingComponent);logger.log("跳转首页成功!");// 刷新列表tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);});// 最后一页customPagingComponent.getFinallyPageButton().setOnAction(event -> {pageBean.setCurrentPageNo(pageBean.getSumPageCount());animalService.listPage(searchAnimalPane.genAnimalBo(), pageBean);customPagingComponent.setPageCountValue(pageBean.getSumPageCount());customPagingComponent.setCurrentPageValue(pageBean.getSumPageCount());// 刷新列表tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);});// 跳转事件customPagingComponent.getSkipPageButton().setOnAction(event -> {int currentPage = customPagingComponent.getCurrentPageValue();if(currentPage < 1) {currentPage = 1;}pageBean.setCurrentPageNo(currentPage);animalService.listPage(searchAnimalPane.genAnimalBo(), pageBean);// 如果输入的当前页大于总页数,修复跳转至最后一页if(currentPage > pageBean.getSumPageCount()) {currentPage = pageBean.getSumPageCount();pageBean.setCurrentPageNo(currentPage);animalService.listPage(searchAnimalPane.genAnimalBo(), pageBean);}customPagingComponent.setPageCountValue(pageBean.getSumPageCount());customPagingComponent.setCurrentPageValue(currentPage);logger.log(String.format("跳转第【%s】页成功!", currentPage));// 刷新列表tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);});// 当选择发生变化时调用该函数-选择某一行时animalTableView.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> {if (newVal != null && !animalTableView.getSelectionModel().isSelected(newVal.getId())) {logger.log("已选择 " + newVal.getName());}});// 注册搜索searchAnimalPane.getSearchButton().setOnAction(event -> {refreshToFirstPage(pageBean, searchAnimalPane, customPagingComponent);logger.log("搜索成功!");// 刷新列表tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);});// 注册删除deleteButton.setOnAction(ControlUtil.alertConfirm("确认删除吗?", "", buttonType -> {ButtonBar.ButtonData buttonData = buttonType.getButtonData();if (buttonData.isDefaultButton()) {// 确认删除ObservableList<AnimalVo> items = animalTableView.getSelectionModel().getSelectedItems();List<Long> ids = items.stream().mapToLong(vo -> Long.valueOf(vo.getId())).boxed().toList();logger.log("正在删除 " + items.stream().map(AnimalVo::getName).collect(Collectors.joining(",")));animalService.delete(ids);// 刷新列表refreshToFirstPage(pageBean, searchAnimalPane, customPagingComponent);tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);logger.log("删除 " + items.stream().map(AnimalVo::getName).collect(Collectors.joining(",")) + "成功!");}}));// 注册新增addButton.setOnAction(event -> {AddAndUpdateAnimalDialog addDialog = new AddAndUpdateAnimalDialog(null);addDialog.getDialog().showAndWait().ifPresent(buttonType -> {if (buttonType.getButtonData().isDefaultButton()) {logger.log("开始新增数据");// 获取文本框中数据AnimalBO animalBO = addDialog.genAnimalBo();logger.log("正在新增 " + animalBO.getName());// 添加动物animalService.add(animalBO);// 刷新列表refreshToFirstPage(pageBean, searchAnimalPane, customPagingComponent);tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);logger.log("新增 " + animalBO.getName() + "成功!");}});addDialog.getDialog().close();});// 注册更新updateButton.setOnAction(event -> {ObservableList<AnimalVo> selectedItems = animalTableView.getSelectionModel().getSelectedItems();if (selectedItems == null || selectedItems.size() != 1) {logger.log("请选择一条数据进行修改");return;}// 获取选中的数据原值AnimalVo selectedAnimal = selectedItems.get(0);AddAndUpdateAnimalDialog updateDialog = new AddAndUpdateAnimalDialog(selectedAnimal);// 注册点击事件updateDialog.getDialog().showAndWait().ifPresent(buttonType -> {if (buttonType.getButtonData().isDefaultButton()) {logger.log("开始修改数据");// 获取文本框中数据AnimalBO animalBO = updateDialog.genAnimalBo();animalBO.setId(selectedAnimal.getId().longValue());logger.log(String.format("正在修改ID为【%s】,名字为【%s】 ", selectedAnimal.getId(), updateDialog.getOldAnimal().getName()));// 更新动物animalService.update(animalBO);// 刷新列表refreshToFirstPage(pageBean, searchAnimalPane, customPagingComponent);tableViewComponent.resetData(pageBean.getData());ControlUtil.refreshTableView(animalTableView, logger);logger.log(String.format("修改完成! ID为【%s】,修改名字【%s】为【%s】,动物类型【%s】为【%s】,年龄【%s】为【%s】", selectedAnimal.getId(), updateDialog.getOldAnimal().getName(), animalBO.getName(),updateDialog.getOldAnimal().getAnimalType(), animalBO.getAnimalType().getDesc(), updateDialog.getOldAnimal().getAge(), animalBO.getAge()));}});updateDialog.getDialog().close();});// 动物管理页面初始化完成,刷新一次ControlUtil.refreshTableView(animalTableView, logger);return vbox;}/*** 刷新列表数据至第一页*/private void refreshToFirstPage(PageBean<AnimalVo> pageBean, SearchAnimalPane searchAnimalPane, CustomPagingComponent customPagingComponent) {pageBean.setCurrentPageNo(1);animalService.listPage(searchAnimalPane.genAnimalBo(), pageBean);customPagingComponent.setPageCountValue(pageBean.getSumPageCount());customPagingComponent.setCurrentPageValue(1);}@Dataprivate static class SearchAnimalPane {// 折叠面板private TitledPane searchPane;private TextField searchNameTextField;private TextField searchAgeTextField;private ComboBox<String> searchTypeComboBox;private ComboBox<String> searchSexComboBox;private DatePicker createDateStart;private DatePicker createDateEnd;private DatePicker updateDateStart;private DatePicker updateDateEnd;private Button searchButton;public SearchAnimalPane(double width) {// 定义搜索网格面板GridPane searchGridPane = new GridPane();// 设置垂直间距,水平间距searchGridPane.setVgap(10);searchGridPane.setHgap(5);searchNameTextField = new TextField();searchAgeTextField = new TextField();searchTypeComboBox = new ComboBox<>();searchTypeComboBox.getItems().addAll(Arrays.stream(AnimalTypeEnum.values()).map(AnimalTypeEnum::getDesc).toList());searchSexComboBox = new ComboBox<>();searchSexComboBox.getItems().addAll(Arrays.stream(AnimalSexEnum.values()).map(AnimalSexEnum::getDesc).toList());searchButton = ControlUtil.genSearchButton();Button clearButton = ControlUtil.genClearButton();createDateStart = new DatePicker();createDateEnd = new DatePicker();updateDateStart = new DatePicker();updateDateEnd = new DatePicker();createDateStart.setEditable(true);createDateEnd.setEditable(true);updateDateStart.setEditable(true);updateDateEnd.setEditable(true);searchGridPane.add(new Label("名字 "), 0, 0);searchGridPane.add(searchNameTextField, 1, 0);searchGridPane.add(new Label("年龄 "), 0, 1);searchGridPane.add(searchAgeTextField, 1, 1);searchGridPane.add(new Label("类型 "), 0, 2);searchGridPane.add(searchTypeComboBox, 1, 2);searchGridPane.add(new Label("性别 "), 0, 3);searchGridPane.add(searchSexComboBox, 1, 3);searchGridPane.add(new Label("创建日期起止 "), 0, 4);searchGridPane.add(new Label("更新日期起止 "), 0, 5);searchGridPane.add(createDateStart, 1, 4);searchGridPane.add(createDateEnd, 2, 4);searchGridPane.add(updateDateStart, 1, 5);searchGridPane.add(updateDateEnd, 2, 5);searchGridPane.add(clearButton, 0, 7);searchGridPane.add(searchButton, 1, 7);// 折叠面板-搜索searchPane = new TitledPane("高级搜索", searchGridPane);// 设置外边距,上、右,下,左searchPane.setPadding(new Insets(0, 0, 8, 0));searchPane.setMaxWidth(width);// 设置可折叠searchPane.setCollapsible(true);// 设置折叠时的动画searchPane.setAnimated(true);// 注册清空参数事件clearButton.setOnAction(event -> {clearSearchParam();});}public void clearSearchParam() {searchNameTextField.setText("");searchAgeTextField.setText("");searchTypeComboBox.setValue("");searchSexComboBox.setValue("");createDateStart.setValue(null);createDateEnd.setValue(null);updateDateStart.setValue(null);updateDateEnd.setValue(null);}public AnimalBO genAnimalBo() {String searchNameText = this.getSearchNameTextField().getText();String searchAgeText = this.getSearchAgeTextField().getText();String searchTypeValue = this.getSearchTypeComboBox().getValue();String searchSexValue = this.getSearchSexComboBox().getValue();LocalDate createDateStartValue = this.getCreateDateStart().getValue();LocalDate createDateEndValue = this.getCreateDateEnd().getValue();LocalDate updateDateStartValue = this.getUpdateDateStart().getValue();LocalDate updateDateEndValue = this.getUpdateDateEnd().getValue();AnimalVo animalVo = new AnimalVo();if (StringUtil.isNotEmpty(searchNameText)) {animalVo.setName(searchNameText);}if (StringUtil.isNotEmpty(searchAgeText)) {animalVo.setAge(Integer.parseInt(searchAgeText));}if (StringUtil.isNotEmpty(searchTypeValue)) {animalVo.setAnimalType(searchTypeValue);}if (StringUtil.isNotEmpty(searchSexValue)) {animalVo.setAnimalSex(searchSexValue);}// 创建时间起、止选择后生效if (Objects.nonNull(createDateStartValue) || Objects.nonNull(createDateEndValue)) {animalVo.setCreateDateRange(new DateRange(createDateStartValue, createDateEndValue));}// 更新时间起、止选择后生效if (Objects.nonNull(updateDateStartValue) || Objects.nonNull(updateDateEndValue)) {animalVo.setUpdateDateRange(new DateRange(updateDateStartValue, updateDateEndValue));}return animalVo.toAnimalBo();}}@Dataprivate static class AddAndUpdateAnimalDialog {private Dialog<ButtonType> dialog;private TextField nameTextField;private TextField ageTextField;private ComboBox<String> typeComboBox;private ComboBox<String> sexComboBox;private TextArea remarkTextArea;private AnimalVo oldAnimal;public AddAndUpdateAnimalDialog(AnimalVo animalVo) {Label nameLabel = new Label("名字 ");nameTextField = new TextField();Label ageLabel = new Label("年龄 ");ageTextField = new TextField();Label typeLabel = new Label("类型 ");typeComboBox = new ComboBox<>();typeComboBox.getItems().addAll(Arrays.stream(AnimalTypeEnum.values()).map(AnimalTypeEnum::getDesc).toList());Label sexLabel = new Label("性别 ");sexComboBox = new ComboBox<>();sexComboBox.getItems().addAll(Arrays.stream(AnimalSexEnum.values()).map(AnimalSexEnum::getDesc).toList());Label remarkLabel = new Label("备注 ");remarkTextArea = new TextArea();remarkTextArea.setScrollTop(Double.MAX_VALUE);remarkTextArea.setEditable(true);remarkTextArea.setMaxHeight(250);remarkTextArea.setMaxWidth(300);if (animalVo == null) {typeComboBox.setValue(AnimalTypeEnum.UN_KNOW.getDesc());sexComboBox.setValue(AnimalSexEnum.UN_KNOW.getDesc());} else {oldAnimal = new AnimalVo();BeanUtil.copyProperties(animalVo, oldAnimal);// 数据回显nameTextField.setText(oldAnimal.getName());ageTextField.setText(String.valueOf(oldAnimal.getAge()));typeComboBox.setValue(oldAnimal.getAnimalType());sexComboBox.setValue(oldAnimal.getAnimalSex());remarkTextArea.setText(oldAnimal.getRemark());}// 定义网格面板GridPane gridPane = new GridPane();// 设置垂直间距,水平间距gridPane.setVgap(10);gridPane.setHgap(5);gridPane.add(nameLabel, 0, 0);gridPane.add(nameTextField, 1, 0);gridPane.add(ageLabel, 0, 1);gridPane.add(ageTextField, 1, 1);gridPane.add(typeLabel, 0, 2);gridPane.add(typeComboBox, 1, 2);gridPane.add(sexLabel, 0, 3);gridPane.add(sexComboBox, 1, 3);gridPane.add(remarkLabel, 0, 4);gridPane.add(remarkTextArea, 1, 4);DialogPane dialogPane = new DialogPane();dialogPane.setPrefHeight(300);dialogPane.setPrefWidth(500);dialogPane.setMaxHeight(400);dialogPane.setMaxWidth(550);dialogPane.setContent(gridPane);dialogPane.getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK);dialog = new Dialog<>();dialog.setDialogPane(dialogPane);}public AnimalBO genAnimalBo() {AnimalBO animalBO = new AnimalBO();// 年龄animalBO.setAge(Integer.parseInt(this.getAgeTextField().getText()));// 姓名animalBO.setName(this.getNameTextField().getText());// 获取下拉框的数据:动物类型String type = this.getTypeComboBox().getValue();animalBO.setAnimalType(AnimalTypeEnum.getByDesc(type));// 获取下拉框的数据:性别String sex = this.getSexComboBox().getValue();animalBO.setAnimalSex(AnimalSexEnum.getByDesc(sex));// 获取文本域内容:备注animalBO.setRemark(this.getRemarkTextArea().getText());return animalBO;}}
}

2.7 页面工厂

package org.feng.demofx.sys;import org.feng.demofx.util.StringUtil;import java.lang.reflect.InvocationTargetException;
import java.util.*;/*** PageNodeRender工厂** @author feng*/
public class PageNodeRenderFactory {private static final Map<String, PageNodeRender> PAGE_NODE_RENDER_MAP = new HashMap<>(8);private static final Set<PageNodeDefine> PAGE_NODE_DEFINES = new TreeSet<>(Comparator.comparingInt(PageNodeDefine::getOrder).thenComparing(PageNodeDefine::getPageKey));private static final Map<String, String> PAGE_NAME_MAP = new LinkedHashMap<>();private static final Map<String, String> RESERVE_PAGE_NAME_MAP = new LinkedHashMap<>();public static PageNodeRender newInstance(String pageKey) {return PAGE_NODE_RENDER_MAP.get(pageKey);}public static Map<String, String> getPageNameMap() {return PAGE_NAME_MAP;}public static String getPageKeyByName(String pageName) {return RESERVE_PAGE_NAME_MAP.get(pageName);}public static void registerNodeRender(Class<? extends PageNodeRender> renderClass) {try {// 处理PageNodeRender#getPageKey()PageNodeRender pageNodeRender = renderClass.getDeclaredConstructor().newInstance();String pageKey = pageNodeRender.getPageKey();if (StringUtil.isNotEmpty(pageKey)) {PAGE_NODE_RENDER_MAP.put(pageKey, pageNodeRender);PageNodeDefine pageNodeDefine = new PageNodeDefine();pageNodeDefine.setPageKey(pageKey);pageNodeDefine.setPageName(pageNodeRender.getPageName());pageNodeDefine.setOrder(pageNodeRender.order());PAGE_NODE_DEFINES.add(pageNodeDefine);return;}// 处理PageNodeKey注解if (renderClass.isAnnotationPresent(PageNodeKey.class)) {PageNodeKey pageNodeKey = renderClass.getAnnotation(PageNodeKey.class);pageKey = pageNodeKey.value();if (StringUtil.isNotEmpty(pageKey)) {PAGE_NODE_RENDER_MAP.put(pageKey, pageNodeRender);PageNodeDefine pageNodeDefine = new PageNodeDefine();pageNodeDefine.setPageKey(pageKey);pageNodeDefine.setPageName(pageNodeKey.pageName());pageNodeDefine.setOrder(pageNodeKey.order());PAGE_NODE_DEFINES.add(pageNodeDefine);return;}}throw new IllegalArgumentException(renderClass.getName() + "定义错误,请检查");} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |IllegalAccessException e) {throw new RuntimeException(e);}}public static void fillPageNameMap() {PAGE_NODE_DEFINES.forEach(pageNodeDefine -> {PAGE_NAME_MAP.put(pageNodeDefine.getPageKey(), pageNodeDefine.getPageName());RESERVE_PAGE_NAME_MAP.put(pageNodeDefine.getPageName(), pageNodeDefine.getPageKey());});}
}

附录

附1:sql脚本

CREATE TABLE `fx_animal`
(`id`          BIGINT       NOT NULL AUTO_INCREMENT,`name`        VARCHAR(255) NOT NULL COMMENT '名字',`animal_type` INT          NOT NULL DEFAULT - 1 COMMENT '动物类型,-1 未知',`animal_sex`  INT          NOT NULL DEFAULT - 1 COMMENT '动物性别,-1 未知 0 雄性 1雌性',`age`         INT          NOT NULL DEFAULT 0 COMMENT '年龄',`update_time` datetime     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',`create_time` datetime     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`remark`      VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备注',PRIMARY KEY (`id`)
);INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (1, '小名', 0, 1, 2, '2024-01-19 23:10:36', '2024-01-19 22:31:53', '呜呜呜汪汪汪');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (2, '小红', 1, 0, 0, '2024-01-19 23:50:17', '2024-01-19 22:31:59', '00000');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (3, '啊华', 1, 1, 2, '2024-01-19 23:13:46', '2024-01-19 23:13:46', '喵喵喵');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (4, '小吗', 1, 1, 2, '2024-01-22 23:34:09', '2024-01-22 23:34:09', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (5, '待机', -1, -1, 2, '2024-01-22 23:34:56', '2024-01-22 23:34:56', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (6, '松紧带哦哦', -1, -1, 21, '2024-01-22 23:35:05', '2024-01-22 23:35:05', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (7, '额温枪', -1, -1, 21, '2024-01-22 23:35:10', '2024-01-22 23:35:10', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (8, '大萨达', -1, -1, 2, '2024-01-22 23:35:16', '2024-01-22 23:35:16', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (9, '哇打算', -1, -1, 21, '2024-01-22 23:35:21', '2024-01-22 23:35:21', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (10, '大东方闪电', -1, -1, 22, '2024-01-22 23:35:37', '2024-01-22 23:35:37', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (11, '2多发点', -1, -1, 4322, '2024-01-22 23:35:50', '2024-01-22 23:35:50', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (12, '绕弯儿', -1, -1, 32, '2024-01-22 23:37:23', '2024-01-22 23:37:23', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (13, '法国掉头发', -1, -1, 32, '2024-01-22 23:37:30', '2024-01-22 23:37:30', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (14, '43给对方刚刚', -1, -1, 32, '2024-01-22 23:37:36', '2024-01-22 23:37:36', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (15, '手动挡', -1, -1, 2, '2024-01-22 23:37:45', '2024-01-22 23:37:45', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (16, '发得分', -1, -1, 32, '2024-01-22 23:37:53', '2024-01-22 23:37:53', '');
INSERT INTO `fx_demo`.`fx_animal`(`id`, `name`, `animal_type`, `animal_sex`, `age`, `update_time`, `create_time`, `remark`) VALUES (17, '明明', 1, 1, 13, '2024-01-24 21:03:58', '2024-01-24 21:03:21', '修改了一次年龄');

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/645050.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL怎么根据当前时间获取连续十二个月统计数据

需求 在某些业务场景中&#xff0c;需要后台获取连续十二个月的统计数据&#xff0c;如下图&#xff1a; 解决方式 1、创建一张临时表&#xff0c;在表中插入序号数据 该表的最大数量决定统计返回的最大条数 CREATE TABLE sys_redundancy (id bigint(22) NOT NULL AUTO_I…

uniapp 链接跳转(内部跳转和外部跳转)

使用uniapp的超链接跳转在微信小程序中会出现复制链接在外面在跳转如图 这样的客户体验感不好 我们需要可以直接跳转查看 思路&#xff1a;webview 1.先在自己uniapp项目pages.json建一个内部页面webview.vue 在page.json里面指向我们跳转的这个内部路径(这个创建页面会自动…

【Conda】超详细的linux-conda环境安装教程

背景 最近被python各个版本环境整的头晕目眩&#xff0c;本来就不是专长做python的&#xff0c;切换各种版本着实不好操作&#xff0c;因此想到了conda这个好工具&#xff0c;以下是对conda的相关理解和搭建的详细过程&#xff0c;做个记录。 Conda简介 Conda是在Windows、m…

SwiftUI 打造酷炫流光边框 + 微光滑动闪烁的 3D 透视滚动卡片墙

功能需求 有时候我们希望自己的 App 能向用户展示与众不同、富有创造力的酷炫视觉效果: 如上图所示,我们制作了一款流光边框 + 微光滑动闪烁的 3D 透视卡片滚动效果。这是怎么做到的呢? 在本篇博文中,您将学到以下内容 功能需求1. 3D 透视滚动2. 灵动边框流光效果3. 背景…

黑马苍穹外卖学习Day10

文章目录 Spring Task介绍cron表达式入门案例 订单状态定时处理需求分析代码开发功能测试 WebSocket介绍入门案例 来单提醒需求分析代码开发 客户催单需求分析代码开发 Spring Task 介绍 cron表达式 入门案例 订单状态定时处理 需求分析 代码开发 新建一个task包里面编写代码…

ShardingSphere数据库中间件

数据库中的数据量猛增&#xff0c;访问性能也变慢了&#xff0c;优化迫在眉睫 ? 1. 关系型数据库本身比较容易成为系统瓶颈&#xff1a;单机存储容量、数据库连接数、处理能力都有限。 2. 当单表的数据量达到 1000W 或 100G 以后&#xff0c;由于查询维度较多&#xff0c;即…

JS高频面试题(下)

11. 线程和进程的区别 进程是资源分配的最小单元&#xff0c;线程是代码执行的最小单元。 一个应用程序可能会开启多个进程&#xff0c;进程之间数据不共享&#xff0c;一个进程内部可以开启多个线程&#xff0c;线程之间的数据可以共享的&#xff0c;所以多线程的情况下&…

探索设计模式的魅力:深入理解面向对象设计的深层原则与思维

如何同时提高一个软件系统的可维护性 和 可复用性是面向对象对象要解决的核心问题。 通过学习和应用设计模式&#xff0c;可以更加深入地理解面向对象的设计理念&#xff0c;从而帮助设计师改善自己的系统设计。但是&#xff0c;设计模式并不能够提供具有普遍性的设计指导原则。…

运维神器Ansible的常用模块

引言&#xff1a;话不多说&#xff0c;今天分享一下Ansible的常用模块&#xff0c;建议收藏哦 1、ping模块 ping模块可以进行主机连通性测试 命令格式 ansible 主机或主机组 -m ping 例&#xff0c;成功显示如下&#xff1a; 2、command 模块 command模块可以直接在远程主机…

C#使用DateTime.Now.AddDays方法获取任一天的信息

目录 一、使用DateTime对象的AddDays方法获取任一天信息方法 二、举例说明获取昨天的信息 三、涉及到的知识点 1. MessageBox.Show(&#xff09;中信息分行的办法 使用DateTime.Now属性可以得到当前的日期信息&#xff0c;此时调用ToString方法&#xff0c;并在该方法中添加…

【Python编程工具】【ssh连接Docker容器】如何使用Docker容器里的python环境,如何调试在容器中的代码

文章目录 方案一览Gateway软件介绍启动容器配置apt源在容器中安装SSH服务器配置SSH服务器生成SSH密钥启动SSH服务为root创建密码连接到容器使用Gateway 方案一览 本篇博客将介绍如何在Docker容器中打开SSH连接服务&#xff0c;以及如何使用JetBrains Gateway软件进行代码调试。…

基于springboot+vue的社区医院信息平台系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

vp9协议笔记

vp9协议笔记&#x1f4d2; 本文主要是对vp9协议的梳理&#xff0c;协议的细节参考官方文档&#xff1a;VP9协议链接&#xff08;需要加速器&#xff09; vp9协议笔记 vp9协议笔记&#x1f4d2;1. 视频编码概述2. 超级帧superframe&#xff08;sz&#xff09;&#xff1a;2. fr…

VBA即用型代码手册之改变主窗口标题栏名称及隐藏工作表

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。可以大大提高自己的劳动效率&#xff0c;而且可以提高数据的准确性。我这里专注VBA,将我多年的经验汇集在VBA系列九套教程中。 作为我的学员要利用我的积木编程思想&#xff0c;积木编程最重要的是积木如何搭建…

JavaFX场景入门

目录 JAVAFX jdk1.8以上引入javafx类库 JDK11JAVAFX(eclipse) 小知识点 舞台Stage platform、screen类 Scene场景类 查看电脑屏幕宽高 Group容器 JAVAFX项目 Image javafx场景 javaFx文本 javaFX颜色 JAVAFX jdk1.8以上引入javafx类库 JDK11JAVAFX(eclipse) 方式…

threejs学习

重要概念&#xff08;场景、相机、渲染器&#xff09; 如下图所示&#xff0c;我们最终看到浏览器上生成的内容是通过虚拟场景和虚拟相机被渲染器渲染后的结果&#xff0c;下面首先介绍这三个概念&#xff0c;将贯穿所有简单复杂的threejs项目。 场景 Scene 虚拟的3D场景&a…

扫码登录流程

扫码登录 场景 在网页版qq邮箱&#xff0c;微信登录账号等时候&#xff0c;无需输入账号和密码&#xff0c;只需要在手机上扫码即可完成登录 登录分析 扫码登录涉及3种角色&#xff1a; PC端&#xff0c; 手机端&#xff0c; 服务端 涉及围绕这三端进行&#xff0c;每一端…

代码随想录算法训练营第四十二天|01背包问题、01背包问题(滚动数组)、416. 分割等和子集

题目&#xff1a;01背包问题 文章链接&#xff1a;代码随想录 视频链接&#xff1a;LeetCode:背包问题 题目链接&#xff1a;卡码题目链接 图释&#xff1a; //二维dp数组实现 #include <bits/stdc.h> using namespace std;int n, bagweight;// bagweight代表行李箱空…

打 jar 包运行 在windows 平台控制台和日志 乱码解决

--拒絕鷄巴囉嗦&#xff0c;直接解決問題 我们在Windows下运行jar包时&#xff0c;常常会出现乱码&#xff0c;主要分为dos窗口输出的日志中出现乱码和程序返回数据出现乱码。 dos窗口输出的日志中出现乱码 执行如下命令&#xff0c;将控制台输出编码改为UTF8&#xff1a; ch…

Python接口自动化测试实战

接口自动化测试是指通过编写程序来模拟用户的行为&#xff0c;对接口进行自动化测试。Python是一种流行的编程语言&#xff0c;它在接口自动化测试中得到了广泛应用。下面详细介绍Python接口自动化测试实战。 1、接口自动化测试框架 在Python接口自动化测试中&#xff0c;我们…