作者:小傅哥 博客:https://bugstack.cn
❝沉淀、分享、成长,让自己和他人都能有所收获!😜 ❞
没招了,不写点刺激的,你总是不好好看!
以前,我不懂。写的技术就是技术内容,写的场景就是场景分析,但从读者的阅读我发现,大家更喜欢的是技术与场景结合,尤其是用技术结合那些羞羞答答的场景,虽然嘴上都不说。
本章节主要是想给大家介绍关于在 IDEA 插件开发中如何使用工具栏和Tab页,来填充在 IDEA 中底部的窗体,就像 IDEA 中的控制台一样。但就这么写好像是够呛能有人看,因为大家只从技术点来看,很难发现这里面有什么应用场景,即使看了好像也不知道这技术能干啥。
那咋办,整点刺激
的吧。大家不是喜欢赔钱炒股
吗,那就把股票行情
和K线展示
结合到IDEA插件开发中。可以让学习插件的伙伴,都能在写代码疲惫的时候还能看一眼股票,也许在关键的时候还能提醒你赶紧抛出去!
安全起见,需要在 IDEA 中以一个比较隐秘的角落,开发股票插件,让炒股的同学可以在紧张编码CRUD之余,不要忘记自己关注的股票购买和抛售。
那么为了解决这个问题,我们需要几个技术点,包括:股票数据接口、查询对象封装、IDEA 底部窗体和工具栏开发、定时任务扫描、Swing UI、股票代码配置和保存、窗体按钮事件监听等。
接下来我们就结合这些技术点,来解决实际的场景问题,看看如何在 IDEA 中开发一个股票插件。
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
源码获取:#公众号:bugstack虫洞栈
回复:idea
即可下载全部 IDEA 插件开发源码
在此 IDEA 插件工程中,主要分为5块区域:
接下来,我们就分别看下每个核心功能点的实现过程,这个过程中你可以提前把代码下载下来,对照着学习会更加容易理解。
首先这里我们先使用 IDEA 插件开发中,Swing UI 功能,拖拽出2个简单的窗体。有了这样的一个基本结构大家的脑子里应该就可以有画面
了。
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);
}
}
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);
}
}
}
K线
页中看到对应的股票指数了。在开发完 UI 窗体后,我们还需要使用一个 SimpleToolWindowPanel 的继承实现类,承载工具栏和页面的设置。
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()));
}
}
actionPerformed
中使用 ShowSettingsUtil
工具类启动 UI 窗体。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());
}
}
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;
}
}
DefaultActionGroup
中可以以此添加设置和刷新按钮,并最终填充到 ActionToolbar
里去,这样就设置完成了。JBSplitter
是一个分割线,右侧填充上我们的股票指数展示面板 splitter.setFirstComponent(consoleUI.getPanel())
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);*/
}
}
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>
anchor="bottom"
这个位置既方便又最安全plugin.xml
中 applicationService
配置上实现了 PersistentStateComponent
的数据设置存放类。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;
}
}
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();
}
}
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<applicationService serviceImplementation="cn.bugstack.guide.idea.plugin.infrastructure.DataSetting"/>
</extensions>
零碎的事情
处理完,才能进行代码开发,这个过程也叫做技术调研到设计和评审。就像现在我们需要进行股票信息的查询,那么就需要找到一个可以提供数据查询的接口,看看这个接口如何申请使用,以及返回的对象都有哪些字段,是否符合我们的预期。100次/天
调用,如果你有更好的可以更换下。
有了股票的查询接口,接下来就可以对数据做一个查询和对象转换了。
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;
}
}
:runIde
这样就可以运行了。运行效果 - 激动人心的时刻到了,再也不用担心写代码影响看股票了哦
- END -
下方扫码关注 bugstack虫洞栈,与小傅哥一起学习成长、共同进步,做一个码场最贵Coder!
你好,我是小傅哥。一线互联网java
工程师、架构师,开发过交易&营销、写过运营&活动、设计过中间件也倒腾过中继器、IO板卡。不只是写Java语言,也搞过C#、PHP,是一个技术活跃的折腾者。
2020年写了一本PDF《重学Java设计模式》,全网下载量50万+,帮助很多同学成长,现已出书。同年 github 的两个项目,CodeGuide
、itstack-demo-design
,持续霸榜 Trending,成为全球热门项目。
2021年上架一本小册《SpringBoot 中间件设计和开发》,16个互联网中间件场景、30个工程,是全网唯一一次手把手教你造轮子、写中间件,因为这样的技术离P7最近、离架构师最近、离高薪资最近!