作者:小傅哥
部落格: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 的閱讀,以及你想看的書籍。