在IntelliJ IDEA中,开发一个摸鱼看书插件
作者:小傅哥
博客:https://bugstack.cn
原文:https://mp.weixin.qq.com/s/R8qvoSNyedVM95Ty8sbhgg
沉淀、分享、成长,让自己和他人都能有所收获!
一、说明
方向不对,努力白费!
总有人拿到产品的需求,就着急开干,反正也懒的想开发中会发生啥,上线后多少人使用,管它三七二十一先堆起来代码看一看,反正能跑就行,无论代码还是你!
其实很多时候在编写代码前,所需要做的技术调研、架构设计、模块分层、数据结构、详细分析、方案评审等,与三七二十一那家伙对比起来,好像都会显得有点慢。但这个看上去慢的过程,却能解决以后很多常见和麻烦的问题,比如产品需求迭代、业务流程变更、代码逻辑更改、线上异常排查。虽然看着慢,但这个积基树本的过程就像打地基一样,总得有一个稳定的根基,才能盖好整栋大楼。万丈高楼平地起,勿在浮沙筑高台
二、需求目的
如果你需要开发一个自定义功能的插件,无论是处理代码、辅助ORM生成、日志信息记录等,都会需要进行一个插件的功能配置进行初始化操作以及把对应功能展示到整个 IDEA 窗体中的右边栏或者下边栏中,这样才能满足一个插件的基本需求。
那么这样就需要在 IDEA 窗体 File -> Settings 中扩展自己的配置窗体,以及开发自己需要的 ToolWindow 嵌入到 IDEA 中(左侧、右侧、下侧),这里窗体的开发需要用到 Swing 但目前在 IDEA 中开发这样的功能只需要拖拽窗体就可以,还是蛮容易的。
那么接下来我们以一个在 IDEA 中摸鱼看书的场景为案例,学习配置窗体和阅读窗体的功能实现。
三、案例开发
1. 工程结构
guide-idea-plugin-tool-window
├── .gradle
└── src
├── main
│ └── java
│ └── cn.bugstack.guide.idea.plugin
│ └── factory
│ │ ├── ReadFactory.java
│ │ └── SettingFactory.java
│ └── ui
│ │ ├── ReadUI.java
│ │ ├── ReadUI.form
│ │ ├── SettingUI.java
│ │ └── SettingUI.form
│ └── Config
├── resources
│ └── META-INF
│ └── plugin.xml
├── build.gradle
└── gradle.properties
- 源码获取:#公众号:
bugstack虫洞栈回复:idea即可下载全部 IDEA 插件开发源码
此工程主要涉及两部分,在factory中一个是配置窗体、一个是阅读窗体,与之对应的两组UI的实现。最后 factory 类的实现都会配置到 plugin.xml 中进行使用,同时也是在 plugin.xml 中控制窗体位置和图标。
2. 创建 UI 窗体
2.1 创建方式
New -> Swing UI Designer -> GUI Form

- 在 Java 中创建窗体的方式主要有 AWT、Swing、JavaFx,由于 IDEA 使用 Swing 开发,所以这里创建 Swing 窗体的兼容性会更好。
- 那么这里 Swing 窗体的创建可以是自己手写窗体结构,也可以使用可视化拖拽的 GUI Form 如果你的窗体不复杂,其实拖拽的方式就可以满足使用。
2.2 配置页窗体
public class SettingUI {
private JPanel mainPanel;
private JPanel settingPanel;
private JLabel urlLabel;
private JTextField urlTextField;
private JButton urlBtn;
public SettingUI() {
// 给按钮添加一个选择文件的事件
urlBtn.addActionListener(e -> {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.showOpenDialog(settingPanel);
File file = fileChooser.getSelectedFile();
urlTextField.setText(file.getPath());
});
}
public JComponent getComponent() {
return mainPanel;
}
public JTextField getUrlTextField() {
return urlTextField;
}
}

- 配置页窗体主要提供文章路径的选择,这里需要用到的标签包括:JLabel、JTextField、JButton
- 在使用 GUI Form 创建完窗体后,就会出现这样一个可视化的页面,右侧可以把各类标签拖到中间的面板中,左侧进行设置展示名称和属性名称。
- 最终这里的代码标签代码会展示到
SettingUI.java中,而渲染内容会被隐藏,这样的方式也比较方便控制一些自定义内容的添加,例如事件和新窗体等 - 另外在
SettingUI.java中,还需要在构造函数添加一个按钮事件,用于打开文件选择器,把我们需要打开的文件,设置到urlTextField中。
2.3 阅读页窗体
public class ReadUI {
private JPanel mainPanel;
private JTextPane textContent;
public JComponent getComponent() {
return mainPanel;
}
public JTextPane getTextContent() {
return textContent;
}
}

- 在窗体创建和配置页窗体是一样的,也是通过拖拽到面板中,用于展示路径文件内容。
- 你可以适当的添加一些其他按钮进去,比如翻页阅读、滚动条、字数展示等。
3. ToolWindow 工具框
为了把我们自己实现的阅读窗体放到整个 IDEA 右侧侧边栏中,我们需要创建一个实现了 ToolWindowFactory 的接口,并把实现类配置到 plugin.xml 中
public class ReadFactory implements ToolWindowFactory {
private ReadUI readUI = new ReadUI();
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
// 获取内容工厂的实例
ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
// 获取 ToolWindow 显示的内容
Content content = contentFactory.createContent(readUI.getComponent(), "", false);
// 设置 ToolWindow 显示的内容
toolWindow.getContentManager().addContent(content);
// 全局使用
Config.readUI = readUI;
}
}
- 接口方法
ToolWindowFactory#createToolWindowContent是需要自己工具框类实现的方法,在这个createToolWindowContent方法中把自己的窗体ReadUI实例化后填充进去即可。 - 添加窗体的补助主要依赖于
ContentFactory.SERVICE.getInstance()创建出 ContentFactory 并最终使用 toolWindow 添加窗体显示 UI 即可。 - 这里我们额外的还添加了一个全局属性
Config.readUI这是为了后续可以在配置窗体中使用这个 UI 进行设置文件内容。
4. Configurable 配置框
public class SettingFactory implements SearchableConfigurable {
private SettingUI settingUI = new SettingUI();
@Override
public @NotNull String getId() {
return "test.id";
}
@Override
public @Nls(capitalization = Nls.Capitalization.Title) String getDisplayName() {
return "test-config";
}
@Override
public @Nullable JComponent createComponent() {
return settingUI.getComponent();
}
@Override
public boolean isModified() {
return true;
}
@Override
public void apply() throws ConfigurationException {
String url = settingUI.getUrlTextField().getText();
// 设置文本信息
try {
File file = new File(url);
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
randomAccessFile.seek(0);
byte[] bytes = new byte[1024 * 1024];
int readSize = randomAccessFile.read(bytes);
byte[] copy = new byte[readSize];
System.arraycopy(bytes, 0, copy, 0, readSize);
String str = new String(copy, StandardCharsets.UTF_8);
// 设置内容
Config.readUI.getTextContent().setText(str);
} catch (Exception ignore) {
}
}
}
- 实现自 SearchableConfigurable 接口的方法比较多,包括:getId、getDisplayName、
createComponent、isModified、apply这些里面用于写逻辑实现的主要是createComponent和apply - createComponent 方法主要是把我们自己创建的 UI 面板提供给 JComponent
- apply 是一个事件,当我们点击完成配置的 OK、完成,时候就会触发到这个方法。在这个方法中我们拿到文件的 URL 地址使用
RandomAccessFile进行读取解析文件,并最终把文件内容展示到阅读窗体中Config.readUI.getTextContent().setText(str);
5. 配置 plugin.xml
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<!-- 配置 File -> Settings -> Tools -->
<projectConfigurable groupId="tools" displayName="My Test Config" id="test.id"
instance="cn.bugstack.guide.idea.plugin.factory.SettingFactory"/>
<!-- 窗体 (IDEA 界面右侧) -->
<toolWindow id="Read-Book" secondary="false" anchor="right" icon="/icons/logo.png"
factoryClass="cn.bugstack.guide.idea.plugin.factory.ReadFactory"/>
</extensions>
- 本次在 plugin.xml 中的主要配置内容就是 projectConfigurable 和 toolWindow,另外在 toolWindow 中还添加了一个 icon 的 logo,配置完成后就可以在 IDEA 页面展示出我们的自己添加的窗体了。
四、插件测试
- 通过 Plugin 启动插件,这个时候会打开一个新的 IDEA 窗体,在这个新窗体中就可以看到我们添加的功能了。
配置文件路径

- 点击选择按钮,选择你的文件位置,选择后点击 OK
查看展示文件

- 确认好文件路径后,就可以再右侧栏看到自己的文件展示内容了。是不是在扩展些,就适合你摸鱼了!?
五、总结
- 学习自定义开发UI,把UI填充到需要放置的 IDEA 窗体位置,并在窗体中添加功能的流程步骤,其实主要包括三方面:Swing UI、Factory 实现类、plugin 配置。
- 在 plugin 配置中,主要包括如窗体ID、位置、icon图标、对应的实现类,如果不添加这些是不能正常展示窗体信息的。
- 另外可以以这个案例为基础,添加自己想完成的功能,比如让这个摸鱼看书的功能更加完善,可以支持不同类型的文件,甚至可以是 PDF 的阅读,以及你想看的书籍。
六、系列推荐
- IDEA 插件怎么开发?
- 如何发布Jar包到Maven中心仓库
- 12种 vo2dto 方法,就 BeanUtils.copyProperties 压测最拉胯!
- 炸!1024,小傅哥的博客升级啦,文章开源、支持PR,冲哇!
- 面经手册 · 开篇《面试官都问我啥》
在IntelliJ IDEA中,开发一个摸鱼看书插件的更多相关文章
- 用 WinUI 3 开发了一个摸鱼应用
1. 开发了一个摸鱼 App 我做了一个简单的 App:摸鱼. 如上图所示,这个 App 就只有一个按钮,点击后假装开始 Windows Update,然后用户就可以光明正大地摸鱼了. 不要小看摸鱼, ...
- spark (java API) 在Intellij IDEA中开发并运行
概述:Spark 程序开发,调试和运行,intellij idea开发Spark java程序. 分两部分,第一部分基于intellij idea开发Spark实例程序并在intellij IDEA中 ...
- 模仿写了一个摸鱼APP解决原作者的问题
前几天见到微博里有人提到摸鱼APP,发现需要在windows store下载才可以使用,文件约100多M左右的样子,自已没有登录微软Store的习惯.想想只有一个介面,没有必要这么大,于是,自已动手写 ...
- 在Visual Studio中开发一个C语言程序
→新建一个项目→选择"其他语言","Visual C++",并选择"win32控制台应用程序",并给控制台应用程序起名.→点击"下 ...
- 十分钟开发一个调用Activity的PhoneGap插件
在HybridApp开发中,非常多业务我们是没有办法通过HTML5+js实现的,比方调用第三方的包括Activity的jar包,一些必须使用原生代码才干实现的功能,比方复杂的UI的效果,调用通讯相关的 ...
- Chrome插件:提醒你正在摸鱼,摸鱼的时候知道自己在摸鱼,减少摸鱼的时间和频率。
stop-mess-around 项目介绍 减少摸鱼的时间和频率的Chrome插件:在上班/学习期间很容易下意识的打开摸鱼网站,插件帮助我们减少摸鱼的时间和频率,提高我们上班和学习的效率,节省时间用于 ...
- 如何避免让线程摸鱼,请用异步技术 async await 拿捏他~
发现问题 你点了外卖后,会一直不做其它事情,一直等外卖的到来么? 当然不会拉! 我们来看看代码世界的: public void Query(){ // 当前线程 向 数据库服务器 发起查询命令 // ...
- 架构师之路-在Dubbo中开发REST风格的远程调用
架构师之路:从无到有搭建中小型互联网公司后台服务架构与运维架构 http://www.roncoo.com/course/view/ae1dbb70496349d3a8899b6c68f7d10b 概 ...
- 在ASP.NET MVC应用中开发插件框架(中英对照)
[原文] Developing a plugin framework in ASP.NET MVC with medium trust [译文] 在ASP.NET MVC应用中开发一个插件框架 I’v ...
- 【Rest】在Dubbo中开发REST风格的远程调用(RESTful Remoting)
目录 概述 REST的优点 应用场景 快速入门 标准Java REST API:JAX-RS简介 REST服务提供端详解 HTTP POST/GET的实现 Annotation放在接口类还是实现类 J ...
随机推荐
- Codeforces Round #529 (Div. 3) 练习赛
Examples input 6 baabbb output bab input 10 ooopppssss output oops 思路: 模拟等差数列即可 #include<bits/std ...
- 面试通过,拿到offer了,不去了会怎么样?
接受了offer但不去,其实没啥事,但这属于诚信问题. 这里有个概念,给了offer但不接受,这没事. 给了offer,也接受了,但在入职前一周(或在其它约定的时间范围内)说不去,同时姿态放低些打招呼 ...
- vue学习笔记 四、定义组件(组件基本结构)
系列导航 vue学习笔记 一.环境搭建 vue学习笔记 二.环境搭建+项目创建 vue学习笔记 三.文件和目录结构 vue学习笔记 四.定义组件(组件基本结构) vue学习笔记 五.创建子组件实例 v ...
- Nacos注册中心搭建
1.Nacos服务端搭建(需要有java环境),下载地址:https://github.com/alibaba/Nacos/releases 下载对应操作系统的包解压. 1.1.解压:tar -zxv ...
- 【驱动】I2C驱动分析(一)-I2C驱协议简介
什么是 I²C I²C 叫集成电路总线 它是一种串行通信接口,具有双向两线同步串行总线,通常由两根线组成--SDA(串行数据线)和SCL(串行时钟线)和上拉电阻. 它们用于需要许多不同部件(例如传感器 ...
- 存储密码-ssh添加秘钥
- CSS3 ------- object-fit属性
做项目经常会遇到图片列表展示,图片一般是用户从后台上传的,上传的图片尺寸千差万别.如果前端不控制图片大小,整个排版就会很乱,如果给定长宽,图片又会变形,用背景图片来处理有特别麻烦.这个问题一直苦恼了我 ...
- P3842-DP【黄】
想搜索到最后一层,就必得先完成前面层的搜索任务,这构成了对状态转移的启示,即当前层的DP值应该是此前层转移过来后得到的最佳值. 但这道题看数据范围应该不能用二维数组,抱着侥幸的心理我使用了动态二维数组 ...
- CSS 3D - rotate旋转90度看不到的原理 和 解决方法
原理: 旋转元素的坐标有三个 :X(向右), Y(向左) , Z(向电脑屏幕的你) 当没有位移旋转元素时,元素 Z 坐标也会同着一起旋转 ,当一个物品旋转到90度时,我们只能看到它的厚度,而d ...
- Laravel - Eloquent 模型查询
Laravel 的 Eloquent ORM 提供了漂亮.简洁的 ActiveRecord 实现来和数据库进行交互.每个数据库表都有一个对应的「模型」可用来跟数据表进行交互.你可以通过模型查找数据表内 ...