# AxisInnovatorsBoxWindowApi [项目链接](https://gitea.lingqi.vip/lanxi/window-axis-innovators-box) | [官网](https://box.nimblenexa.cn) | 简体中文 --- ## 项目概述 `AxisInnovatorsBoxWindowApi` 是一个为 **AxisInnovatorsBox** 平台设计的管理API接口库,开发者可通过此API创建自定义插件,实现窗口管理、事件交互等核心功能。该仓库提供了接口定义、类说明文档及插件开发示例代码,帮助开发者快速接入AxisInnovatorsBox生态系统。 --- ## 功能特性 - 🖥️ **窗口生命周期管理** - 创建/销毁窗口、调整窗口状态(最小化/最大化) - 🎮 **事件驱动交互** - 支持窗口事件监听与自定义事件触发 - 📦 **跨语言插件支持** - 基于 Java 平台无缝加载 Python 插件,提供标准插件基类(Java/Python)实现快速扩展 - 📄 **动态配置管理** - 通过 properties 配置文件灵活加载多语言插件(支持 Java/Python 插件声明) - 📊 **统一日志追踪** - 集成 Java 平台日志系统,同步记录 Python 插件的运行状态与异常信息 --- ## 插件加载系统说明 - 插件加载系统核心组件。 - 插件加载系统由 **程序内部** 完成 ### 注册Jar插件 - Jar插件在/plug-in中添加 ```java @PluginMeta(id = "test", name = "测试插件", supportedVersions = {"0.0.2"}, description = "测试插件", icon = "", registeredName = "test") public class Template { public static PluginDescriptor INSTANCE = null; public Template() { GlobalEventBus.EVENT_BUS.register(this); } @SubscribeEvent public void onStartup(StartupEvent event) { MainWindow.ToolCategory category = new MainWindow.ToolCategory("测试插件", "test", "测试插件"); event.main().getRegistrationTool().addToolCategory( category, INSTANCE, "templatePlugin" ); } } ``` - 插件加载系统会自动填充 **INSTANCE** 内容 - 使用PluginMeta注册插件信息 ### Python插件注册 - Python插件在/plug-in/python中添加 - Python可以直接调用Java类实现对插件系统的控制 - 插件还需要单独的放在一个子文件夹中,如/plug-in/python/Examples - Python插件需要声明一个metadata.json文件,如: ```json { "id": "testing", "name": "测试", "version": "0.0.1", "description": "测试插件", "author": "tzdwindows 7", "dependencies": [], "_comment": { "warning": "本文件为插件元数据配置,修改后需重启应用生效", "path": "插件资源应放置在plugins/{id}/目录下" } } ``` - Python插件需要声明一个main.py文件做为插件的主脚本,如: ```python """ 工具模块初始化脚本 功能:向Axis Innovators Box注册自定义工具类别和工具项 作者:tzdwindows 7 版本:1.1 """ from com.axis.innovators.box.python import PyLocalSide from javax.swing import AbstractAction class MyAction(AbstractAction): def actionPerformed(self, event): """工具项点击事件处理""" print("[DEBUG] Tool item clicked! Event source:", event.getSource()) def onStartup(): """ 系统启动时自动执行的初始化逻辑 功能: 1. 创建工具类别 2. 创建工具项并绑定动作 3. 注册到系统全局工具集 """ print('[INFO] 正在初始化自定义工具...') # -------------------------- # 创建工具类别(参数顺序:显示名称,图标资源名,描述) # -------------------------- tool_category = PyLocalSide.getToolCategory( u"数据分析工具", # 显示名称(GUI可见) u"analytics_icon.png", # 图标文件名(需存在于资源目录) u"高级数据分析功能集合" # 悬停提示描述 ) # -------------------------- # 创建工具项(参数顺序:显示名称,图标,描述,ID,动作对象) # -------------------------- tool_action = MyAction() tool_item = PyLocalSide.getToolItem( u"数据可视化", # 工具项显示名称 u"chart_icon.png", # 工具项图标 u"生成交互式数据图表", # 工具项描述 1001, # 工具项唯一ID(需在配置中统一管理) tool_action # 点击触发的动作 ) tool_category.addTool(tool_item) # -------------------------- # 注册工具类别到系统(参数:类别对象,全局唯一注册名称) # -------------------------- PyLocalSide.addToolCategory( tool_category, u"custom_module::data_analysis_tools" # 推荐命名规则:模块名::功能名 ) print('[SUCCESS] 工具类别注册成功') if __name__ == '__main__': result = 0 errorResult = "" # 确保Jython运行时可以访问onStartup函数 # 原理:将函数显式绑定到全局字典 globals()['onStartup'] = onStartup ``` ### 声明CorePlugins * CorePlugins核心组件可以修改部分模块的字节码。 * CorePlugins需要在jar的属性中添加 **CorePlugins: CorePlugins类位置** * 自动化构建,在build.gradle中添加如下代码: ```groovy jar { manifest { attributes 'CorePlugin': 'com.axis.core.template.TemplateLoadingCorePlugin' } } ``` * CorePlugins核心组件需要实现 **CorePlugins** 接口,如: ```java package com.axis.core.template; import com.axis.innovators.box.plugins.LoadingCorePlugin; import com.axis.innovators.template.Template; /** * 注册core插件 */ public class TemplateLoadingCorePlugin implements LoadingCorePlugin { @Override public String getMainClass() { // 返回主类名 return Template.class.getName(); } @Override public String[] getASMTransformerClass() { // 返回字节码转换器类名 return new String[]{TemplateTransformer.class.getName()}; } } ``` * IClassTransformer的实现,如: ```java package com.axis.core.template; import com.axis.innovators.box.plugins.IClassTransformer; import org.objectweb.asm.*; /** * core plugin transformer * @author tzdwindows 7 */ public class TemplateTransformer implements IClassTransformer { @Override public byte[] transform(String s, String s1, byte[] bytes) { ClassReader classReader = new ClassReader(bytes); ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) { @Override public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { if ((access & Opcodes.ACC_PRIVATE) != 0) { access = (access & ~Opcodes.ACC_PRIVATE) | Opcodes.ACC_PUBLIC; System.out.println("Changing field access to public: " + name); } return super.visitField(access, name, descriptor, signature, value); } @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { System.out.println(name + " , descriptor:" + descriptor); if ((access & Opcodes.ACC_PRIVATE) != 0) { access = (access & ~Opcodes.ACC_PRIVATE) | Opcodes.ACC_PUBLIC; System.out.println("Changing method access to public: " + name); } return super.visitMethod(access, name, descriptor, signature, exceptions); } }; classReader.accept(classVisitor, 0); return classWriter.toByteArray(); } } ``` ## 事件系统说明 - 事件驱动架构核心组件。 - 事件总线系统,支持跨模块通信。 - 事件总线由 **EventBus & GlobalEventBus** 实现 ### 1.. EventBus & GlobalEventBus 说明 应用程序内的事件驱动架构核心组件: ```java package com.axis.innovators.box.events; /** * 事件总线系统(支持多总线实例隔离) */ public class EventBus { // 核心方法 public void register(Object listener); // 注册监听器 public void unregister(Object target); // 注销监听器 public boolean post(Object event); // 发布事件 public void shutdown(); // 关闭总线 } public class GlobalEventBus { public static final EventBus EVENT_BUS = new EventBus(); // 全局单例总线 } ``` - **EventBus**:用于处理应用程序内各个模块之间的事件通信。 - **GlobalEventBus**:用于处理应用程序内各个模块之间的事件通信,支持多总线实例隔离。 ### 2. EventBus & GlobalEventBus 使用示例 #### 示例1:基础事件处理 ```java // 1. 定义事件类型 public class UserLoginEvent { private final String username; private boolean cancelled; public UserLoginEvent(String username) { this.username = username; } // Getter/Setter... } // 2. 创建监听器类 public class SecurityLogger { @SubscribeEvent public void logLoginAttempt(UserLoginEvent event) { System.out.println("[安全审计] 登录尝试: " + event.getUsername()); } } // 3. 使用全局总线 public class Main { public static void main(String[] args) { // 注册监听器 GlobalEventBus.EVENT_BUS.register(new SecurityLogger()); // 模拟用户登录 UserLoginEvent loginEvent = new UserLoginEvent("admin"); GlobalEventBus.EVENT_BUS.post(loginEvent); } } ``` - 示例2:事件取消机制 ```java // 1. 定义可取消事件 public class FileDeleteEvent { private final Path filePath; private boolean cancelled; // 构造方法/getters/setters... } // 2. 创建权限校验监听器 public class PermissionValidator { @SubscribeEvent public void validateDeletePermission(FileDeleteEvent event) { if (!checkAdminAccess()) { event.setCancelled(true); System.out.println("文件删除被拒绝:权限不足"); } } private boolean checkAdminAccess() { // 权限校验逻辑 return false; } } // 3. 主业务流程 public class FileManager { public void deleteFile(Path path) { FileDeleteEvent event = new FileDeleteEvent(path); GlobalEventBus.EVENT_BUS.post(event); if (!event.isCancelled()) { // 执行删除操作 System.out.println("正在删除文件: " + path); } } } ``` ### 3.所有系统所支持的事件 - `com.axis.innovators.box.events.CategoryRenderingEvent`: 分类栏的渲染事件 - `com.axis.innovators.box.events.MainWindowEvents`: 主窗口事件 - `com.axis.innovators.box.events.OpenFileEvents`: 接收文件事件 - `com.axis.innovators.box.events.SettingsLoadEvents`: 程序初始化事件 - `com.axis.innovators.box.events.StartupEvent`: 程序启动事件 - `com.axis.innovators.box.events.TABUIEvents`: 选项卡Ui属性事件 ## HTML窗口集成指南 我们实现了一套高性能的HTML渲染系统,通过Java Chromium Embedded Framework (JCEF) 将HTML内容无缝集成到Java桌面应用中,底层基于[jcefmaven](https://github.com/jcefmaven/jcefmaven)项目。 ### 核心实现步骤 #### 1. 创建HTML窗口 ```java // 创建窗口引用 AtomicReference htmlWindow = new AtomicReference<>(); SwingUtilities.invokeLater(() -> { // 通过窗口注册表创建子窗口 WindowRegistry.getInstance().createNewChildWindow("main", builder -> { htmlWindow.set(builder .title("Axis Innovators Box AI 工具箱") // 窗口标题 .parentFrame(parentFrame) // 父级窗口 .icon(getApplicationIcon()) // 应用图标 .size(1280, 720) // 初始尺寸 .htmlPath(getHtmlResourcePath()) // HTML文件路径 .operationHandler(createOperationHandler()) // 自定义操作处理器 .build()); }); // 配置消息路由 configureMessageRouter(htmlWindow.get()); }); ``` #### 2. 辅助方法 ```java // 获取应用图标 private Image getApplicationIcon() { return new ImageIcon(Objects.requireNonNull( MainApplication.class.getClassLoader() .getResource("icons/logo.png") )).getImage(); } // 获取HTML资源路径 private String getHtmlResourcePath() { return FolderCreator.getJavaScriptFolder() + "/AIaToolbox_dark.html"; } ``` #### 3. 配置消息路由器 ```java private void configureMessageRouter(BrowserWindowJDialog window) { CefMessageRouter msgRouter = window.getMsgRouter(); if (msgRouter == null) return; msgRouter.addHandler(new CefMessageRouterHandlerAdapter() { @Override public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, String request, boolean persistent, CefQueryCallback callback) { // 处理来自HTML的请求 handleBrowserRequest(request, callback); return true; // 表示已处理该请求 } @Override public void onQueryCanceled(CefBrowser browser, CefFrame frame, long queryId) { // 处理请求取消逻辑 System.out.println("请求被取消: " + queryId); } }, true); // true表示优先处理 } ``` ## HTML事件 HTML窗口内可以捕捉到一些Java的事件 | 事件名 | 介绍 | 触发时机 | |--------|------------|---------------------| | `javaFontsLoaded` | Java字体加载完成 | Java字体信息传输到HTML时,或在在更新主题时 | | `javaThemeChanged` | 在主题发生变化时触发 | 在更新主题时 | #### 具体示例 ```javascript // 监听Java字体加载事件 document.addEventListener('javaFontsLoaded', function(event) { const fontInfo = event.detail; console.log('接收到Java字体信息:', fontInfo); // 应用Java字体到界面 applyJavaFonts(fontInfo); }); // 监听Java主题变化事件 document.addEventListener('javaThemeChanged', function(event) { const themeInfo = event.detail; console.log('接收到Java主题信息:', themeInfo); applyJavaTheme(themeInfo); }); ``` ### 窗口管理系统说明 通过`WindowRegistry`统一管理应用窗口: | 方法 | 说明 | |------|------| | `createNewWindow(String id, Consumer config)` | 创建主窗口 | | `createNewChildWindow(String id, Consumer config)` | 创建模态子窗口 | | `getWindow(String id)` | 获取已注册窗口 | | `unregisterWindow(String id)` | 关闭指定窗口 | ### CefMessageRouter 使用指南 实现Java与JavaScript双向通信的核心组件: 1. **消息处理流程**: - JavaScript → Java: 通过`window.cefQuery()`发送请求 - Java → JavaScript: 使用`CefFrame.executeJavaScript()`执行脚本 2. **核心方法**: ```java // JavaScript调用示例 function callJavaMethod(data) { window.cefQuery({ request: JSON.stringify(data), onSuccess: response => console.log("Success:", response), onFailure: (err, msg) => console.error("Error:", msg) }); } ``` 3. **最佳实践**: - 使用JSON格式进行数据交换 - 为不同功能模块使用独立的路由处理器 - 在窗口关闭前移除所有路由处理器 ### 生命周期管理 ```java // 关闭窗口时清理资源 htmlWindow.get().addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { window.getMsgRouter().dispose(); CefApp.getInstance().dispose(); } }); ``` ## 核心类说明 ### 1. AxisInnovatorsBox 窗口实例的核心操作类,提供以下功能: - `getMain()`: 获取当前AxisInnovatorsBox实例 - `getMainWindow()`: 获取主窗口实例 - `quit()`: 退出程序 - `organizingCrashReports(Exception)`: 组织崩溃报告,用于在应用程序发生异常时生成崩溃报告。 - `popupWindow(WindowsJDialog)`: 弹出新的窗口,并将其添加到窗口列表中。 - `isWindowStartup(WindowsJDialog)`: 判断指定的窗口是否已经启动。 - `clearWindow(WindowsJDialog)`: 清除指定的窗口,并将其从窗口列表中移除。 - `reloadAllWindow()`: 重新加载窗口。 - `getRegistrationTool()`: 获取注册工具实例。 - `getArgs()`: 获取命令行参数。 - `isWindow()`: 判断窗口是否已经启动。 - `getVersion()`: 获取应用程序的版本号。 - `getRegistrationTopic()`: 获取注册主题实例。 - `getAuthor()`: 获取应用程序的作者信息。 - `getStateManager()`: 获取状态管理器实例。 ### 2. RegistrationTool 负责在 **应用程序启动阶段** 注册和管理工具分类的核心组件,具备插件系统集成能力: ```java package com.axis.innovators.box.register; /** * 工具分类注册中心(窗口启动前必须完成注册) */ public class RegistrationTool { // 构造方法关联主程序实例 public RegistrationTool(AxisInnovatorsBox main) { ... } // 核心功能方法 public boolean addToolCategory(ToolCategory category, String regName); public void addToolCategory(ToolCategory category, PluginDescriptor descriptor, String regName); public ToolCategory getToolCategory(UUID id); public UUID getUUID(String registeredName); } ``` - `addToolCategory(ToolCategory category, String regName)`: 向工具分类注册中心添加一个新的工具分类。 - `addToolCategory(ToolCategory category, PluginDescriptor descriptor, String regName)`: 向工具分类注册中心添加一个新的工具分类,同时关联插件描述符。 - `getToolCategory(UUID id)`: 通过UUID获取工具分类。 - `getUUID(String registeredName)`: 通过注册名称获取UUID。 #### 注册示例 ```java // 创建调试工具分类 MainWindow.ToolCategory debugCategory = new MainWindow.ToolCategory( "逆向分析工具", "icons/debugger.png", "二进制逆向分析工具集" ); // 添加工具项(带点击事件) debugCategory.addTool(new MainWindow.ToolItem( "内存分析器", "icons/memory.png", "实时查看进程内存映射", 1, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(null, "启动内存分析模块..."); } } )); // 注册到系统(必须在窗口初始化前完成) try { registrationTool.addToolCategory(debugCategory, "system:reverseEngineering"); } catch (RegistrationError ex) { System.err.println("注册失败: " + ex.getMessage()); } ``` ### 3. RegistrationTopic 负责在 **应用程序初始化阶段** 统一管理UI主题注册的核心组件,支持类名/LookAndFeel双模式主题注入: ```java package com.axis.innovators.box.register; /** * 主题注册中心(窗口初始化前必须完成注册) */ public class RegistrationTopic { // 核心注册方法 public void addTopic(String topicClass, String name, String tip, Icon icon, String regName); public void addTopic(LookAndFeel laf, String name, String tip, Icon icon, String regName); // 状态管理方法 public boolean isLoading(String themeName); public void setLoading(String themeName); } ``` - `addTopic(String topicClass, String name, String tip, Icon icon, String regName)`: 向主题注册中心添加一个新的主题。 - `addTopic(LookAndFeel laf, String name, String tip, Icon icon, String regName)`: 向主题注册中心添加一个新的主题,同时关联LookAndFeel。 - `isLoading(String themeName)`: 判断指定主题是否正在加载。 - `setLoading(String themeName)`: 设置指定主题为正在加载状态。 #### 注册示例 ```java try { // 重复注册相同名称 topicRegistry.addTopic("com.axis.light.MaterialTheme", "质感浅色", "Material Design风格", materialIcon, "theme:light"); // 已存在同名注册 } catch (RegistrationError ex) { // 捕获异常并提示:theme:light duplicate registered names JOptionPane.showMessageDialog(null, ex.getMessage()); } ``` ### 4. StateManager 应用程序状态管理工具类,提供跨会话的配置持久化能力: ```java package com.axis.innovators.box.tools; /** * 状态持久化管理器(线程安全) */ public class StateManager { // 构造方法 public StateManager(); // 默认使用toolbox.properties public StateManager(String customFileName); // 自定义状态文件名 // 核心操作方法 public void saveState(String key, [int|long|boolean...] value); public [String|int|boolean...] getStateAs[Type](String key); } ``` - `saveState(String key, [int|long|boolean...] value)`: 保存状态到配置文件。 - `getStateAs[Type](String key)`: 从配置文件获取状态。 - `[String|int|boolean...]`: 支持多种数据类型保存到配置文件,并支持多种数据类型从配置文件获取。 ### 5. RegistrationSettingsItem 负责管理系统 **设置中心** 的配置面板注册,支持插件化扩展设置项的核心组件: ```java package com.axis.innovators.box.register; /** * 设置项注册中心(集成插件配置扩展能力) */ public class RegistrationSettingsItem extends WindowsJDialog { // 核心注册方法 public void addSettings(JPanel panel, String title, Icon icon, String tip, String regName); public void addSettings(JPanel panel, String title, Icon icon, String tip, PluginDescriptor plugin, String regName); // 查询方法 public static List getRegistrationsByPlugin(PluginDescriptor plugin); } ``` - `addSettings(JPanel panel, String title, Icon icon, String tip, String regName)`: 向设置项注册中心添加一个新的设置项。 - `addSettings(JPanel panel, String title, Icon icon, String tip, PluginDescriptor plugin, String regName)`: 向设置项注册中心添加一个新的设置项,同时关联插件描述符。 - `getRegistrationsByPlugin(PluginDescriptor plugin)`: 通过插件描述符获取关联的设置项列表。 ### 6. LanguageManager 应用程序多语言管理核心组件,支持动态加载与合并多语言资源: ```java package com.axis.innovators.box.register; /** * 国际化语言管理中心(支持插件扩展语言包) */ public class LanguageManager { // 核心操作方法 public static void addLanguage(Language lang); public static void loadLanguage(String regName); public static Language getLoadedLanguages(); public static Language getLanguage(String identifier); } ``` - `addLanguage(Language lang)`: 向语言管理中心添加一个新的语言包。 - `loadLanguage(String regName)`: 加载指定语言包。 - `getLoadedLanguages()`: 获取当前系统加载的语言包。 - `getLanguage(String identifier)`: 通过标识符获取语言包。