0


IntelliJ IDE 插件开发 | (二)UI 界面与数据持久化

系列文章

  • IntelliJ IDE 插件开发 |(一)快速入门
  • IntelliJ IDE 插件开发 |(二)UI 界面与数据持久化
  • IntelliJ IDE 插件开发 |(三)消息通知与事件监听

前言

在上一篇文章中介绍了在

  1. IDEA

下开发、运行和安装插件的基本步骤,因此创建项目等基础步骤不再赘述,本文则开始介绍如何进行 UI 界面的开发以及相关数据的持久化存储,本文涉及到的的完整代码已上传到Github。

UI 界面开发

在开发插件的过程中,我们或多或少都需要进行 UI 界面的开发,但是

  1. IntelliJ IDE

插件需要使用

  1. Swing

进行 UI 的开发,相信大部分人都不太了解,因此本文及后续文章都选择使用

  1. UI Designer

这款插件(IDEA 默认安装,可自行检查一下)通过可视化工具拖拽的方式来实现基本的界面设计。

image-20231205165021976

UI Designer 使用步骤

在上一篇文章中提到过,后续 UI 相关的开发使用 Java,其他则使用 Kolin,由于默认创建的工程目录如下,没有 Java 模块:

image-20231206094935959

所有我们首先需要创建 Java 模块:

image-20231206095044404

然后按照引导创建 UI 文件:

Clip_20231206_095314

image-20231206095502253

创建完成后,会出现类似下图的界面:

image-20231206100144787

可以看到,默认会创建一个 Java 类和一个 form 布局文件,其中 Java 文件主要用于后续控制字段的初始化及获取等操作,form 文件则用于界面布局,点击 form 文件会出现上图所示的三个栏目:组件属性栏、UI 效果栏和组件栏,其中先选中右侧组件然后就可以拖拽到中间的 UI 效果栏展示。

下面我们用一个简单的登录表单来讲解使用方式,首先以一个 GIF 演示拖拽功能开始:

修改 Label 的内容可以通过左侧工具栏或者直接在 UI 效果栏双击标签进行:

image-20231206104111547

输入框对应的字段名则通过左侧组件属性栏进行修改:

image-20231206104321338

这时候我们查看 UIDemo.java 文件会发现以下内容(注释随自己的配置变化):

  1. importjavax.swing.*;/**
  2. * UI 界面
  3. *
  4. * @author butterfly
  5. * @date 2023-12-06
  6. */publicclassUIDemo{privateJTextField username;privateJTextField password;}

然后通过预览功能,我们也可以先查看表单效果:

动画

简单的使用步骤就到这里,这里就不挨个讲解组件的效果和使用方式了,后续会在使用的过程和实战应用中再进行讲解,大家也可以先自行探索。

使用平台自带组件

在上一小节中我们讲解了如何通过

  1. UI Designer

插件来创建我们的 UI 界面,可以发现默认提供的 Swing UI 组件并没有办法满足我们的日常使用,比如文件下拉树选择组件就不存在。而我们对 Swing 的开发又不熟悉,那该怎么办呢?还好,我们还可以使用 IntelliJ 平台自带的组件,下面就来讲解使用方法:

首先在空白处右键创建一个分组:

image-20231206110825049

image-20231206110838272

然后右键分组选择第一项添加组件:

image-20231206110928930

选择类名的方式,然后点击

  1. ...

image-20231206111101478

这里输入

  1. TextFieldWithBrowseButton

即可找到带有文件下拉树选择输入框:

image-20231206111329419

然后经过两次确认就可以发现组件已经添加到了右侧组件栏中:

image-20231206111601608

由于 UI Designer 的预览功能不支持原生组件的预览,需要运行插件才可以,这里先知道是类似下图选择文件夹的效果即可:

image-20231206144400519

平台自带的组件大多都可以在

  1. com.intellij.openapi.ui

包下找到,根据组件名

  1. TextFieldWithBrowseButton

我们也可以发现相关组件的命名也很规范,因此当需要某个组件时就可以先在该包下或者通过关键字进行搜索,除此之外,我们还可以参考开源插件来找到和学习原生组件的使用方式。

以 Git 插件为例,布局如下:

image-20231206150121611

可以在官方仓库找到源码(这里选择的是 192 版本这个分支,之后的版本布局开始使用 Kotlin 进行了重构):

image-20231206152416294

image-20231206150819587

根据插件界面可以发现第一行就是使用带有文件树选择的输入框,我们在代码中也可以找到对应实现:

image-20231206151233997

image-20231206151309499

由于 192 版本之后使用 Kotlin 进行 UI 的编写,因此初学建议可以下载一个 192 的 IDEA 社区版进行界面的参考,这样通过参考布局及相应源码也是快速学习 UI 界面开发的一种方法。

至于如何快速找到插件的某个组件实现,这里建议在下载源码后,就可以根据界面上的提示文字进行代码的全局搜索即可。

在配置界面和侧边栏中展示 UI 界面

通过上述两步,我们可以了解到如何实现开发一个简单的 UI 界面,下面就开始讲解如何将设计好的界面展示在配置页面或者侧边栏中。

准备工作

在正式开始之前我们需要对上文中创建的界面进行一些修改,布局外层的 Panel 需要先设置一下字段名:

image-20231206155142916

然后增加相应的 Get 方法:

  1. importjavax.swing.*;/**
  2. * UI 界面
  3. *
  4. * @author butterfly
  5. * @date 2023-12-06
  6. */publicclassUIDemo{privateJTextField username;privateJTextField password;privateJPanel mainPanel;publicJPanelgetMainPanel(){return mainPanel;}}

准备工作到此结束。

配置界面 UI

接下来就是将 UI 展示在配置界面,我们先创建一个

  1. UISettingsConfig.kt

文件:

  1. import cn.butterfly.ui.UIDemo
  2. import com.intellij.openapi.options.Configurable
  3. import javax.swing.JComponent
  4. /**
  5. * UI 配置界面配置类
  6. *
  7. * @author butterfly
  8. * @date 2023-12-06
  9. */class UISettingsConfig: Configurable {privateval form =UIDemo()privateval component: JComponent
  10. init{
  11. component = form.mainPanel
  12. }overridefuncreateComponent()= component
  13. overridefunisModified()=trueoverridefunapply(){}overridefungetDisplayName()="UISettingsConfig"}

然后在

  1. plugin.xml

文件中进行如下的配置,这里的

  1. applicationConfigurable

代表使用应用级别的配置,相应地,还有

  1. projectConfigurable

代表项目级别的配置,具体区别在下文的数据持久化中进行介绍:

  1. <extensionsdefaultExtensionNs="com.intellij"><applicationConfigurableinstance="cn.butterfly.ui.config.UISettingsConfig"id="cn.butterfly.ui.config.UISettingsConfig"displayName="UISettingsConfig"/></extensions>

这里我们运行插件,打开配置界面就可以发现我们的界面效果了:

image-20231206160442085

如果想要修改其显示位置,比如显示在

  1. Tools

菜单下:

image-20231206160426698

只需要在配置中增加

  1. parentId="tools"

即可:

  1. <applicationConfigurableinstance="cn.butterfly.ui.config.UISettingsConfig"id="cn.butterfly.ui.config.UISettingsConfig"parentId="tools"displayName="UISettingsConfig"/>
  1. applicationConfigurable

中完整的配置项可查看官网文档。

侧边栏界面 UI

最后再来说明如何在侧边栏中显示界面,首先创建一个

  1. UISidebarConfig.kt

  1. import cn.butterfly.ui.UIDemo
  2. import com.intellij.openapi.project.Project
  3. import com.intellij.openapi.wm.ToolWindow
  4. import com.intellij.openapi.wm.ToolWindowFactory
  5. import com.intellij.ui.content.ContentFactory
  6. import javax.swing.JComponent
  7. /**
  8. * UI 侧边栏界面配置类
  9. *
  10. * @author butterfly
  11. * @date 2023-12-06
  12. */class UISidebarConfig: ToolWindowFactory {privateval form =UIDemo()privateval component: JComponent
  13. init{
  14. component = form.mainPanel
  15. }overridefuncreateToolWindowContent(project: Project, toolWindow: ToolWindow){
  16. toolWindow.contentManager.addContent(
  17. ContentFactory.getInstance().createContent(component,"",false))}}

然后我们可以准备一个 svg 图标文件用于后续在侧边栏展示:

image-20231206162613699

同时需要创建对应的文件加载接口:

image-20231206163645276

  1. importcom.intellij.openapi.util.IconLoader;importjavax.swing.*;/**
  2. * 插件图标
  3. *
  4. * @author butterfly
  5. * @date 2023-12-06
  6. */publicinterfacePluginIcons{IconBUTTERFLY=IconLoader.getIcon("/icons/butterfly.svg",PluginIcons.class);}

然后在

  1. plugin.xml

配置文件中进行如下设置即可,

  1. anchor

可设置默认位置,

  1. icon

用于设置上文的图标:

  1. <extensionsdefaultExtensionNs="com.intellij"><toolWindowid="UISettingsConfig"anchor="right"factoryClass="cn.butterfly.ui.config.UISidebarConfig"icon="cn.butterfly.ui.icons.PluginIcons.BUTTERFLY"/></extensions>

运行插件,即可在右侧的侧边栏看到我们设置的界面:

image-20231206164451821

数据持久化

讲完了界面开发的相关内容,下面就开始介绍如何进行配置数据的持久化,首先是创建一个存储数据信息的

  1. UIDemoState.kt

文件:

  1. import com.intellij.openapi.components.PersistentStateComponent
  2. import com.intellij.openapi.components.Service
  3. import com.intellij.openapi.components.State
  4. import com.intellij.openapi.components.Storage
  5. import com.intellij.util.xmlb.XmlSerializerUtil
  6. /**
  7. * 数据持久化存储
  8. *
  9. * @author butterfly
  10. * @date 2023-12-06
  11. */@Service@State(name ="UIDemoState", storages =[Storage("ui-demo-state.xml")])class UIDemoState: PersistentStateComponent<UIDemoState>{var username =""var password =""overridefungetState(): UIDemoState {returnthis}overridefunloadState(state: UIDemoState){
  12. XmlSerializerUtil.copyBean(state,this)}}

其中

  1. username

  1. password

对应表单中我们设置的两个字段,这里设置了默认值为空字符串,

  1. ui-demo-state.xml

用于设置数据持久化存储的文件名。

然后我们需要对前文中创建的布局文件进行些许的修改,增加字段的 Get 方法:

  1. importjavax.swing.*;/**
  2. * UI 界面
  3. *
  4. * @author butterfly
  5. * @date 2023-12-06
  6. */publicclassUIDemo{/**
  7. * 用户名
  8. */privateJTextField username;/**
  9. * 密码
  10. */privateJTextField password;privateJPanel mainPanel;publicJTextFieldgetUsername(){return username;}publicJTextFieldgetPassword(){return password;}publicJPanelgetMainPanel(){return mainPanel;}}

最后我们就需要对前文中创建的

  1. UISettingsConfig.kt

文件进行修改,用于处理界面上保存数据的操作:

  1. import cn.butterfly.ui.UIDemo
  2. import cn.butterfly.ui.state.UIDemoState
  3. import com.intellij.openapi.application.ApplicationManager
  4. import com.intellij.openapi.options.Configurable
  5. import javax.swing.JComponent
  6. /**
  7. * UI 配置界面配置类
  8. *
  9. * @author butterfly
  10. * @date 2023-12-06
  11. */class UISettingsConfig: Configurable {privateval form =UIDemo()privateval component: JComponent
  12. privateval state = ApplicationManager.getApplication().getService(UIDemoState::class.java)init{
  13. component = form.mainPanel
  14. reset()}overridefuncreateComponent()= component
  15. overridefunisModified(): Boolean {return state.username != form.username.text || state.password != form.password.text
  16. }overridefunapply(){
  17. state.username = form.username.text
  18. state.password = form.password.text
  19. }overridefunreset(){
  20. form.username.text = state.username
  21. form.password.text = state.password
  22. }overridefungetDisplayName()="UISettingsConfig"}

其中

  1. reset

用于重置表单内容为修改前设置的值,

  1. apply

用于保存当前修改,

  1. isModified

用于判断当前数据和上次数据之间是否存在不同,用于

  1. Apply

按钮的禁用/激活状态的切换,这三个操作对应界面上的效果如下:

image-20231206180134340

image-20231206180129318

那我们的配置文件存储位置是在哪里呢?

由于在前文中我们使用

  1. applicationConfigurable

选择了应用级别的存储,因此文件就存储在 IDEA 默认的配置文件存储地址:

  1. C:\Users\用户名\AppData\Roaming\JetBrains\IntelliJIdea2023.2\options

,其中

  1. IntelliJIdea2023.2

对应自己使用的 IDEA 名称。不过,由于我们当前是通过沙盒环境运行,所以位置并不是全局设置的位置,而是在

  1. build/idea-sandbox/config/options

下:

image-20231206181847391

当我们将插件安装到我们正式的 IDEA 中,也就可以在上述的位置下发现配置文件了:

image-20231206182446451

如果我们将配置设为

  1. projectConfigurable

选择项目级别,那么首先需要对配置文件进行如下修改:

  1. <extensionsdefaultExtensionNs="com.intellij"><projectConfigurableinstance="cn.butterfly.ui.config.UISettingsConfig"id="cn.butterfly.ui.config.UISettingsConfig"parentId="tools"displayName="UISettingsConfig"/></extensions>

同时修改

  1. UIDemoState.kt

文件上的注解配置:

  1. import com.intellij.openapi.components.PersistentStateComponent
  2. import com.intellij.openapi.components.Service
  3. import com.intellij.openapi.components.State
  4. import com.intellij.openapi.components.Storage
  5. import com.intellij.util.xmlb.XmlSerializerUtil
  6. /**
  7. * 数据持久化存储
  8. *
  9. * @author butterfly
  10. * @date 2023-12-06
  11. */@Service(Service.Level.PROJECT)// 只修改该行@State(name ="UIDemoState", storages =[Storage("ui-demo-state.xml")])class UIDemoState: PersistentStateComponent<UIDemoState>{var username =""var password =""overridefungetState(): UIDemoState {returnthis}overridefunloadState(state: UIDemoState){
  12. XmlSerializerUtil.copyBean(state,this)}}

最后还需要修改

  1. UISettingsConfig.kt

文件,增加一个 project 的构造参数并修改 state 的初始化:

  1. import cn.butterfly.ui.UIDemo
  2. import cn.butterfly.ui.state.UIDemoState
  3. import com.intellij.openapi.options.Configurable
  4. import com.intellij.openapi.project.Project
  5. import javax.swing.JComponent
  6. /**
  7. * UI 配置界面配置类
  8. *
  9. * @author butterfly
  10. * @date 2023-12-06
  11. */// 增加 project: Project 构造参数classUISettingsConfig(project: Project): Configurable {privateval form =UIDemo()privateval component: JComponent
  12. // 修改该行privateval state = project.getService(UIDemoState::class.java)init{
  13. component = form.mainPanel
  14. reset()}overridefuncreateComponent()= component
  15. overridefunisModified(): Boolean {return state.username != form.username.text || state.password != form.password.text
  16. }overridefunapply(){
  17. state.username = form.username.text
  18. state.password = form.password.text
  19. }overridefunreset(){
  20. form.username.text = state.username
  21. form.password.text = state.password
  22. }overridefungetDisplayName()="UISettingsConfig"}

然后我们就可以在项目下的

  1. .idea

文件夹中找到我们针对项目级别的配置了:

image-20231206185943881

至于读取配置文件,则通过

  1. private val state = project.getService(UIDemoState::class.java)

或者

  1. private val state = ApplicationManager.getApplication().getService(UIDemoState::class.java)

分别换取项目或应用级别的 state 对象,然后读取其中的字段即可。

总结

本文讲解了关于 UI 界面开发和数据持久化相关的内容,如果有错误或不足之处,欢迎一起交流讨论。


本文转载自: https://blog.csdn.net/qq_41698074/article/details/134839173
版权归原作者 庄周de蝴蝶 所有, 如有侵权,请联系我们删除。

“IntelliJ IDE 插件开发 | (二)UI 界面与数据持久化”的评论:

还没有评论