以下文章由 Andrew McCall 最初由 Karl-Heinz Kunzelmann 编写的 this article 修改过来,当时他研究了如何为 ImageJ2 编写的插件,目前已更名为斐济。几年后,Karl-Heinz Kunzelmann 在经历了相同的过程后进行了更新。这个新版本假设用户有兴趣为 Fiji编写项目而编写的,该项目严重依赖于Scijava plugin framework。本指南还删除了一些不再推荐的替代方法,以提出问题简单。
编写斐济插件:更新的初学者视角
序言
在您考虑为 Fiji 编写自己的 plugin 之前,请注意,编写 script 的入门功能比 Java 插件开发低倍。
另外,您可能还想看看Introduction_into_Macro_Programming,这是一种使用现有工具和插件自动执行重复任务的简单方法。
本指南的大部分内容都是从使用 IDEA IntelliJ 作为 IDE 的角度编写的。虽然使用其他推荐的 IDE 时可以完成所有操作,但具体细节可能与您在此处看到的有所不同。
最后,本新指南专门主题基于 Scijava 的 Fiji 插件项目,不会涵盖或链接到有关 ImageJ-1.x 插件开发的任何信息。适当地利用 Scijava 和 Imglib2 中的工具进行插件开发,特别是可以处理输入和输出,变得更加轻松和高效。本指南旨在对整个过程进行粗略概述,并刻意单独主题进行详细介绍。如果您对 ImageJ-1.x 开发感兴趣,请参见ImageJ-1.x plugin development page。
查找信息
- 顶级信息源是the ImageJ wiki。
- Development页面是有抱负的ImageJ开发人员的最佳门户。
- Fiji可在以下位置获取:LimeSeg
- 使用Javadoc创建课程文档 -其他帖子帮助,请使用ImageJ Forum。
术语概述
本节的大部分链接都是 wiki 上其他地方对这些术语的更详细的解释。这里的讨论是为了让那些以前从未见过它们的人对它们有一个广泛的概述。
ImgLib2
ImgLib2 是斐济使用的基础 Java 库,负责图像使用的所有底层数据结构。基本上,当您在斐济打开图像时,底层数据结构是一个 ImgLib2 Img 类,尽管上构建了许多层。ImgLib2 还有许多用于数据访问和处理的有用工具。强烈建议阅读ImgLib2 publication,以了解如何了解相关的上层存储和访问数据。
科学java
Scijava是不同库的集合,它为开发人员和用户之间以及您和基础数据结构和工具之间提供了非常有用的接口。其中包括许多基础的services,可以通过斐济的任何实例作为parameters使用。
IDE(集成开发环境)
IDE 是您编写代码的位置。强烈建议使用 IntelliJ_IDEA、NetBeans 或 Eclipse。
Maven
Maven是一个构建,将java代码打包成斐济可以识别的jar文件,并帮助您的项目进行库管理。Maven与主要的java IDE捆绑在一起。Maven属性通过pom.xml文件进行管理,下面将进一步讨论。
Git 和 Github
Git是一个版本控制工具,可用于将项目上传到存储库,并且还与主要IDE捆绑在一起。 Github是一个用于和管理git存储库的在线存储库,其中很多存储库都是开源的。
Scijava Maven 存储库
Scijava Maven Repository 是 Maven 构建项目的仓库,称为工件,其中包含 jar 文件。虽然 Maven 仓库(包括 Scijava 仓库)与 Maven 构建工具相关,而 pom.xml 文件的元素对于创建 Maven 仓库工件很重要,但它们看起来差不多不同(类似于 Git 和 Github)会有很大帮助。特别是因为你可以使用 Maven 构建工具,但不能在任何 Maven 中构建仓库存储库中。将您的项目资源并存储到 Scijava Maven 存储库中并不是必需的,因为您可以严格通过 update site 分发您的项目,但为其他开发人员和 PyImageJ 用户提供一个可用的项目资源。
配置您的环境
您将需要:
- Java 1.8 JDK(版本 1.8 也称为 Java 8)。推荐使用Azul Zulu JDK。
- IDE(推荐:IntelliJ_IDEA、NetBeans 或 Eclipse)
- Github账户(如果您想发布到SciJava Maven存储库,则需要,否则强烈推荐)。
- 如果您想发布到 Maven 存储库:未捆绑 Git
- 如果您想发布到 Maven 存储库:一堆 Apache Maven
- Fiji source code是任选帮助
用于测试本指南的环境:
- Windows 10 和 11,x86_64
- 蓝色祖鲁 1.8.x
- IntelliJ IDEA 2019.2.3 和 2024.3.1(社区版)
- git 2.x
- 阿帕奇Maven 3.x
所有§§0§§§均位于GitHub上。由于斐济现在是一个相当复杂的项目,其开发分成几个subprojects。对于初学者来说,很难理解不同可用项目之间的配合,这些项目都以“SciJava”标签为斐济做出了贡献。令人高兴的是,Maven利用斐济开发者社区提供的配置文件自动从所有斐济子项目中提取必要的代码。提供了斐济 SciJava ecosystem 的第一个概述。
为了使 Maven 工作,我们需要这样的 pom.xml文件。此配置文件包含有关项目的信息以及 Maven 用于构建项目的各种详细配置信息。pom.xml文件有助于组织构建项目所需的一切。可以通过该方法使用任何您想要的基于 Maven 的项目,而不是斐济。所以例如您可以通过这种方式Fiji github,或者单个插件,例如fiji/fiji。
总的来说,有其他替代策略来开发插件:
- 在没有 Maven 的情况下使用 IDE
- 将IDE与Maven结合使用(推荐)
使用 Fiji 教程插件以及 IntelliJ IDEA、Git 和 Maven 测试您的环境
设置IntelliJ
-确保您安装了 JDK 1.8.x 版本(注意:此版本可能很快就会更改为 JDK 21)
导入并构建项目:
- 运行IntelliJ IDEA
- 从主菜单中选择File › Project Structure… › Project
斐济插件
- 对于存储库 URL,输入:§§§CODE0§§§ 并选择要存储项目的本地文件夹
进口
- 单击“克隆”,所有源将被下载并作为新项目打开
- 如果 IntelliJ 要求导入所有 Maven 更改,您必须允许此操作
- 使用项目文件查看器,打开类文件tutorials/java/howtos/src/main/java/howto/ui/SwingExample。
- 在右上角附近,你应该会在下拉菜单旁边看到一个播放按钮。将下拉菜单应该设置为“当前文件”,然后单击播放按钮。这个运行该类并打开Fiji UI。
- 注意:如果播放按钮呈灰色,您可能需要在 IntelliJ 中设置 JDK。转到File › New › Project from Version Control › Git把 SDK 设置为您安装的 JDK。
howtos 项目包含许多教程和指南,其中许多可以以与 Swing UI 示例类似的方式运行。任何具有 §§0§§§方法的类都可以尝试运行,并非所有类都可以执行直接观察到的操作。这些教程是学习 Fiji 和 Scijava 代码各个编写方面的重要资源。
此 git 存储库中的另一个项目更能说明简单的插件项目,即 swing-example 项目。在该项目的 java 文件夹中,您应该找到三个不可运行的类和一个可运行的 SwingExample 类。 DeconvolutionCommand和DeconvolutionCommandSwing都实现了Plugin接口,使得当斐济打开它们时可以被Scijava的PluginService发现。您可以通过以下方式将这些命令添加到您的斐济:
- 展开 Maven 窗口,该窗口位于 IntelliJ 窗口的边缘之一(通常是右侧)。通过File › New › Project…展开,然后运行安装。这仅构建
swing-example项目,而不是像顶部的绿色箭头按钮那样构建每个项目。 - 项目构建完成后,文件查看器中应该会出现一个新的 §§2§§§ 目录,其中包含两个
.jar文件。将不以 -sources 结尾的 jar 文件传输到 Fiji 安装的 jars 目录。可以将文件从 IntelliJ 文件查看器直接拖动到 Windows 资源管理器。 - 打开斐济,你现在应该在顶部看到一个新的
Deconvolution菜单选项,其中有两个命令可用。
#斐济新项目的基本工作流程
教程
- 对于斐济:Writing plugins(注意:Writing plugins#Update_your_POM中的指令“更新您的父 POM”仅表示应调整版本号以反映 GitHub 上父 POM 文件的最新可用版本。)
- ImgLib2 Examples
- Developing ImgLib2
- ImageJ Ops
##入门
创建一个新的Java项目:
- IntelliJ:ImageJTutorials › Swing UI Command › Lifecycle
将构建设置为 Maven,并将 JDK 设置为您安装的 Java 8 SDK。创建项目将自动生成 Fiji 和 Scijava 项目使用的文件夹标准结构以及 pom.xml 文件。
您将需要编辑pom.xml文件才能正常工作才能进行斐济开发。根据this POM guide建立POM,并注意以下事项:
- 更新pom-scijava版本。要确定要使用的pom-scijava版本:首先确定当前的Fiji版本(更新Fiji并单击状态栏,第一个版本号是Fiji版本),然后导航到fiji/fiji,点击显示
main的下拉菜单,转到标签部分并找到当前的Fiji版本。最后,选择此版本的Fiji的pom.xml文件,推出的pom-scijava版本就是您想要在项目中使用的版本。 - 您的
artifactId:这应该与您的项目名称匹配,但没有任何空格或特殊字符。如果您希望遵循 Fiji 和 Scijava 开发人员使用的风格,则您的项目名称将全部小写,并用“-”表示空格。 - 您的
groupId:groupId通常是您正在开发的组的反向域名。如果您单独开发一个项目,当前的通常规定是使用net.作为groupId。 version:建议您的项目使用Semantic versioning。请注意,您通常希望使用以-SNAPSHOT结尾的版本号将其标记为公开的工作,通过将版本发布到 Maven 存储库(如下所述),可以自动删除此 SNAPSHOT 标签。 -添加您的dependencies:POM 指南中推出了常见依赖项。 -添加developer信息- 根据项目的 github 存储库添加
scm信息。
配置完成 pom.xml 文件后,您可以将新的 Java 类文件添加到 src/main/java 文件夹中以开始编写代码。该文件的结构与上面讨论的 SwingExample 中的结构类似,有关详细更多信息,请参阅插件教程部分中的指南。有关如何为 SciJava 编写 Java 代码的指南,请参阅上面的教程。
进一步阅读
构建并测试您的项目
与Fiji tutorials repository不同的目标,您的项目可能没有多个构建目标,当您的代码准备好时,您可以使用 Maven 面板中的绿色箭头来构建您的项目。将您的类资源粘贴到 target 文件夹中的 jar 文件中。生成的 jar 文件(没有附加扩展名的文件)可以放置在 斐济 的 jars文件夹中,如果您的项目带有正确的@Plugin注释的命令,则下次启动Fiji时应该会自动识别它。
除了通过 Fiji 运行项目来测试之外,通常您还可以利用可运行的 Java 类(结构 Fiji tutorials 中的 SwingExample 文件)直接从 IDE 访问和测试项目项目。这些类通常放置在 src/test/java/ 文件夹中,这样它们就不会与构建时生成的主 .jar 文件相连接。这些文件使用窗口顶部的绿色箭头run直接按钮可以从IntelliJ IDEA 运行(与 Maven 面板运行按钮不同)。
更进一步,可以使用JUnit5测试框架在每个构建上自动完成测试。为了使这些单元测试正常工作,需要修改pom.xml文件,如下面的附录“使用JUnit5进行测试”部分所示。
使用 Github
大多数 GitHub 功能都可以在 IntelliJ 中的 Git 菜单下直接管理。最常见:Git › Push用于项目进行的更改标记为commit。Git › Commit用于将这些更改到 GitHub 存储库。您还可以通过 IDE 的Git菜单管理您的分支。首次发布后,建议您将任何启动的工作分支到非主分支,并且仅在代码一个工作状态后才分支分支合并到main上。
###添加许可证 对于项目建立版权规则是非常重要的一步,通过设置项目的许可证来完成,通常通过在 pom.xml 文件中设置属性并在上传到 github 存储库的 LICENSE.TXT 文件中添加许可证文本来完成。有关版权和许可及其重要性的详细概述,请参见§§0§§§,有关斐济及项目许可的信息请参见here。
发布你的项目
一旦您的项目处于安全状态(不要忘记尽早发布、经常发布的SciJava philosophy),有几个选项可以将您的项目发布给其他人。建议同时执行这两个操作,但它们并不相互依赖,因此您只可以执行其中一个。
使用 Github 操作到 Maven 存储库
部署到 Scijava Maven Repository 最常由其他开发使用的库完成,并且它们对于开发人员使用的库也很重要,因为这使得可以轻松添加为其他项目的依赖项。然而,将项目存入 Maven Repositroy 对于小型插件也有一些好处,最重要的是它允许 PyImageJ轻松地initialized with access to your plugin。它还维护了插件的所有先前发布的实例和源代码的积压,允许用户专门下载旧版本。您将看到首次将项目上传到 SciJava Maven 存储库的标准流程的简化概述。本概述做出了一些可能真实的假设,并根据这些假设省略了不必要的。有关此过程的更详细细节概述,请参阅development lifecycle page。 首先,您需要执行以下操作:
- 将
<releaseProfiles>deploy-to-scijava</releaseProfiles>添加到 pom.xml 文件的<Properties>部分。该项目已发布到 SciJava 存储库。 - 如果您的项目当前位于个人 Github 帐户上,请create a Github organization将您的项目转移到该帐户。创建 GitHub 组织是免费、简单的,并且不需要单独的帐户。项目转移后,请求向新组织授权授权,以部署到 §§3§§§ 上的 Scijava Maven 存储库。
完成这些后,您需要(按顺序):
- 将 Scijava Scripts GitHub 存储库克隆到您的本地计算机。
- 将包含 Scijava 脚本的脚本添加到操作系统的 PATH 环境变量中。
3.导航到包含
pom.xml文件的项目文件夹,右键单击并选择Git Bash Here。 - 输入
github-actionify.sh运行 github actionify 脚本的模拟。如有必要,请解决任何问题或错误。一旦一切看起来都不错,请输入github-actionify.sh -f运行实际操作。github actionify 脚本将在您的项目中创建新文件,并把它们放到项目的 GitHub 存储库中。
完成所有这些步骤后,您的项目就可以作为工件定期部署到 SciJava Maven 存储库。所有工件到 GitHub 存储库main分支的操作都将由 github-actionify 脚本创建的新 GitHub 操作产生,以工件部署到 SciJava Maven 的快照部分。要发布完整版本,请再次打开项目 pom.xml 文件夹中的 Git Bash,然后运行release-version.sh。系统会询问您要发布哪个版本(通常是您当前的版本号,不带-SNAPSHOT),该脚本将执行以下几项操作:
- 检查pom.xml文件的格式以确保一切正常。如果SciJava Parent POM Maven早于当前斐济版本配置(通常是这样),则在运行脚本时可能需要添加 –skip-version-check 选项。
- 创建并创建一个 GitHub 标签,其中包含该特定版本的源代码。
- 提供配置给 SciJava Maven 存储库的发布部分的 Maven 工件版本。
- 自动迭代到您的
main分支的下一个 -SNAPSHOT 版本,并将其自适应到 GitHub。
发布新版本后,您的插件应该可以通过 SciJava Maven 存储库获得,并且您可以准备好开发下一个版本。
前往ImageJ更新站点
与 Maven 存储库不同,ImageJ update site 不存储项目的多个版本,仅存储最近上传的版本。但是,更新站点是典型的斐济用户获取创建工具(特别是插件)的方式。有关如何创建和上传到更新站点的详细说明,请参见here。有关将更新站点添加到标准斐济更新管理器列表的说明,请参见简介here。
其他参考资料
以及文中引用的所有其他链接!
# 附录
如何找到依赖项?
您可以按类别搜索 maven.scijava.org 来查找 Maven 工件。例如,search for §§§CODE0§§§。
如果您熟悉命令行工具,您还可以使用Maven Dependency Plugin,它使您能够执行诸如下载依赖项 jar 的本地副本以进行检查之类的操作。
另外,mvnrepository.com是一个很好的资源,可以找到包含代码的存储库,您可以轻松跳转代码复制并粘贴到pom.xml中。
管理 Java 版本
This section is unmodified and untested from the original beginner’s guide
在Linux上可以安装多个java版本。在终端窗口中选择首选版本(例如bash):
update-alternatives --config java
注意:可能需要使用sudo。
如果需要使用,请告知 NetBeans JDK 1.8 作为新项目的默认 JRE(即在 Debian Linux 上:File › New Project /usr/lib/jvm/java-1.8.0-openjdk-amd64),或者在 NetBeans 配置文件中设置 netbeans_jdkhome 属性。应该位于本地 NetBeans 目录中,例如 ./netbeans-8.0/netbeans.conf。
插件的目录结构是什么?
本文改编自Maven页面。
一个非常简单的演示项目的目录结构如下:
DemoPlugin
|-- pom.xml
|-- src
| !-- main
| |-- java
| | !-- MyPlugin.java
| !-- resources
| !-- sample-image.tif
| !-- test
编译 java 文件后,Maven 会自动生成 target 文件夹的内容。:因此将 target 中的任何文件提交到 Git!您可以使用 .gitignore文件告诉 Git 忽略其他这些文件(通常您首先从项目复制an existing one)
!-- target
|-- classes
| |-- sample-image.tif
| |-- META-INF
| | !-- json
| | !-- org.scijava.plugin.Plugin
| !-- MyPlugin.class
|-- generated-sources
| !-- annotations
|-- maven-status
| !-- maven-compiler-plugin
| !-- compile
| !-- default-compile
| |-- createdFiles.lst
| !-- inputFiles.lst
!-- test-classes
总体:
将您的 .java 文件放在 src/main/java/ 下,同时需要包含的其他文件放入 src/main/resources/ 中。用于测试项目的任何辅助类或脚本都将放置在 src/test 文件夹中。
如果您想应用称为“回归测试”甚至“测试驱动开发”的最佳实践,则将测试的.java文件放入src/test/java/中,把您可能需要的非.java文件放入src/test/resources/中。
有关Maven标准目录布局的更多信息可以在Maven website上找到。
斐济插件是否可见仍需要下划线?
如果您编写了 Fiji 命令插件(即:使用 @Plugin 注释实现 org.scijava.command.Command 接口),则不再需要下划线。
如何将现有项目迁移到Maven项目?
This section is unmodified and untested from the original beginner’s guide
在Netbeans中
- 备份您的项目。
- 创建一个名为
NewMavenProject的新项目。 - 关闭您的原始项目。
- 从imagej/minimal-ij1-plugin或其他适当的模板复制
pom.xml。 - 修改
pom.xml的项目特定设置(例如项目名称、依赖项)。 - 删除
build.xml和整个nbproject文件夹。 - 将文件夹移动并重命名为
src/main/newproject(newproject是新名称)。 - 将
src/java移至src/main/java。 - 在 NetBeans 中再次打开您的项目。现在应该是一个 Maven 项目了。
- 删除不需要的
NewMavenProject项目。
在 IntelliJ IDEA 中
- 使用Project Properties › Build › Compile…创建一个新的Maven项目
- 选择左侧的Maven,然后单击下一步
- 选择您的自定义 GroupID(例如 com.yourwebsite)和 ArtifactID 作为该项目的单一标识符(例如 project_name)
- 请注意,对于 ImageJ 1.x 插件,项目名称/标识符中需要有一个“_” ImageJ 1.x 插件
- 项目将为您创建 Maven 所需的结构
- 对于Git支持(推荐):VCS › Import into Version Control › Git
- 将所有
.java文件复制到[project_name]/src/main/java - 将
plugins.config文件复制到 [project_name]/src/main/resources - 在主项目目录 [project_name]/ 中,您可以找到
pom.xml,必须像上一章中所示的示例一样进行编辑 - 如果您的 IDE 要求导入所有 Maven 更改,您必须允许此操作
- 展开位于 IntelliJ 边缘窗口的 Maven 窗口之一,然后选择您的项目
- 在这里,您可以右键单击并运行 Maven Build,或者在 Maven 窗口中按其上方的绿色箭头来构建您的项目
- 构建过程将在 [project_name]/targets/ 下生成多个
.jar文件
使用JUnit5进行测试
在 IntelliJ IDEA 中,您可能确保需要 JUnit5 插件已激活。下一步只需将以下行附加到您的 pom.xml 文件中:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.5.1</version>
<scope>test</scope>
</dependency>
<build>
<plugins>
<plugin>
<!-- fix maven tests -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<excludes>
<exclude>some test to exclude here</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>