From 6059ff20baebd57a728e363beaef47f79605ee19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E8=BD=B2?= Date: Thu, 7 Sep 2023 00:45:03 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0jdk=E5=92=8Cjavafx?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=88=B020?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 21c5020..c67b8b0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,14 +6,14 @@ org.jcnc JNotepad - 1.0-SNAPSHOT + 1.11.2-SNAPSHOT JNotepad UTF-8 5.9.2 - 17.0.1 + 20.0.2 -- Gitee From 5cd4cb85c16ad01d7d0160add04c1b7e01b9c969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E8=BD=B2?= Date: Thu, 7 Sep 2023 02:27:00 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/jnotepad/plgin/ButtonPlugin.java | 22 ++++++ .../java/org/jcnc/jnotepad/plgin/Plugin.java | 9 +++ .../jcnc/jnotepad/plgin/PluginCategory.java | 8 +++ .../org/jcnc/jnotepad/plgin/PluginDemo.java | 72 +++++++++++++++++++ .../jcnc/jnotepad/plgin/PluginManager.java | 55 ++++++++++++++ .../jnotepad/root/top/menu/TopMenuBar.java | 5 ++ tool/jpackage.txt | 2 +- 7 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/jcnc/jnotepad/plgin/ButtonPlugin.java create mode 100644 src/main/java/org/jcnc/jnotepad/plgin/Plugin.java create mode 100644 src/main/java/org/jcnc/jnotepad/plgin/PluginCategory.java create mode 100644 src/main/java/org/jcnc/jnotepad/plgin/PluginDemo.java create mode 100644 src/main/java/org/jcnc/jnotepad/plgin/PluginManager.java diff --git a/src/main/java/org/jcnc/jnotepad/plgin/ButtonPlugin.java b/src/main/java/org/jcnc/jnotepad/plgin/ButtonPlugin.java new file mode 100644 index 0000000..143df5e --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/plgin/ButtonPlugin.java @@ -0,0 +1,22 @@ +package org.jcnc.jnotepad.plgin; + +/** + * @author luke + */ +public class ButtonPlugin implements Plugin { + @Override + public String getCategoryName() { + return "新按钮插件"; + } + + @Override + public String getDisplayName() { + return "新按钮"; + } + + @Override + public void execute() { + // 在这里实现新按钮插件的逻辑 + System.out.println("新按钮插件执行了!"); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/plgin/Plugin.java b/src/main/java/org/jcnc/jnotepad/plgin/Plugin.java new file mode 100644 index 0000000..16be5f0 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/plgin/Plugin.java @@ -0,0 +1,9 @@ +package org.jcnc.jnotepad.plgin; + +/** + * @author luke + */ +public interface Plugin extends PluginCategory { + String getDisplayName(); + void execute(); +} diff --git a/src/main/java/org/jcnc/jnotepad/plgin/PluginCategory.java b/src/main/java/org/jcnc/jnotepad/plgin/PluginCategory.java new file mode 100644 index 0000000..8085df1 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/plgin/PluginCategory.java @@ -0,0 +1,8 @@ +package org.jcnc.jnotepad.plgin; + +/** + * @author luke + */ +public interface PluginCategory { + String getCategoryName(); +} diff --git a/src/main/java/org/jcnc/jnotepad/plgin/PluginDemo.java b/src/main/java/org/jcnc/jnotepad/plgin/PluginDemo.java new file mode 100644 index 0000000..9781aa1 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/plgin/PluginDemo.java @@ -0,0 +1,72 @@ +package org.jcnc.jnotepad.plgin; + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; +import javafx.stage.FileChooser; +import javafx.stage.Stage; + +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + * @author luke + */ +public class PluginDemo { + + public void start(Stage primaryStage) { + PluginManager pluginManager = new PluginManager(); + + FileChooser fileChooser = new FileChooser(); + fileChooser.getExtensionFilters().addAll( + new FileChooser.ExtensionFilter("JAR Files", "*.jar") + ); + + Button loadButton = new Button("加载插件"); + loadButton.setOnAction(event -> { + File selectedFile = fileChooser.showOpenDialog(primaryStage); + if (selectedFile != null) { + String pluginFilePath = selectedFile.getAbsolutePath(); + pluginManager.loadPlugins(pluginFilePath); + + // 更新插件信息显示 + displayPluginInfo(primaryStage, pluginManager); + } + }); + + Button executeButton = new Button("执行插件"); + executeButton.setOnAction(event -> pluginManager.executePlugins()); + + VBox root = new VBox(10, loadButton, executeButton); + Scene scene = new Scene(root, 300, 200); + primaryStage.setScene(scene); + primaryStage.setTitle("插件演示"); + primaryStage.show(); + } + + private void displayPluginInfo(Stage primaryStage, PluginManager pluginManager) { + Map> loadedPluginsByCategory = pluginManager.getLoadedPluginsByCategory(); + VBox infoBox = new VBox(); + + for (String category : loadedPluginsByCategory.keySet()) { + Label categoryLabel = new Label("类别: " + category); + VBox categoryInfoBox = new VBox(); + List pluginNames = loadedPluginsByCategory.get(category); + for (String pluginName : pluginNames) { + Label pluginLabel = new Label("插件名称: " + pluginName); + categoryInfoBox.getChildren().add(pluginLabel); + } + infoBox.getChildren().addAll(categoryLabel, categoryInfoBox); + } + + Scene infoScene = new Scene(infoBox, 400, 300); + Stage infoStage = new Stage(); + infoStage.setScene(infoScene); + infoStage.setTitle("已加载的插件"); + infoStage.initOwner(primaryStage); + infoStage.show(); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/plgin/PluginManager.java b/src/main/java/org/jcnc/jnotepad/plgin/PluginManager.java new file mode 100644 index 0000000..8fe0fe1 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/plgin/PluginManager.java @@ -0,0 +1,55 @@ +package org.jcnc.jnotepad.plgin; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author luke + */ +public class PluginManager { + private final List plugins; + private final Map> categories; + + public PluginManager() { + plugins = new ArrayList<>(); + categories = new HashMap<>(); + } + + public void loadPlugins(String pluginFilePath) { + try { + File file = new File(pluginFilePath); + + if (file.exists() && file.isFile()) { + // 创建URLClassLoader以加载Jar文件中的类 + URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}); + Class pluginClass = classLoader.loadClass("org.jcnc.jnotepad.plgin.ButtonPlugin"); + Plugin plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); + plugins.add(plugin); + + // 添加插件到类别中 + String categoryName = plugin.getCategoryName(); + String displayName = plugin.getDisplayName(); + categories.computeIfAbsent(categoryName, k -> new ArrayList<>()).add(displayName); + } else { + System.err.println("Plugin file not found: " + pluginFilePath); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void executePlugins() { + for (Plugin plugin : plugins) { + plugin.execute(); + } + } + + public Map> getLoadedPluginsByCategory() { + return categories; + } +} diff --git a/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java b/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java index 8e4a218..8c76053 100644 --- a/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java +++ b/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java @@ -10,6 +10,7 @@ import org.jcnc.jnotepad.controller.config.AppConfigController; import org.jcnc.jnotepad.controller.event.handler.menubar.*; import org.jcnc.jnotepad.controller.event.handler.tool.SetBtn; import org.jcnc.jnotepad.controller.i18n.LocalizationController; +import org.jcnc.jnotepad.plgin.PluginDemo; import org.jcnc.jnotepad.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.root.left.sidebar.tools.SidebarToolBar; @@ -264,6 +265,10 @@ public class TopMenuBar extends MenuBar { UiResourceBundle.bindStringProperty(pluginMenu.textProperty(), PLUGIN); addItem = new MenuItem(); + addItem.setOnAction(event -> { + PluginDemo pluginDemo = new PluginDemo(); + pluginDemo.start(new Stage()); + }); UiResourceBundle.bindStringProperty(addItem.textProperty(), ADD_PLUGIN); itemMap.put("addItem", addItem); diff --git a/tool/jpackage.txt b/tool/jpackage.txt index 85f61fc..84aa54c 100644 --- a/tool/jpackage.txt +++ b/tool/jpackage.txt @@ -4,7 +4,7 @@ jpackage ` -m org.jcnc.jnotepad/org.jcnc.jnotepad.LunchApp ` --runtime-image .\target\JNotepad\ ` --icon src/main/resources/img/icon.ico ` - --app-version 1.1.11 ` + --app-version 1.1.12 ` --vendor "JCNC" -- Gitee From 0c27ea43232f28a50d3084ebc1591acc45a3f62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E8=BD=B2?= Date: Thu, 7 Sep 2023 02:35:43 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{plgin => plugin}/ButtonPlugin.java | 7 ++- .../jnotepad/{plgin => plugin}/Plugin.java | 16 ++++- .../{plgin => plugin}/PluginCategory.java | 12 +++- .../{plgin => plugin}/PluginDemo.java | 58 +++++++++++++----- .../{plgin => plugin}/PluginManager.java | 60 ++++++++++++------- .../jnotepad/root/top/menu/TopMenuBar.java | 2 +- 6 files changed, 115 insertions(+), 40 deletions(-) rename src/main/java/org/jcnc/jnotepad/{plgin => plugin}/ButtonPlugin.java (87%) rename src/main/java/org/jcnc/jnotepad/{plgin => plugin}/Plugin.java (34%) rename src/main/java/org/jcnc/jnotepad/{plgin => plugin}/PluginCategory.java (31%) rename src/main/java/org/jcnc/jnotepad/{plgin => plugin}/PluginDemo.java (62%) rename src/main/java/org/jcnc/jnotepad/{plgin => plugin}/PluginManager.java (31%) diff --git a/src/main/java/org/jcnc/jnotepad/plgin/ButtonPlugin.java b/src/main/java/org/jcnc/jnotepad/plugin/ButtonPlugin.java similarity index 87% rename from src/main/java/org/jcnc/jnotepad/plgin/ButtonPlugin.java rename to src/main/java/org/jcnc/jnotepad/plugin/ButtonPlugin.java index 143df5e..be080c9 100644 --- a/src/main/java/org/jcnc/jnotepad/plgin/ButtonPlugin.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/ButtonPlugin.java @@ -1,9 +1,12 @@ -package org.jcnc.jnotepad.plgin; +package org.jcnc.jnotepad.plugin; /** + * 新按钮插件 + * * @author luke */ public class ButtonPlugin implements Plugin { + @Override public String getCategoryName() { return "新按钮插件"; @@ -19,4 +22,4 @@ public class ButtonPlugin implements Plugin { // 在这里实现新按钮插件的逻辑 System.out.println("新按钮插件执行了!"); } -} +} \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/plgin/Plugin.java b/src/main/java/org/jcnc/jnotepad/plugin/Plugin.java similarity index 34% rename from src/main/java/org/jcnc/jnotepad/plgin/Plugin.java rename to src/main/java/org/jcnc/jnotepad/plugin/Plugin.java index 16be5f0..f3ac557 100644 --- a/src/main/java/org/jcnc/jnotepad/plgin/Plugin.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/Plugin.java @@ -1,9 +1,23 @@ -package org.jcnc.jnotepad.plgin; +package org.jcnc.jnotepad.plugin; /** + * 插件接口 + *

+ * 描述插件的基本功能。 + * * @author luke */ public interface Plugin extends PluginCategory { + + /** + * 获取插件的显示名称 + * + * @return 插件的显示名称 + */ String getDisplayName(); + + /** + * 执行插件的逻辑 + */ void execute(); } diff --git a/src/main/java/org/jcnc/jnotepad/plgin/PluginCategory.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginCategory.java similarity index 31% rename from src/main/java/org/jcnc/jnotepad/plgin/PluginCategory.java rename to src/main/java/org/jcnc/jnotepad/plugin/PluginCategory.java index 8085df1..c5c40f7 100644 --- a/src/main/java/org/jcnc/jnotepad/plgin/PluginCategory.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginCategory.java @@ -1,8 +1,18 @@ -package org.jcnc.jnotepad.plgin; +package org.jcnc.jnotepad.plugin; /** + * 插件类别接口 + *

+ * 描述插件的类别信息。 + * * @author luke */ public interface PluginCategory { + + /** + * 获取插件类别的名称 + * + * @return 插件类别的名称 + */ String getCategoryName(); } diff --git a/src/main/java/org/jcnc/jnotepad/plgin/PluginDemo.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java similarity index 62% rename from src/main/java/org/jcnc/jnotepad/plgin/PluginDemo.java rename to src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java index 9781aa1..865887c 100644 --- a/src/main/java/org/jcnc/jnotepad/plgin/PluginDemo.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java @@ -1,6 +1,5 @@ -package org.jcnc.jnotepad.plgin; +package org.jcnc.jnotepad.plugin; -import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; @@ -13,10 +12,19 @@ import java.util.List; import java.util.Map; /** + * 插件演示类 + *

+ * 用于演示插件加载和执行的界面。 + * * @author luke */ -public class PluginDemo { +public class PluginDemo { + /** + * 启动插件演示界面 + * + * @param primaryStage JavaFX的主舞台 + */ public void start(Stage primaryStage) { PluginManager pluginManager = new PluginManager(); @@ -25,17 +33,7 @@ public class PluginDemo { new FileChooser.ExtensionFilter("JAR Files", "*.jar") ); - Button loadButton = new Button("加载插件"); - loadButton.setOnAction(event -> { - File selectedFile = fileChooser.showOpenDialog(primaryStage); - if (selectedFile != null) { - String pluginFilePath = selectedFile.getAbsolutePath(); - pluginManager.loadPlugins(pluginFilePath); - - // 更新插件信息显示 - displayPluginInfo(primaryStage, pluginManager); - } - }); + Button loadButton = createLoadButton(primaryStage, fileChooser, pluginManager); Button executeButton = new Button("执行插件"); executeButton.setOnAction(event -> pluginManager.executePlugins()); @@ -47,6 +45,38 @@ public class PluginDemo { primaryStage.show(); } + /** + * 创建加载插件的按钮 + * + * @param primaryStage JavaFX的主舞台 + * @param fileChooser 文件选择器 + * @param pluginManager 插件管理器 + * @return 加载插件的按钮 + */ + private Button createLoadButton(Stage primaryStage, FileChooser fileChooser, PluginManager pluginManager) { + Button loadButton = new Button("加载插件"); + loadButton.setOnAction(event -> { + try { + File selectedFile = fileChooser.showOpenDialog(primaryStage); + if (selectedFile != null) { + String pluginFilePath = selectedFile.getAbsolutePath(); + pluginManager.loadPlugins(pluginFilePath); + + // 更新插件信息显示 + displayPluginInfo(primaryStage, pluginManager); + } + } catch (Exception ignored) { + } + }); + return loadButton; + } + + /** + * 显示已加载插件的信息 + * + * @param primaryStage JavaFX的主舞台 + * @param pluginManager 插件管理器 + */ private void displayPluginInfo(Stage primaryStage, PluginManager pluginManager) { Map> loadedPluginsByCategory = pluginManager.getLoadedPluginsByCategory(); VBox infoBox = new VBox(); diff --git a/src/main/java/org/jcnc/jnotepad/plgin/PluginManager.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java similarity index 31% rename from src/main/java/org/jcnc/jnotepad/plgin/PluginManager.java rename to src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java index 8fe0fe1..57aa64a 100644 --- a/src/main/java/org/jcnc/jnotepad/plgin/PluginManager.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java @@ -1,4 +1,4 @@ -package org.jcnc.jnotepad.plgin; +package org.jcnc.jnotepad.plugin; import java.io.File; import java.net.URL; @@ -9,46 +9,64 @@ import java.util.List; import java.util.Map; /** + * 插件管理器 + *

+ * 该类用于管理插件的加载和执行。 + * 插件可以通过加载外部JAR文件中的类来扩展应用程序的功能。 + * * @author luke */ public class PluginManager { private final List plugins; private final Map> categories; + /** + * 构造方法,初始化插件列表和类别映射 + */ public PluginManager() { plugins = new ArrayList<>(); categories = new HashMap<>(); } - public void loadPlugins(String pluginFilePath) { - try { - File file = new File(pluginFilePath); - - if (file.exists() && file.isFile()) { - // 创建URLClassLoader以加载Jar文件中的类 - URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}); - Class pluginClass = classLoader.loadClass("org.jcnc.jnotepad.plgin.ButtonPlugin"); - Plugin plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); - plugins.add(plugin); - - // 添加插件到类别中 - String categoryName = plugin.getCategoryName(); - String displayName = plugin.getDisplayName(); - categories.computeIfAbsent(categoryName, k -> new ArrayList<>()).add(displayName); - } else { - System.err.println("Plugin file not found: " + pluginFilePath); - } - } catch (Exception e) { - e.printStackTrace(); + /** + * 加载插件 + * + * @param pluginFilePath 插件文件的路径 + * @throws Exception 如果加载插件时发生异常 + */ + public void loadPlugins(String pluginFilePath) throws Exception { + File file = new File(pluginFilePath); + + if (file.exists() && file.isFile()) { + // 创建URLClassLoader以加载Jar文件中的类 + URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}); + Class pluginClass = classLoader.loadClass("org.jcnc.jnotepad.plugin.ButtonPlugin"); + Plugin plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); + plugins.add(plugin); + + // 添加插件到类别中 + String categoryName = plugin.getCategoryName(); + String displayName = plugin.getDisplayName(); + categories.computeIfAbsent(categoryName, k -> new ArrayList<>()).add(displayName); + } else { + System.err.println("Plugin file not found: " + pluginFilePath); } } + /** + * 执行加载的插件 + */ public void executePlugins() { for (Plugin plugin : plugins) { plugin.execute(); } } + /** + * 获取按类别分类的已加载插件 + * + * @return 插件类别映射 + */ public Map> getLoadedPluginsByCategory() { return categories; } diff --git a/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java b/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java index 8c76053..3edcafa 100644 --- a/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java +++ b/src/main/java/org/jcnc/jnotepad/root/top/menu/TopMenuBar.java @@ -10,7 +10,7 @@ import org.jcnc.jnotepad.controller.config.AppConfigController; import org.jcnc.jnotepad.controller.event.handler.menubar.*; import org.jcnc.jnotepad.controller.event.handler.tool.SetBtn; import org.jcnc.jnotepad.controller.i18n.LocalizationController; -import org.jcnc.jnotepad.plgin.PluginDemo; +import org.jcnc.jnotepad.plugin.PluginDemo; import org.jcnc.jnotepad.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.root.left.sidebar.tools.SidebarToolBar; -- Gitee