From a143e6a01064e0353f6e64854e557291785ab8f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E7=99=BD=E4=B8=8E=E5=AD=9F=E6=B5=A9=E7=84=B6?=
<1063889643@qq.com>
Date: Thu, 28 Sep 2023 17:21:12 +0800
Subject: [PATCH 1/2] =?UTF-8?q?#I806RK=20state=20to=20=E8=BF=9B=E8=A1=8C?=
=?UTF-8?q?=E4=B8=AD=20=E5=9F=BA=E6=9C=AC=E6=A0=B7=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 12 +-
...ialApplication.java => GitManagerApp.java} | 62 ++++++----
src/main/java/com/light/LogApplication.java | 26 ----
src/main/java/com/light/LogService.java | 18 ---
.../java/com/light/layout/ContentPane.java | 14 +++
src/main/java/com/light/layout/MenuPane.java | 63 ++++++++++
src/main/java/com/light/layout/NavItem.java | 51 ++++++++
src/main/java/com/light/util/FxUtil.java | 114 ++++++++++++++++++
src/main/java/com/light/util/H2Utils.java | 4 +
src/main/java/com/light/util/NodeUtils.java | 29 +++++
src/main/java/module-info.java | 3 +
11 files changed, 323 insertions(+), 73 deletions(-)
rename src/main/java/com/light/{TutorialApplication.java => GitManagerApp.java} (30%)
delete mode 100644 src/main/java/com/light/LogApplication.java
delete mode 100644 src/main/java/com/light/LogService.java
create mode 100644 src/main/java/com/light/layout/ContentPane.java
create mode 100644 src/main/java/com/light/layout/MenuPane.java
create mode 100644 src/main/java/com/light/layout/NavItem.java
create mode 100644 src/main/java/com/light/util/FxUtil.java
create mode 100644 src/main/java/com/light/util/H2Utils.java
create mode 100644 src/main/java/com/light/util/NodeUtils.java
diff --git a/pom.xml b/pom.xml
index 4ddcd58..882fede 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,10 +9,10 @@
1.0-SNAPSHOT
- 20
- 20
+ 21
+ 21
UTF-8
- 20.0.2
+ 21
2.0.1
@@ -106,6 +106,12 @@
atlantafx-base
${atlantafx.version}
+
+ org.jetbrains
+ annotations
+ 23.0.0
+ compile
+
diff --git a/src/main/java/com/light/TutorialApplication.java b/src/main/java/com/light/GitManagerApp.java
similarity index 30%
rename from src/main/java/com/light/TutorialApplication.java
rename to src/main/java/com/light/GitManagerApp.java
index 97bb58e..6cccd4f 100644
--- a/src/main/java/com/light/TutorialApplication.java
+++ b/src/main/java/com/light/GitManagerApp.java
@@ -1,45 +1,55 @@
package com.light;
+import atlantafx.base.theme.PrimerLight;
+import com.light.layout.ContentPane;
+import com.light.layout.MenuPane;
+import com.light.util.NodeUtils;
import javafx.application.Application;
+import javafx.geometry.Insets;
import javafx.scene.Scene;
-import javafx.scene.control.Label;
import javafx.scene.image.Image;
-import javafx.scene.layout.*;
-import javafx.scene.paint.Color;
-import javafx.scene.text.Font;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
import javafx.stage.Stage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-/**
- * TODO 例子,后续移除
- */
-public class TutorialApplication extends Application {
+public class GitManagerApp extends Application {
- public static void main(String[] args) {
- launch(args);
- }
+ public static final Logger LOGGER = LoggerFactory.getLogger(GitManagerApp.class);
@Override
public void start(Stage stage) throws Exception {
- // label
- Label l = new Label("Hello");
- l.setFont(Font.font(20));
-
- BorderPane root = new BorderPane(l);
-
- root.setTop(getPane("blue"));
- root.setLeft(getPane("green"));
-
- Scene scene = new Scene(root, 1096, 768);
+ // 主题
+ Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
+
+ // 根节点
+ AnchorPane root = new AnchorPane();
+
+ // 左右布局
+ HBox container = new HBox();
+ // 内容
+ ContentPane contentPane = new ContentPane();
+ // 菜单
+ MenuPane menuPane = new MenuPane(contentPane);
+ container.getChildren().addAll(menuPane, contentPane);
+ HBox.setHgrow(contentPane, Priority.ALWAYS);
+
+ root.getChildren().add(container);
+ NodeUtils.setAnchors(root, Insets.EMPTY);
+
+ // 场景
+ Scene scene = new Scene(root, 1000, 600);
stage.setTitle("Git批量管理工具");
stage.getIcons().add(new Image(this.getClass().getResource("/icons/git.png").toExternalForm()));
stage.setScene(scene);
stage.show();
+
+ LOGGER.info("项目启动完成。。。");
}
- public Pane getPane(String color) {
- Pane pane = new Pane();
- pane.setPrefSize(100.0, 100.0);
- pane.setStyle("-fx-background-color: " + color);
- return pane;
+ public static void main(String[] args) {
+ launch(args);
}
}
diff --git a/src/main/java/com/light/LogApplication.java b/src/main/java/com/light/LogApplication.java
deleted file mode 100644
index da176e6..0000000
--- a/src/main/java/com/light/LogApplication.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.light;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-/**
- * 日志使用示例,后续删除
- */
-public class LogApplication {
-
- public static final Logger LOGGER = LoggerFactory.getLogger(LogApplication.class);
- private static final Logger COMMON_LOGGER = LoggerFactory.getLogger("COMMON");
-
- public static void main(String[] args) {
- for (int i = 0; i < 10; i++) {
- LogService logService = new LogService();
- LOGGER.info("这是info日志");
- LOGGER.error("这是error日志");
- LOGGER.warn("这是warn日志");
- LOGGER.debug("这是debug日志");
- COMMON_LOGGER.info("这是common的info日志");
- COMMON_LOGGER.warn("这是common的warn日志");
- COMMON_LOGGER.debug("这是common的debug日志");
- }
-
- }
-}
diff --git a/src/main/java/com/light/LogService.java b/src/main/java/com/light/LogService.java
deleted file mode 100644
index eef7698..0000000
--- a/src/main/java/com/light/LogService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.light;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 日志使用示例,后续删除
- */
-public class LogService {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(LogService.class);
-
- public LogService() {
- LOGGER.info("这是com.leo.service中的info日志");
- LOGGER.warn("这是com.leo.service中的warn日志");
- LOGGER.debug("这是com.leo.service中的debug日志");
- }
-}
diff --git a/src/main/java/com/light/layout/ContentPane.java b/src/main/java/com/light/layout/ContentPane.java
new file mode 100644
index 0000000..d08b986
--- /dev/null
+++ b/src/main/java/com/light/layout/ContentPane.java
@@ -0,0 +1,14 @@
+package com.light.layout;
+
+import javafx.scene.Node;
+import javafx.scene.layout.BorderPane;
+
+public class ContentPane extends BorderPane {
+
+ public ContentPane() {
+ }
+
+ public void setContent(Node content) {
+ setCenter(content);
+ }
+}
diff --git a/src/main/java/com/light/layout/MenuPane.java b/src/main/java/com/light/layout/MenuPane.java
new file mode 100644
index 0000000..e2e2602
--- /dev/null
+++ b/src/main/java/com/light/layout/MenuPane.java
@@ -0,0 +1,63 @@
+package com.light.layout;
+
+import javafx.geometry.Orientation;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListView;
+import javafx.scene.control.Separator;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled;
+import org.kordamp.ikonli.antdesignicons.AntDesignIconsOutlined;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.util.Optional;
+
+public class MenuPane extends StackPane {
+
+ // 顶部导航栏
+ private final NavItem setting = new NavItem(new FontIcon(AntDesignIconsFilled.SETTING), "设置", null);
+ private final NavItem notification = new NavItem(new FontIcon(AntDesignIconsFilled.NOTIFICATION), "通知", null);
+ private final VBox topMenu = new VBox(setting, notification);
+
+ // 动态导航栏
+ private final ListView dynamicMenu = new ListView<>();
+
+ // 底部导航栏
+ private final Label userLabel = new Label("test");
+ private final Label emailLabel = new Label("test@163.com");
+ private final VBox bottomMenu = new VBox(userLabel, emailLabel);
+
+ private VBox asideContainer = new VBox(topMenu, new Separator(Orientation.HORIZONTAL), dynamicMenu, new Separator(Orientation.HORIZONTAL), bottomMenu);
+
+ private final ContentPane contentPane;
+
+ public MenuPane(ContentPane contentPane) {
+ this.contentPane = contentPane;
+ initialize();
+
+ // 模拟数据
+ dynamicMenu.getItems().addAll(
+ new NavItem(new FontIcon(AntDesignIconsOutlined.MESSAGE), "提示", null),
+ new NavItem(new FontIcon(AntDesignIconsFilled.CONTROL), "抽屉", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.MESSAGE), "消息提示", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.LOADING_3_QUARTERS), "加载", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "气泡卡片", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "案例一", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "案例二", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "案例三", null)
+ );
+ }
+
+ private void initialize() {
+ getChildren().addAll(asideContainer);
+ VBox.setVgrow(dynamicMenu, Priority.ALWAYS);
+
+ // 加上监听
+ dynamicMenu.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
+ Optional.ofNullable(newValue).ifPresent(menuItem -> {
+ contentPane.setContent(menuItem.getContent());//设置内容
+ });
+ });
+ }
+}
diff --git a/src/main/java/com/light/layout/NavItem.java b/src/main/java/com/light/layout/NavItem.java
new file mode 100644
index 0000000..76a946d
--- /dev/null
+++ b/src/main/java/com/light/layout/NavItem.java
@@ -0,0 +1,51 @@
+package com.light.layout;
+
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+/**
+ * 导航组件
+ */
+public class NavItem extends HBox {
+
+ /**
+ * 图标
+ */
+ private Label iconLabel = new Label();
+
+ /**
+ * 标题
+ */
+ private Label titleLabel = new Label();
+
+ /**
+ * 内容界面
+ */
+ private Node content;
+
+ public NavItem(FontIcon fontIcon, String title, Node content) {
+ this.iconLabel.setGraphic(fontIcon);
+ this.titleLabel.setText(title);
+ this.content = content;
+ initialize();
+ }
+
+ private void initialize() {
+ getChildren().addAll(iconLabel, titleLabel);
+ // 标题占满剩余空间
+ titleLabel.setMaxSize(Double.MAX_VALUE, USE_PREF_SIZE);
+ HBox.setHgrow(titleLabel, Priority.ALWAYS);
+
+ getStyleClass().add("nav-item");
+ iconLabel.getStyleClass().add("icon-label");
+ titleLabel.getStyleClass().add("name-label");
+ prefWidthProperty().bind(this.widthProperty().subtract(1));
+ }
+
+ public Node getContent() {
+ return content;
+ }
+}
diff --git a/src/main/java/com/light/util/FxUtil.java b/src/main/java/com/light/util/FxUtil.java
new file mode 100644
index 0000000..c8bb440
--- /dev/null
+++ b/src/main/java/com/light/util/FxUtil.java
@@ -0,0 +1,114 @@
+package com.light.util;
+
+import javafx.beans.binding.Bindings;
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+import javafx.geometry.Bounds;
+import javafx.scene.Node;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.Region;
+import javafx.scene.shape.Rectangle;
+import javafx.stage.Stage;
+import javafx.stage.Window;
+
+import java.util.concurrent.Callable;
+
+/**
+ * @author ChenFei
+ * @date 2022/12/9
+ */
+public class FxUtil {
+
+ public static String getResource(String resources) {
+ return FxUtil.class.getResource(resources).toExternalForm();
+ }
+
+ public static Image getImage(String resources) {
+ return new Image(getResource(resources));
+ }
+
+ public static ImageView getImageView(String resources, double size) {
+ return getImageView(resources, size, size);
+ }
+
+ public static ImageView getImageView(String resources, double height, double width) {
+ ImageView imageView = new ImageView(getResource(resources));
+ imageView.setFitHeight(height);
+ imageView.setFitWidth(width);
+ return imageView;
+ }
+
+ /**
+ * 获取组件在屏幕中的位置
+ *
+ * @param node
+ * @return
+ */
+ public static Bounds localToScreen(Node node) {
+ return node.localToScreen(node.getLayoutBounds());
+ }
+
+ /**
+ * 获取窗口
+ *
+ * @param node
+ * @return
+ */
+ public static Stage getStage(Node node) {
+ return (Stage) getWindow(node);
+ }
+
+
+ /**
+ * 获取当前被聚焦的第一个窗口,没有则返回null。
+ *
+ * @return
+ */
+ public static Window getFocusedWindow() {
+ return Stage.getWindows().stream().filter(Window::isFocused).findFirst().orElse(null);
+ }
+
+ /**
+ * 获取窗口
+ *
+ * @param node
+ * @return
+ */
+ public static Window getWindow(Node node) {
+ return node.getParent().getScene().getWindow();
+ }
+
+ /**
+ * 矩形裁剪
+ *
+ * @param region :裁剪区域
+ * @return Rectangle
+ */
+ public static Rectangle clipRect(Region region) {
+ return clipRect(region, new SimpleDoubleProperty(0));
+ }
+
+ /**
+ * 矩形裁剪
+ *
+ * @param node :裁剪区域
+ * @param bindArc :裁剪圆角
+ * @return Rectangle
+ */
+ public static Rectangle clipRect(Node node, DoubleProperty bindArc) {
+ Rectangle rectangle = new Rectangle();
+ //rectangle.setSmooth(false);
+ rectangle.widthProperty().bind(Bindings
+ .createObjectBinding((Callable) () ->
+ node.getLayoutBounds().getWidth(), node.layoutBoundsProperty()));
+ rectangle.heightProperty().bind(Bindings
+ .createObjectBinding((Callable) () ->
+ node.getLayoutBounds().getHeight(), node.layoutBoundsProperty()));
+ rectangle.arcWidthProperty().bind(bindArc);
+ rectangle.arcHeightProperty().bind(bindArc);
+ node.setClip(rectangle);
+ return rectangle;
+ }
+
+}
diff --git a/src/main/java/com/light/util/H2Utils.java b/src/main/java/com/light/util/H2Utils.java
new file mode 100644
index 0000000..186e4c2
--- /dev/null
+++ b/src/main/java/com/light/util/H2Utils.java
@@ -0,0 +1,4 @@
+package com.light.util;
+
+public class H2Utils {
+}
diff --git a/src/main/java/com/light/util/NodeUtils.java b/src/main/java/com/light/util/NodeUtils.java
new file mode 100644
index 0000000..eeebc21
--- /dev/null
+++ b/src/main/java/com/light/util/NodeUtils.java
@@ -0,0 +1,29 @@
+package com.light.util;
+
+import javafx.geometry.Insets;
+import javafx.scene.Node;
+import javafx.scene.layout.AnchorPane;
+
+public final class NodeUtils {
+
+ /**
+ * 设置子节点距AnchorPane锚点布局四边的距离
+ *
+ * @param node
+ * @param insets
+ */
+ public static void setAnchors(Node node, Insets insets) {
+ if (insets.getTop() >= 0) {
+ AnchorPane.setTopAnchor(node, insets.getTop());
+ }
+ if (insets.getRight() >= 0) {
+ AnchorPane.setRightAnchor(node, insets.getRight());
+ }
+ if (insets.getBottom() >= 0) {
+ AnchorPane.setBottomAnchor(node, insets.getBottom());
+ }
+ if (insets.getLeft() >= 0) {
+ AnchorPane.setLeftAnchor(node, insets.getLeft());
+ }
+ }
+}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index a0fa134..fbb190d 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -7,4 +7,7 @@ open module com.leo {
requires java.sql;
requires com.h2database;
requires atlantafx.base;
+ requires org.kordamp.ikonli.javafx;
+ requires org.jetbrains.annotations;
+ requires org.kordamp.ikonli.antdesignicons;
}
--
Gitee
From 2eba09f88088464e9cac32454f3bf43d3371e094 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E7=99=BD=E4=B8=8E=E5=AD=9F=E6=B5=A9=E7=84=B6?=
<1063889643@qq.com>
Date: Sat, 7 Oct 2023 10:14:54 +0800
Subject: [PATCH 2/2] =?UTF-8?q?#I806RK=20state=20to=20=E8=BF=9B=E8=A1=8C?=
=?UTF-8?q?=E4=B8=AD=20=E5=9F=BA=E6=9C=AC=E6=A0=B7=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/com/light/layout/MenuPane.java | 19 ++++---
src/main/resources/css/menu.css | 56 ++++++++++++++++++++
src/main/resources/css/test.css | 1 -
3 files changed, 67 insertions(+), 9 deletions(-)
create mode 100644 src/main/resources/css/menu.css
delete mode 100644 src/main/resources/css/test.css
diff --git a/src/main/java/com/light/layout/MenuPane.java b/src/main/java/com/light/layout/MenuPane.java
index e2e2602..b56ba7d 100644
--- a/src/main/java/com/light/layout/MenuPane.java
+++ b/src/main/java/com/light/layout/MenuPane.java
@@ -15,6 +15,8 @@ import java.util.Optional;
public class MenuPane extends StackPane {
+ private static final String STYLE_SHEET = MenuPane.class.getResource("/css/menu.css").toExternalForm();
+
// 顶部导航栏
private final NavItem setting = new NavItem(new FontIcon(AntDesignIconsFilled.SETTING), "设置", null);
private final NavItem notification = new NavItem(new FontIcon(AntDesignIconsFilled.NOTIFICATION), "通知", null);
@@ -38,21 +40,22 @@ public class MenuPane extends StackPane {
// 模拟数据
dynamicMenu.getItems().addAll(
- new NavItem(new FontIcon(AntDesignIconsOutlined.MESSAGE), "提示", null),
- new NavItem(new FontIcon(AntDesignIconsFilled.CONTROL), "抽屉", null),
- new NavItem(new FontIcon(AntDesignIconsOutlined.MESSAGE), "消息提示", null),
- new NavItem(new FontIcon(AntDesignIconsOutlined.LOADING_3_QUARTERS), "加载", null),
- new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "气泡卡片", null),
- new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "案例一", null),
- new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "案例二", null),
- new NavItem(new FontIcon(AntDesignIconsOutlined.CONTROL), "案例三", null)
+ new NavItem(new FontIcon(AntDesignIconsOutlined.HOME), "首页", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.PARTITION), "管理", null),
+ new NavItem(new FontIcon(AntDesignIconsOutlined.EDIT), "笔记", null)
);
}
private void initialize() {
+ // 加载样式
+ getStylesheets().add(STYLE_SHEET);
+
getChildren().addAll(asideContainer);
VBox.setVgrow(dynamicMenu, Priority.ALWAYS);
+ // 添加样式
+ this.dynamicMenu.getStyleClass().addAll("menu");
+
// 加上监听
dynamicMenu.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
Optional.ofNullable(newValue).ifPresent(menuItem -> {
diff --git a/src/main/resources/css/menu.css b/src/main/resources/css/menu.css
new file mode 100644
index 0000000..5f1ad56
--- /dev/null
+++ b/src/main/resources/css/menu.css
@@ -0,0 +1,56 @@
+/*导航栏Item样式*/
+.nav-item{
+ -fx-background-radius: 3px;
+ -fx-min-height: 40px;
+ -fx-pref-height: 40px;
+ -fx-alignment: center-left;
+ -fx-spacing: 10px;
+ -fx-padding: 0 10px;
+ -fx-cursor: hand;
+}
+.nav-item > .icon-label > .ikonli-font-icon{
+ -fx-icon-size: 20px;
+ -fx-icon-color: derive(#303133,30%);
+}
+.nav-item > .name-label{
+ -fx-font-size: 14px;
+ -fx-pref-height: 30px;
+ -fx-font-weight: bolder;
+ -fx-text-fill: derive(#303133,30%);
+}
+.nav-item:hover > .name-label{
+ -fx-text-fill: #6690FF;
+}
+.nav-item:hover > .icon-label > .ikonli-font-icon{
+ -fx-icon-color: #6690FF;
+}
+/*动态导航栏*/
+.menu{
+ -fx-background-insets: 0px;
+ -fx-background-color:transparent;
+ -fx-padding:5px 0 5px 0;
+}
+.menu .scroll-bar{
+ -fx-opacity:0;
+}
+.menu:hover .scroll-bar{
+ -fx-opacity:1;
+}
+.menu .cell.indexed-cell.list-cell{
+ -fx-background-color:transparent;
+ -fx-padding:0px;
+}
+.menu .cell.indexed-cell.list-cell:empty:hover{
+ -fx-background-color:transparent;
+}
+.menu .cell.indexed-cell.list-cell:hover{}
+.menu .cell.indexed-cell.list-cell:selected{}
+.menu .cell.indexed-cell.list-cell:selected .nav-item{
+ -fx-background-color: rgba(0,0,0,0.1);
+}
+.menu .cell.indexed-cell.list-cell:selected .name-label{
+ -fx-text-fill: #6690FF;
+}
+.menu .cell.indexed-cell.list-cell:selected .icon-label > .ikonli-font-icon{
+ -fx-icon-color: #6690FF;
+}
\ No newline at end of file
diff --git a/src/main/resources/css/test.css b/src/main/resources/css/test.css
deleted file mode 100644
index 4e55547..0000000
--- a/src/main/resources/css/test.css
+++ /dev/null
@@ -1 +0,0 @@
-/*例子后续移除*/
\ No newline at end of file
--
Gitee