Author: Xiao Fu Ge
Blog: https://bugstack.cn
Precipitate, share, grow, so that you and others can gain something! 😄
I. Introduction
No tricks, don't write something exciting, you are always not good-looking!
Before, I didn't understand. The technology written is the technical content, and the scene written is the scene analysis. But from the readers' reading, I found that everyone prefers the combination of technology and scenes, especially the use of technology to combine those shameful scenes, even though they don't say anything.
This chapter mainly wants to introduce to you how to use toolbars and Tab pages in IDEA plug-in development to fill in the bottom form in IDEA, just like the console in IDEA. But writing like this seems to be boring enough for someone to watch, because everyone only looks at the technical point, it is difficult to find any application scenarios in it, even if you look at it, you don't know what this technology can do.
, the hour excites it. Don’t you like
losing money and trading stocks? Then
stock quotation and
K-line display into the IDEA plug-in development. This allows partners who learn plug-ins to take a look at the stock when they are tired of writing code, and maybe remind you to throw it out when it is critical!
2. Purpose of demand
To be safe, you need to develop a stock plug-in in a relatively hidden corner of IDEA, so that students who are trading in stocks can code CRUD intensely, and don't forget to buy and sell the stocks they care about.
So in order to solve this problem, we need several technical points, including: stock data interface, query object packaging, IDEA bottom form and toolbar development, timing task scanning, Swing UI, stock code configuration and saving, form button event monitoring Wait.
Next, we will combine these technical points to solve actual scene problems and see how to develop a stock plug-in in IDEA.
Three, case development
1. Engineering structure
guide-idea-plugin-tab
├── .gradle
└── src
├── main
│ └── java
│ └── cn.bugstack.guide.idea.plugin
│ ├── domain
│ │ ├── model
│ │ │ ├── aggregates
│ │ │ │ └── StockResult.java
│ │ │ └── vo
│ │ │ ├── Data.java
│ │ │ ├── GoPicture.java
│ │ │ └── Stock.java
│ │ └── service
│ │ ├── impl
│ │ │ └── StockImpl.java
│ │ └── IStock
│ ├── factory
│ │ └── TabFactory.java
│ ├── infrastructure
│ │ ├── DataSetting.java
│ │ └── DataState.java
│ ├── module
│ │ ├── RefreshBar.java
│ │ ├── SettingBar.java
│ │ └── ViewBars.java
│ └── ui
│ │ ├── ConsoleUI.java
│ │ ├── ConsoleUI.form
│ │ ├── GidConfig.java
│ │ └── GidConfig.form
│ └── Config
├── resources
│ └── META-INF
│ └── plugin.xml
├── build.gradle
└── gradle.properties
source code acquisition : #public number: bugstack wormhole stack reply:
idea
can download all IDEA plug-in development source code
In this IDEA plug-in project, it is mainly divided into 5 areas:
- Domain: The domain layer, which provides data services for querying stock interfaces. If you are doing some other tool-type functions, you can also put the content of the business class in the domain for implementation.
- factory: The factory layer, here is mainly an entry object generated by a tool form to create the form content that we add ourselves.
- Infrastructure: The basic layer provides data storage objects. This data object is an operation that can be placed on the disk. The created class can be configured in plugin.xml. so that after we configure the stock code, shut down and restart IDEA, the configuration can also be read
- module: Module, which provides some tool page operations used in UI forms. For example, the ViewBars here will be instantiated in TabFactory to display the form you added.
- ui: This part uses the form generated by the automatic drag and drop in IDEA, which eliminates the complexity of handwriting. You can drag and drop some simple pages directly. This is also a low code!
Next to , we will look at the implementation process of each core function point separately. During this process, you can download the code in advance, and it will be easier to understand by comparing it with learning.
- Implement ToolWindowFactory to develop a bottom form to carry the required content
- On the left is the side toolbar, configure self-selected stocks and refresh stock indexes
- On the right are 2 tab pages, which are used to display stock data and K-line charts respectively. The data here needs to be provided through the stock interface
2. Tab page form
First of all, here we first use the IDEA plug-in development, Swing UI function, drag and drop 2 simple forms. With such a basic structure, you should be able to in your mind.
2.1 Watchlist configuration form
public class GidConfig implements Configurable {
private JPanel mainPanel;
private JPanel settingPanel;
private JLabel gidLabel;
private JTextField gidTextField;
private ConsoleUI consoleUI;
public GidConfig(ConsoleUI consoleUI){
this.consoleUI = consoleUI;
}
public JTextField getGidTextField() {
return gidTextField;
}
@Override
public void apply() throws ConfigurationException {
List<String> gidList = DataSetting.getInstance().getGids();
gidList.clear();
String[] gids = gidTextField.getText().trim().split(",");
for (String gid : gids) {
gidList.add(gid.trim());
}
// 刷新数据
consoleUI.addRows(gidList);
}
}
- In the java class corresponding to GidConfig, you can get some properties that appear in the form. When the user clicks the confirmation button in this form, we can get the stock code configured by the user in apply, and read and set the stock data on it.
2.2 Stock display form
public class ConsoleUI {
private JTabbedPane tabbedPane1;
private JPanel one;
private JPanel two;
private JLabel picMin;
private JTable table;
private JLabel picDay;
// 查询数据服务
private IStock stock = new StockImpl();
private DefaultTableModel defaultTableModel = new DefaultTableModel(new Object[][]{}, new String[]{"股票", "代码", "最新", "涨跌", "涨幅"});
public ConsoleUI() {
// 初始数据
table.setModel(defaultTableModel);
addRows(DataSetting.getInstance().getGids());
// 添加事件
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = table.getSelectedRow();
Object value = table.getValueAt(row, 1);
GoPicture goPicture = stock.queryGidGoPicture(value.toString());
try {
// 分钟K线
picMin.setSize(545, 300);
picMin.setIcon(new ImageIcon(new URL(goPicture.getMinurl())));
// 当日K线
picDay.setSize(545, 300);
picDay.setIcon(new ImageIcon(new URL(goPicture.getDayurl())));
} catch (MalformedURLException m) {
m.printStackTrace();
}
}
});
}
public JTabbedPane getPanel() {
return tabbedPane1;
}
public void addRows(List<String> gids) {
// 查询
List<Data> dataList = stock.queryPresetStockData(gids);
// 清空
int rowCount = defaultTableModel.getRowCount();
for (int i = 0; i < rowCount; i++) {
defaultTableModel.removeRow(0);
}
// 添加
for (Data data : dataList) {
defaultTableModel.addRow(new String[]{data.getName(), data.getGid(), data.getNowPri(), data.getIncrease(), data.getIncrePer()});
table.setModel(defaultTableModel);
}
}
}
- The ConsoleUI class corresponding to the form that displays stocks is mainly responsible for data rendering, updating and event operations on each piece of data. When the user clicks on a piece of data, you can go to the
K-line page to see the corresponding stock index.
3. Stock frame settings
After the UI form is developed, we also need to use an inherited implementation class of SimpleToolWindowPanel to carry the toolbar and page settings.
3.1 Settings-Toolbar
cn.bugstack.guide.idea.plugin.module.SettingBar
public class SettingBar extends DumbAwareAction {
private ViewBars panel;
public SettingBar(ViewBars panel) {
super("配置股票", "Click to setting", IconLoader.getIcon("/icons/config.svg"));
this.panel = panel;
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
ShowSettingsUtil.getInstance().editConfigurable(panel.getProject(), new GidConfig(panel.getConsoleUI()));
}
}
- The setting toolbar is located at the leftmost position in the custom plug-in panel and is used to set the stock code of your choice.
- By the method
actionPerformed
useShowSettingsUtil
tools start UI form.
3.2 Refresh-Toolbar
cn.bugstack.guide.idea.plugin.module.RefreshBar
public class RefreshBar extends DumbAwareAction {
private ViewBars panel;
public RefreshBar(ViewBars panel) {
super("刷新指数", "Click to refresh", IconLoader.getIcon("/icons/refresh.svg"));
this.panel = panel;
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
panel.getConsoleUI().addRows(DataSetting.getInstance().getGids());
}
}
- The refresh toolbar is mainly used to manually trigger the refresh of the latest stock results. The main reason for using manual refresh is that this interface has a limit on the number of queries. If it is a timed task that runs all the time, the 100 query limit will be used up after a while. But we are here also to reflect the use of technology in the column, adding multiple setting buttons, it is easier to know how to add
3.3 Form fill panel
cn.bugstack.guide.idea.plugin.module.ViewBars
public class ViewBars extends SimpleToolWindowPanel {
private Project project;
private ConsoleUI consoleUI;
public ViewBars(Project project) {
super(false, true);
this.project = project;
consoleUI = new ConsoleUI();
// 设置窗体侧边栏按钮
DefaultActionGroup group = new DefaultActionGroup();
group.add(new SettingBar(this));
group.add(new RefreshBar(this));
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("bar", group, false);
toolbar.setTargetComponent(this);
setToolbar(toolbar.getComponent());
// 添加
JBSplitter splitter = new JBSplitter(false);
splitter.setSplitterProportionKey("main.splitter.key");
splitter.setFirstComponent(consoleUI.getPanel());
splitter.setProportion(0.3f);
setContent(splitter);
}
public Project getProject() {
return project;
}
public ConsoleUI getConsoleUI() {
return consoleUI;
}
}
- The filling panel is mainly in our custom plug-in, adding a toolbar on the left side, and adding a stock display panel in the rest of the position.
DefaultActionGroup
can add settings and refresh buttons toActionToolbar
, and finally fill them in 0619c4425e56d2, so that the setting is complete.JBSplitter
is a dividing line, and the right side is filled with our stock index display panelsplitter.setFirstComponent(consoleUI.getPanel())
4. Fill the main panel to the IDEA toolbar
4.1 Form Factory
cn.bugstack.guide.idea.plugin.factory.TabFactory
public class TabFactory implements ToolWindowFactory {
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
// 窗体
ViewBars viewPanel = new ViewBars(project);
// 获取内容工厂的实例
ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
// 获取 ToolWindow 显示的内容
Content content = contentFactory.createContent(viewPanel, "股票", false);
// 设置 ToolWindow 显示的内容
toolWindow.getContentManager().addContent(content, 0);
// 定时任务,自动刷新股票
/* 因每日查询次数限制,这里就不开定时任务了,用户可以自行申请 https://dashboard.juhe.cn/home
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
viewPanel.getConsoleUI().addRows(DataSetting.getInstance().getGids());
}
}, 3000, 2000);*/
}
}
- There are two main parts in TabFactory, one is to fill ViewBars into the entire toolWindow, and the other is the timing task of refreshing stock data that we have commented out so far.
- Here, due to the limitation of the number of times of stock interface query, the timed task is commented out, otherwise the available times will be gone after a while.
4.2 Configuration form
plugin.xml
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<toolWindow id="XUtil"
canCloseContents="true"
anchor="bottom"
factoryClass="cn.bugstack.guide.idea.plugin.factory.TabFactory"
icon="/icons/stock.png"
/>
</extensions>
</idea-plugin>
- Here we configure the form to the bottom of the entire IDEA interface
anchor="bottom"
This location is convenient and safest
5. Data persistence configuration
- When we use IDEA to configure some basic parameters, such as: Maven, Gradle, Git, signature information, etc., these configuration information will be saved when IDEA is shut down and restarted daily.
- Then some optional stock code configurations that we developed for this plug-in need to be saved, otherwise they cannot be reset every time IDEA starts. So here we need to use the
plugin.xml
configuration inapplicationService
to implement the data setting storage classPersistentStateComponent
5.1 Object data
cn.bugstack.guide.idea.plugin.infrastructure.DataState
public class DataState {
private List<String> gids = new ArrayList<>();
public List<String> getGids() {
return gids;
}
public void setGids(List<String> gids) {
this.gids = gids;
}
}
- This is a data object class, you can set the attributes you need to store here, just like gids, it is used to store the stock code collection configured by the user.
5.2 Persistent data
cn.bugstack.guide.idea.plugin.infrastructure.DataSetting
@State(name = "DataSetting",storages = @Storage("plugin.xml"))
public class DataSetting implements PersistentStateComponent<DataState> {
private DataState state = new DataState();
public static DataSetting getInstance() {
return ServiceManager.getService(DataSetting.class);
}
@Nullable
@Override
public DataState getState() {
return state;
}
@Override
public void loadState(@NotNull DataState state) {
this.state = state;
}
public List<String> getGids(){
return state.getGids();
}
}
- The DataSetting class needs to use the annotation @State provided by IDEA plug-in development to configure persistent objects
- In addition, we need to provide a getInstance method to obtain the data object instance, so that when we actually use it, we can get the object we configured and set and read the data.
5.3 plugin.xml configuration
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<applicationService serviceImplementation="cn.bugstack.guide.idea.plugin.infrastructure.DataSetting"/>
</extensions>
- After creating the data setting class, you need to use the applicationService tag to configure your class in extensions in plugin.xml.
6. Stock interface
6.1 Technical research
- No matter what function development is, it is necessary to
bits and pieces before starting code development. This process is also called technical research to design and review. Just as we need to query stock information, we need to find an interface that can provide data query, and see how this interface applies for use, and what fields the returned object has, and whether it meets our expectations.
Here Xiao Fu found an interface to aggregate data, but he can only
100 times/day for free. If you have a better one, you can replace it.
- Interface: http://web.juhe.cn:8080/finance/stock/hs?gid=sz000651&key=Apply by yourself -The key here needs to be applied for by yourself
data:
6.2 Service Packaging
With the stock query interface, you can then perform a query and object conversion on the data.
cn.bugstack.guide.idea.plugin.domain.service.impl.StockImpl
public class StockImpl implements IStock {
// 自行申请,股票API,替换key即可【一天可免费调用100次】:https://dashboard.juhe.cn/home/
private final String key = "4bc57728***********f0595";
@Override
public List<Data> queryPresetStockData(List<String> gids) {
List<Data> dataList = new ArrayList<>();
for (String gid : gids) {
StockResult stockResult = JSON.parseObject(HttpUtil.get("http://web.juhe.cn:8080/finance/stock/hs?gid=" + gid + "&key=" + key), StockResult.class);
Stock[] stocks = stockResult.getResult();
for (Stock stock : stocks) {
dataList.add(stock.getData());
}
}
return dataList;
}
}
- Here we define data vo objects in the domain layer, and provide encapsulation of stock query services. In this way, the caller can directly use this data. If you are a stock query interface provided by another manufacturer, you can also encapsulate and replace it to create an interface adaptation layer.
Four, test verification
- If you download the project without Plugin and a green arrow, you can configure
:runIde
yourself according to the figure so that it can run.
running effect -the exciting time has arrived, no longer have to worry about writing code that affects watching stocks
1. Allocation of stocks
- First of all, you need to configure the stock codes you are concerned about here. I have configured 3 ones that I am optimistic about.
2. Value-Choice Index
- After the configuration is complete, you can see your own self-selected stock index. After selecting one, click on the K line.
- When you need to see the latest data, you can click the refresh button on the left.
3. K Line
- Now this is the corresponding K-line, is it pretty fragrant? Currently, the latest K-line and daily K-line have been added, and you can also expand the graphs in other dimensions.
Five, summary
- In this chapter, we used to add a slightly more complicated page structure to the IDEA form, with sidebars and Tab pages, and interact and communicate in the body of these pages. In addition, data storage settings are still used, which will be used in many IDEA plug-ins development.
- Technical practices like this can not only be used to display stock data, you can also combine what you need to expand what you need in the actual scenario, such as developing a data centralized query plug-in that can query databases, ES, Redis, etc., also It can be a collection page of all tools, these contents will have more technical value.
- When you start to actively add the functions you want to some of the source codes, frameworks, components, projects, etc. that you have learned, you have really started to learn, otherwise a content will be forgotten after reading it for a long time.
Sixth, series recommendation
- IDEA plug-in?
- based on IDEA plug-in development and bytecode instrumentation technology to realize automatic analysis of R&D delivery quality
- investigates bytecode instrumentation technology for system monitoring design and implementation
- "Hand Lu Spring" PDF, 260 pages of 65,000 words, finished & published!
- your own technology stack blind spot
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。