Idea包含UI内容的插件开发

Idea包含UI内容的插件开发

    • 前言
    • 插件效果
    • 项目结构
    • 配置功能的实现
    • 找一个股票接口
    • 完成最终的页面
    • 配置Plugin.xml
    • 源码地址

前言

在这一篇文章中将会做一个包含UI内容的能看股票的插件。

插件效果

首先是在设置中配置股票的编号,如sh000001,sh600519。

接着在侧边栏中有一个叫做Stock Prices的Tab框,点击之后就可以看到设置的这几个股票消息

当点击刷新按钮之后,就会重新刷新数据,上边的最新更新日期也会同步变化。

项目结构

项目结构如下:

  • StockSettingsComponent保存了配置页面的样式。
  • StockConfigurable是配置页面的配置类,加载了StockSettingsComponent这个组件。
  • handler里的是一个OkHttp的单例实现类,以及调用股票接口的处理器,response是接口的返回。
  • StockSettingsState中保存的是配置的持久化内容,这个文件会保存在本地。
  • StockToolWindow是在侧边栏展示的内容,也就是最终看到的效果。

所有的图都是用javax.swing画的。

配置功能的实现

配置功能要做的事情是把股票编号的配置交给用户自己,首先定义了一个配置的持久化类。

import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;/*** 股票配置的持久化类*/
@State(name = "top.codeease.stockwatch.storage.StockSettingsState",storages = @Storage("StockPluginSettings.xml")
)
public class StockSettingsState implements PersistentStateComponent<StockSettingsState> {/*** 默认股票符号,取上证指数*/public String stockSymbol = "sh000001";public static StockSettingsState getInstance() {return ServiceManager.getService(StockSettingsState.class);}@Nullable@Overridepublic StockSettingsState getState() {return this;}@Overridepublic void loadState(@NotNull StockSettingsState state) {this.stockSymbol = state.stockSymbol;}
}

这个持久化文件最终会保存在本地。接着定义一个组件类叫做StockSettingsComponent,就用一个 JPanel 包裹一个 JTextField。

import javax.swing.*;/*** 设置组件类*/
public class StockSettingsComponent {private JPanel panel;private JTextField stockSymbolTextField;public StockSettingsComponent() {panel = new JPanel();stockSymbolTextField = new JTextField(40);panel.add(new JLabel("请输入股票编号(用英文逗号分割):"));panel.add(stockSymbolTextField);}public JPanel getPanel() {return panel;}public String getStockSymbol() {return stockSymbolTextField.getText();}public void setStockSymbol(String stockSymbol) {stockSymbolTextField.setText(stockSymbol);}
}

最后就是一个配置类将上面两个类拼装起来了。

import com.intellij.openapi.options.Configurable;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.Nullable;
import top.codeease.stockwatch.component.StockSettingsComponent;
import top.codeease.stockwatch.storage.StockSettingsState;import javax.swing.*;/*** 股票配置的最终实现*/
public class StockConfigurable implements Configurable {private StockSettingsComponent settingsComponent;@Overridepublic @Nls(capitalization = Nls.Capitalization.Title) String getDisplayName() {return "Stock Plugin";}@Overridepublic @Nullable JComponent createComponent() {settingsComponent = new StockSettingsComponent();return settingsComponent.getPanel();}@Overridepublic boolean isModified() {StockSettingsState settings = StockSettingsState.getInstance();return !settingsComponent.getStockSymbol().equals(settings.stockSymbol);}@Overridepublic void apply() {StockSettingsState settings = StockSettingsState.getInstance();settings.stockSymbol = settingsComponent.getStockSymbol();}@Overridepublic void reset() {StockSettingsState settings = StockSettingsState.getInstance();settingsComponent.setStockSymbol(settings.stockSymbol);}
}

最终要将配置类注册到plugin.xml中。

找一个股票接口

这里以腾讯接口为例:https://qt.gtimg.cn/q=sh000001

点击后拿到的结果如下,不同的数据之间用~分割

v_sh000001="1~上证指数~000001~2974.01~2971.30~2963.85~268992597~0~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~~20240715155911~2.71~0.09~2977.31~2959.13~2974.01/268992597/268733339474~268992597~26873334~0.57~13.32~~2977.31~2959.13~0.61~429130.60~566227.31~0.00~-1~-1~0.88~0~2970.27~~~~~~26873333.9474~0.0000~0~ ~ZS~-0.03~1.76~~~~3322.13~2635.09~-0.69~-1.39~-1.10~4546667906679~~-10.22~-2.77~4546667906679~~~-8.14~-0.05~~CNY~0~~0.00~0";

下面是其中一些关键的参数:

0: 未知
1: 名字
2: 代码
3: 当前价格
4: 昨收
5: 今开
6: 成交量(手)
7: 外盘
8: 内盘
29: 最近逐笔成交
30: 时间
31: 涨跌
32: 涨跌%
33: 最高
34: 最低
35: 价格/成交量(手)/成交额
36: 成交量(手)
37: 成交额(万)
38: 换手率
39: 市盈率
41: 最高
42: 最低
43: 振幅
44: 流通市值
45: 总市值
46: 市净率
47: 涨停价
48: 跌停价

自定义一个接口的返回结构,取想展示的内容:

/*** 股票结果返回*/
@Data
public class GetStockPriceResponse {/*** 股票名称*/private String stockName;/*** 股票编号*/private String stockNo;/*** 当前价格*/private String lastTrade;/*** 涨跌幅*/private String change;/*** 昨收*/private String prevClose;/*** 今开*/private String open;
}

然后编写OkHTTP的单例实现类:

import okhttp3.OkHttpClient;
import java.util.concurrent.TimeUnit;/*** OkHttp模块的单例实现*/
public class OkHttpClientSingleton {private static OkHttpClient instance;private OkHttpClientSingleton() {// 私有构造函数,防止外部实例化}public static OkHttpClient getInstance() {if (instance == null) {synchronized (OkHttpClientSingleton.class) {if (instance == null) {OkHttpClient.Builder builder = new OkHttpClient.Builder();// 设置连接超时builder.connectTimeout(60, TimeUnit.SECONDS);// 设置读取超时builder.readTimeout(60, TimeUnit.SECONDS);// 设置写入超时builder.writeTimeout(60, TimeUnit.SECONDS);// 构建 OkHttpClient 实例instance = builder.build();}}}return instance;}
}

最后编写获取数据以及处理数据的处理器:

/*** 股票价格*/
public class StockPriceHandler {/*** 腾讯的股票API接口*/private String STOCK_API_TX = "https://qt.gtimg.cn/q=";public List<GetStockPriceResponse> fetchStockPrice(String stockSymbol) {OkHttpClient client = OkHttpClientSingleton.getInstance();String url = STOCK_API_TX + stockSymbol;Request request = new Request.Builder().url(url).build();String responseData = "";List<GetStockPriceResponse> stockPriceResponseList = new ArrayList<>();try {Response response = client.newCall(request).execute();responseData = response.body().string();stockPriceResponseList = dealData(responseData);System.out.println(responseData);} catch (IOException e) {e.printStackTrace();}return stockPriceResponseList;}/*** 接口数据处理,获取到腾讯的接口后会拿到这样一串字符串,如:* v_sh000001="1~上证指数~000001~2971.30~2970.39~2965.61~303713014~0~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~~20240712153511~0.91~0.03~2977.14~2963.30~2971.30/303713014/302581575979~303713014~30258158~0.65~13.27~~2977.14~2963.30~0.47~428104.13~563894.26~0.00~-1~-1~1.02~0~2970.97~~~~~~30258157.5979~0.0000~0~ ~ZS~-0.12~0.72~~~~3322.13~2635.09~0.13~-2.02~-2.82~4534435145087~~-16.75~-3.64~4534435145087~~~-8.19~0.01~~CNY~0~~0.00~0";* 以 ~ 进行分割,一些重要的数据*  0: 未知*  1: 名字*  2: 代码*  3: 当前价格*  4: 昨收*  5: 今开*  6: 成交量(手)*  7: 外盘*  8: 内盘* 29: 最近逐笔成交* 30: 时间* 31: 涨跌* 32: 涨跌%* 33: 最高* 34: 最低* 35: 价格/成交量(手)/成交额* 36: 成交量(手)* 37: 成交额(万)* 38: 换手率* 39: 市盈率* 41: 最高* 42: 最低* 43: 振幅* 44: 流通市值* 45: 总市值* 46: 市净率* 47: 涨停价* 48: 跌停价* @param responseData* @return*/private List<GetStockPriceResponse> dealData(String responseData) {List<GetStockPriceResponse> getStockPriceResponseList = new ArrayList<>();// 如果有多个股票号,先通过;进行拆分responseData = responseData.substring(0, responseData.length() - 1);String[] stockArray = responseData.split(";");for (String stockInfo : stockArray) {GetStockPriceResponse response = new GetStockPriceResponse();String[] split = stockInfo.split("~");response.setStockName(split[1]);response.setStockNo(split[2]);response.setLastTrade(split[3]);response.setChange(split[32]);response.setPrevClose(split[4]);response.setOpen(split[5]);getStockPriceResponseList.add(response);}return getStockPriceResponseList;}
}

完成最终的页面

股票页面由一个按钮JButton,一个展示时间的JLabel,以及表格JBTable组成,源码实现如下。

import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.table.JBTable;
import org.jetbrains.annotations.NotNull;
import top.codeease.stockwatch.handler.StockPriceHandler;
import top.codeease.stockwatch.response.GetStockPriceResponse;
import top.codeease.stockwatch.storage.StockSettingsState;
import top.codeease.stockwatch.util.DateUtil;import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.List;/*** 股票展示页面*/
public class StockToolWindow implements ToolWindowFactory {private JPanel mainPanel;private JButton refreshButton;private JBTable stockTable;private DefaultTableModel tableModel;private JLabel lastUpdatedLabel;private final String[] columnNames = {"股票名称", "股票编号","当前价格","涨跌%","昨收","今开"};@Overridepublic void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {mainPanel = new JPanel(new BorderLayout());// 创建按钮JPanel buttonPanel = new JPanel();refreshButton = new JButton("Refresh");lastUpdatedLabel = new JLabel("Last Updated: " + DateUtil.getNowTime());buttonPanel.add(refreshButton);buttonPanel.add(lastUpdatedLabel);// 创建表格Object[][] data = getDataArray();tableModel = new DefaultTableModel(data, columnNames);stockTable = new JBTable(tableModel);// 添加组件到主面板mainPanel.add(buttonPanel, BorderLayout.NORTH);mainPanel.add(new JScrollPane(stockTable), BorderLayout.CENTER);ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();Content content = contentFactory.createContent(mainPanel, "", false);toolWindow.getContentManager().addContent(content);// 添加按钮操作逻辑refreshButton.addActionListener(e -> refreshFetchingStockPrice());}/*** 刷新股票的价格数据*/private void refreshFetchingStockPrice() {Object[][] data = getDataArray();tableModel = new DefaultTableModel(data, columnNames);stockTable.setModel(tableModel);lastUpdatedLabel.setText("Last Updated: " + DateUtil.getNowTime());}/*** 获取表格的数据列* @return*/private Object[][] getDataArray() {String stockSymbol = StockSettingsState.getInstance().stockSymbol;StockPriceHandler handler = new StockPriceHandler();List<GetStockPriceResponse> getStockPriceResponseList = handler.fetchStockPrice(stockSymbol);Object[][] data = new Object[getStockPriceResponseList.size()][];for (int i = 0; i < getStockPriceResponseList.size(); i++) {GetStockPriceResponse stockPriceResponse = getStockPriceResponseList.get(i);Object[] rowData = {stockPriceResponse.getStockName(),stockPriceResponse.getStockNo(),stockPriceResponse.getLastTrade(),stockPriceResponse.getChange(),stockPriceResponse.getPrevClose(),stockPriceResponse.getOpen()};data[i] = rowData;}return data;}
}

配置Plugin.xml

最后配置一下Plugin.xml,在extensions中将需要注册的类注册进去。

<extensions defaultExtensionNs="com.intellij"><!-- Add your extensions here --><applicationService serviceImplementation="top.codeease.stockwatch.storage.StockSettingsState"/><projectConfigurable instance="top.codeease.stockwatch.config.StockConfigurable"/><toolWindow id="Stock Prices" anchor="right" factoryClass="top.codeease.stockwatch.window.StockToolWindow"/>
</extensions>

这样一个股票插件就实现了。

源码地址

参考代码:https://github.com/OliverLiy/StockWatch

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3281143.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

为何2024年这4款ai智能写作工具被赞为YYDS?

在数字化的大潮中&#xff0c;人工智能已经深入到我们生活的各个角落&#xff0c;当然也包括写作领域。随着ai智能写作工具的兴起&#xff0c;它们不仅显著提升了写作效率&#xff0c;还为创作打开了全新的可能性。今天&#xff0c;我们就来看看四款特别受欢迎的AI写作工具&…

干货分享 | 基于VB6.0 实现 CAN信号收发 Demo

本文主要讲的是&#xff0c;基于TSMaster 实现 TOSUN 系列 CAN/CANFD&#xff0c;LIN 设备的操作。主要给大家介绍在 TSMaster 软件里如何实现 CAN 信号收发 Demo工程。 本文关键词&#xff1a;CAN报文、VB6.0、libTSCAN 一、关于Demo工程 简要描述&#xff1a; VB6.0编程语…

Python药物副作用生物图分析算法和矩阵降维算法

&#x1f3af;要点 &#x1f3af;人体疾病模块网络结构位置与病理生物学关系 | &#x1f3af;药物与药物靶点相互作用 | &#x1f3af;细胞和蛋白质之间的作用分层 | &#x1f3af;疾病和症状之间的联系 | &#x1f3af;药物与副作用之间的联系 | &#x1f3af;生物学分析 &a…

年过30年程序员,到底要不要考虑搞点副业

一、前言 作为一名年过三十的程序员&#xff0c;我深刻体会到了职场的残酷和不确定性。在这个技术日新月异的时代&#xff0c;我们不仅要在专业领域深耕细作&#xff0c;更要敏锐地捕捉互联网的风口&#xff0c;以确保自己不被时代淘汰。程序员的黄金年龄似乎被限定在35岁之前…

事务性邮件api接口服务怎么选?怎么集成?

事务性邮件API接口安全性如何保障&#xff1f;API接口调用方法&#xff1f; 在现代企业的运营中&#xff0c;事务性邮件是确保信息及时传达和用户体验的关键环节。AokSend将探讨如何选择合适的事务性邮件API接口服务&#xff0c;以及如何有效地集成这些服务。 事务性邮件api接…

MongoDB下载与基本使用(mac图文详解)

目录 一、下载安装 1.1 官网下载mongoDB 1.1.1 mongoDB 1.1.2 MongoDB GUI 1.2 下载流程 二、基本使用 2.1 创建数据库和集合 2.2 插入 2.3 查询 2.4 修改 2.5 删除 三、case 3.1 销售case 3.1.1 实操 3.1.2 全部指令汇总 背景&#xff1a; 个人练习用 一、下…

《计算机网络》(第8版)第九章 无线网络和移动网络 复习笔记

第九章 无线网络和移动网络 一、无线局域网 WLAN 1 无线局域网的组成 无线局域网提供移动接入的功能&#xff0c;可分为两大类&#xff1a;有固定基础设施的和无固定基础设 施的。 &#xff08;1&#xff09;IEEE 802.11 IEEE 802.11 是无线以太网的标准&#xff0c;是有固定…

MySQL安装教程(保姆级)

1. 首先要了解自己的计算机 打开设置——系统——系统信息 然后就可以知道自己计算机的类型了。 2. 下载MySQL 2.1. 来到MySQL官网 点击进入 我们下拉页面&#xff0c;可以找到DOWNLOADS 页面默认给咱们选择最新的版本&#xff0c;咱们不用&#xff0c;咱们尽量选一个稳定的版…

Linux的防火墙

一、防火墙概述 防火墙是一种计算机硬件和软件的结合&#xff0c;使internet和intranet之间建立一个安全网关&#xff08;Security Gateway&#xff09;&#xff0c;从而保护内网免受非法用户侵入的技术。 防火墙主要由服务访问规则、验证工具、包过滤和应用网关4个部分组成。…

绝密!OceanBase OBCP备考模拟题讲解(2)

「源de爸讲数据库」每天更新OceanBase OBCP题库及全网独家超详细题目解析&#xff0c;祝您早日持证上岸&#xff01; 现如今&#xff0c;一大批国产数据库随着国产化浪潮&#xff0c;已经逐步被越来越多的人认可。OceanBase便是其中一个优秀代表。 做这个日更专题&#xff0c;…

easy_Maze

结合题目,知道是一道迷宫题型 那么我们要做的就是 1.找到迷宫 2.确定方向(一般为wasd,但是可能会改) 3.确定起点 4.确定终点 // TAGS: dict_keys([spawn]) int __cdecl main(int argc, const char **argv, const char **envp) {__int64 v3; // raxint v5[49]; // [rsp0h]…

HCIA总结

一、情景再现&#xff1a;ISP网络为学校提供了DNS服务&#xff0c;所以&#xff0c;DNS服务器驻留在ISP网络内&#xff0c;而不再学校网络内。DHCP服务器运行在学校网络的路由器上 小明拿了一台电脑&#xff0c;通过网线&#xff0c;接入到校园网内部。其目的是为了访问谷歌网站…

【ROS 最简单教程 002/300】ROS 集成开发环境安装: Noetic

&#x1f497; 有遇到安装问题可以留言呀 ~ 当时踩了挺多坑&#xff0c;能帮忙解决的我会尽力 &#xff01; 1. 安装操作系统环境 Linux ❄️ VM / VirtualBox Ubuntu20.04 如果已有 linux 环境 (如双系统等)&#xff0c;可跳过步骤 1 ~ &#x1f449; 保姆级图文安装教程指路…

微服务事务管理(分布式事务问题 理论基础 初识Seata XA模式 AT模式 )

目录 一、分布式事务问题 1. 本地事务 2. 分布式事务 3. 演示分布式事务问题 二、理论基础 1. CAP定理 1.1 ⼀致性 1.2 可⽤性 1.3 分区容错 1.4 ⽭盾 2. BASE理论 3. 解决分布式事务的思路 三、初识Seata 1. Seata的架构 2. 部署TC服务 3. 微服务集成Se…

P3501 [POI2010] ANT-Antisymmetry 反对称 题解(字符串哈希+二分)

原题 题意 若一个由 01 01 01组成的字符串将 0 0 0和 1 1 1取反&#xff0c;并倒过来后与原字符串相同&#xff0c;则称为反对称字符串。现在给你一个长度为 n ( n ≤ 1 0 5 ) n(n \le 10^5) n(n≤105) 01 01 01组成的字符串&#xff0c;求它有多少个反对称子串。&#xff08…

Prometheus-部署

Prometheus-部署 Server端安装配置部署Node Exporters监控系统指标监控MySQL数据库监控nginx安装grafana Server端安装配置 1、上传安装包&#xff0c;并解压 cd /opt/ tar xf prometheus-2.30.3.linux-amd64.tar.gz mv prometheus-2.30.3.linux-amd64 /usr/local/prometheus…

npm install报错原因记录:npm ERR! code ENOENT

报错原因&#xff1a;路径打开错了&#xff0c;你需要在package.json这个文件的文件夹目录打开终端执行命令才行。 比如我的前端项目中&#xff0c;package.json项目在back-system-font-ts文件下&#xff0c;我就需要右击该文件&#xff0c;从该目录打开终端才有用

【前端】(仅思路)如何在前端实现一个fc手柄,将手机作为游戏手柄设备。

文章目录 背景界面demo遇到的问题最终后端demo(甚至比前端逻辑更简单) 背景 突发奇想&#xff0c;想要在前端实现一个fc游戏手柄&#xff0c;然后控制电脑的nes模拟器玩玩魂斗罗。 思路很简单&#xff0c;前后端使用websocket通信&#xff0c;connected标识socket链接已建立&a…

【Vulnhub系列】Vulnhub_Dr4g0n_b4ll 靶场渗透(原创)

【Vulnhub系列靶场】Vulnhub_Dr4g0n_b4ll靶场渗透 原文转载已经过授权 原文链接&#xff1a;Lusen的小窝 - 学无止尽&#xff0c;不进则退 (lusensec.github.io) 一、环境搭建 选择打开.ovf 文件 配置名称和路径 打开后调整网络连接模式为【NAT】即可 二、信息收集 1、主机…