跳转至

Theme 插件开发专题

Theme 插件用于改变 IntelliJ 系列 IDE 的视觉外观。它可以替换图标、调整 UI 控件颜色和边框、提供编辑器配色方案、添加背景图。它不应该和普通功能插件混在一起;官方建议主题插件保持独立,降低发布、审核、兼容和用户预期成本。

本章面向两类开发者:

  • 想发布独立主题插件的设计/前端/插件开发者。
  • 普通插件作者,需要让自己的自定义 UI 暴露主题元数据,方便主题作者适配。

Theme 插件能改什么

能力 文件/API 说明
IDE UI 控件颜色 *.theme.jsonui Label、Button、Tree、List、Popup、Tabs 等控件
IDE 图标颜色 icons.ColorPalette 全局色值替换或 Actions/Objects 调色板替换
IDE 图标替换 icons 路径映射 用 SVG 替换平台默认图标
编辑器配色 editorScheme 指向 XML 代码、行号、VCS 状态、滚动条等编辑器颜色
背景图 background / emptyFrameBackground IDE 窗口和空 frame 背景
主题继承 parentTheme 基于已有主题继续覆盖
插件自定义 UI 主题键 themeMetadataProvider 普通插件暴露自己的 UI customization keys

Theme 插件不是 UI framework。它改变现有 UI 的视觉参数,不负责新增业务功能、Action、Tool Window 或 Service。

开发方式选择

方式 适合场景
DevKit Theme Project 只做主题、希望从 IDE Wizard 快速开始、不熟悉 Gradle
Gradle 插件项目 需要 CI、自动 patch plugin.xml、构建分发包、发布到 Marketplace
普通插件附带主题资源 不推荐;只有在插件主体就是主题体验的一部分时才考虑

新项目如果需要长期维护和发布,建议直接用 Gradle;一次性实验或设计验证可以从 DevKit Wizard 开始。

项目结构

典型主题插件结构:

theme-plugin/
  build.gradle.kts
  src/main/resources/
    META-INF/
      plugin.xml
    themes/
      example.theme.json
      Example.xml
    icons/
      factory.svg
    pluginIcon.svg
    pluginIcon_dark.svg

核心文件:

  • plugin.xml:声明 themeProvider
  • example.theme.json:主题描述文件。
  • Example.xml:可选编辑器配色方案。
  • SVG 图标:可选替换平台图标或提供 Marketplace 图标。

主题资源路径以 resources 根为起点。themeProviderpath 和 JSON 内部路径要保持一致。

plugin.xml 声明

主题插件通过 themeProvider 扩展点注册:

<idea-plugin>
  <id>com.example.theme</id>
  <name>Example Theme</name>
  <vendor email="dev@example.com">Example</vendor>

  <depends>com.intellij.modules.platform</depends>

  <extensions defaultExtensionNs="com.intellij">
    <themeProvider
        id="com.example.theme.light"
        path="/themes/example.theme.json"/>
  </extensions>
</idea-plugin>

注意:

  • themeProviderid 必须稳定,不要复用别的主题 ID。
  • 一个插件可以提供多个主题,例如 light/dark 变体,每个主题用一个 themeProvider
  • 主题插件通常只依赖 com.intellij.modules.platform
  • 如果只发布主题,不要额外注册业务扩展点。

DevKit Wizard 会自动生成 themeProvider,官方特别提醒不要修改或复用已有生成 ID。Gradle 项目也应把 ID 当成长期兼容标识。

最小主题描述文件

*.theme.json 是主题插件最重要的文件:

{
  "name": "Example Light",
  "author": "Example",
  "dark": false,
  "editorScheme": "/themes/Example.xml",
  "ui": {}
}

字段含义:

字段 说明
name Settings 主题下拉框里展示的名称
author 主题作者
dark true 基于 Darcula,false 基于 Light
editorScheme 可选,关联编辑器配色 XML
ui UI 控件键覆盖
colors 可选,定义命名颜色
icons 可选,覆盖图标颜色或替换图标
background 可选,IDE 主窗口背景
emptyFrameBackground 可选,空 frame 背景
parentTheme 可选,继承已有主题

dark 不是“把所有颜色自动变暗”的开关。它决定基底主题,后续覆盖仍然要自己保证对比度、可读性和控件状态完整。

命名颜色

颜色可以直接写十六进制 RGB/RGBA,也可以先定义命名颜色再复用:

{
  "name": "Example Light",
  "dark": false,
  "author": "Example",
  "colors": {
    "surface": "#F7F8FA",
    "accent": "#2F6FED",
    "danger": "#C93A3A"
  },
  "ui": {
    "Panel.background": "surface",
    "Button.default.startBackground": "accent",
    "ValidationTooltip.errorBackground": "danger"
  }
}

建议:

  • 高频颜色用 colors 命名,便于整体调色。
  • 命名体现用途,不要叫 blue1gray2
  • 少量特殊值可以直接写十六进制。
  • RGBA 用八位十六进制,避免不透明度含义散落在注释里。

UI 控件键

UI 控件颜色放在 ui 中,键通常是 element.property

{
  "ui": {
    "Panel.background": "#F7F8FA",
    "Label.foreground": "#1F2328",
    "TextField.background": "#FFFFFF",
    "Popup.Advertiser.foreground": "#6A737D",
    "ScrollBar.Mac.Transparent.thumbColor": "#00000033"
  }
}

常见 property:

property 用途
foreground 文本色
background 背景色
errorForeground 错误文本
borderColor 边框色
selectionForeground 选中文本色
selectionBackground 选中背景色
inactiveBackground 非活动状态背景
hoverForeground / hoverBackground hover 状态
pressedForeground / pressedBackground pressed 状态

不要只改默认态。至少检查 hover、pressed、selected、inactive、disabled、error/warning/success 等状态,否则主题在真实 IDE 中会出现“看起来正常,但一交互就不可读”的问题。

通配符覆盖

可以用 "*" 覆盖所有控件的同名 property:

{
  "ui": {
    "*": {
      "background": "#F7F8FA"
    },
    "Label.background": "#FFFFFF"
  }
}

更具体的键会覆盖通配符。通配符适合做全局基调,但风险也高:

  • 容易影响未预期控件。
  • 可能破坏第三方插件 UI。
  • 可能让弹窗、列表、树、编辑器边栏失去层次。

实际项目中应优先使用具体键,通配符只用于非常确定的基础色。

Tab 与版本兼容

Tabs 是主题里最容易出现兼容问题的控件之一。平台里存在多类 Tab:

作用
DefaultTabs 默认 Tab,除非被更具体类型覆盖
EditorTabs 编辑器 Tab
ToolWindow.HeaderTab Tool Window 头部 Tab
TabbedPane 设置、运行配置等普通 Swing Tabbed Pane
SearchEverywhere.Tab Search Everywhere Tab

一些属性在旧版本和新版本中名称不同。官方示例里同一个主题文件可能同时保留旧属性和新属性,让旧 IDE 忽略新属性、新 IDE 忽略已替代属性。维护多版本主题时,不要只在一个目标 IDE 里预览,应至少验证 since-build、最新稳定版和当前 EAP。

图标颜色与替换

图标定制放在 icons

{
  "icons": {
    "ColorPalette": {
      "Actions.Blue": "#2F6FED",
      "Objects.Green": "#2E9D58",
      "#DB5860": "#C93A3A"
    },
    "/actions/compile.svg": "/icons/factory.svg"
  }
}

规则:

  • ColorPalette 用于替换平台图标颜色。
  • Actions.* 用于 toolbar/action 语境。
  • Objects.* 用于文件、符号、run configuration 等对象语境。
  • 路径映射用于把平台默认 SVG 替换成自定义 SVG。
  • 替换图标的颜色优先级高于 ColorPalette

图标路径可以通过 UI Inspector 查看。一般从 AllIcons.Group.IconName 推导到资源路径,例如 action 图标常见形态是 /actions/name.svg

图标替换应克制。大规模替换平台图标会提高识别成本,也更容易违反 JetBrains 图标规范。

编辑器配色方案

主题可以通过 editorScheme 关联编辑器配色 XML:

{
  "name": "Example Dark",
  "dark": true,
  "editorScheme": "/themes/ExampleDark.xml",
  "ui": {}
}

常见流程:

  1. 在 IDE Settings 中创建或复制一个 Editor Color Scheme。
  2. 调整语法高亮、行号、光标、选择区、VCS 文件状态等颜色。
  3. 导出 .icls
  4. 改名为 .xml 并放入 resources。
  5. *.theme.jsoneditorScheme 中引用。

示例片段:

<scheme name="Example Dark" version="142" parent_scheme="Darcula">
  <colors>
    <option name="LINE_NUMBERS_COLOR" value="7A828E"/>
    <option name="FILESTATUS_ADDED" value="62CC47"/>
    <option name="FILESTATUS_DELETED" value="ED864A"/>
  </colors>
</scheme>

编辑器滚动条颜色有些不能从 Settings 导出,需要手动在 editor scheme XML 中维护,例如 ScrollBar.Mac.thumbColorScrollBar.Transparent.hoverThumbColor 等。

背景图

背景图通过 backgroundemptyFrameBackground 配置:

{
  "background": {
    "image": "/background.png",
    "transparency": 12,
    "fill": "scale",
    "anchor": "center"
  },
  "emptyFrameBackground": {
    "image": "/background.png",
    "transparency": 20,
    "fill": "scale",
    "anchor": "center"
  }
}

注意:

  • image 指向 resources 中的图片。
  • transparency 范围为 1 到 100,100 表示不透明。
  • fill 常用 scale
  • 背景图不能影响代码可读性、对比度和长时间使用舒适度。
  • Marketplace 展示图应呈现真实 IDE 使用效果,不要只展示装饰图。

主题插件最好让背景图成为可选卖点,而不是让整套主题依赖背景图才能成立。

继承已有主题

可以通过 parentTheme 基于已有主题继续覆盖:

{
  "name": "Example Night",
  "dark": true,
  "parentTheme": "ParentThemeId",
  "ui": {
    "Panel.background": "#111827"
  }
}

ParentThemeId 是目标主题 themeProviderid。内置主题 ID 可以查看平台注册的 themeProvider

继承适合:

  • 做一个现有主题的轻量变体。
  • 保持大部分平台视觉,只改品牌色和少量组件。
  • 减少完整维护所有控件键的成本。

如果父主题未来改动,子主题也会继承变化。发布前仍要完整预览。

为自定义 UI 暴露主题元数据

普通插件如果有自定义 UI,并希望主题作者能修改这些颜色,应提供 *.themeMetadata.json

<idea-plugin>
  <extensions defaultExtensionNs="com.intellij">
    <themeMetadataProvider path="/META-INF/Example.themeMetadata.json"/>
  </extensions>
</idea-plugin>

元数据示例:

{
  "name": "Example Plugin",
  "fixed": false,
  "ui": [
    {
      "key": "ExamplePanel.headerForeground",
      "description": "Foreground color for the Example tool window header.",
      "source": "com.example.ui.ExamplePanel",
      "since": "2026.1"
    },
    {
      "key": "ExamplePanel.oldBorderColor",
      "description": "Deprecated. Use ExamplePanel.borderColor instead.",
      "deprecated": true,
      "source": "com.example.ui.ExamplePanel"
    }
  ]
}

代码中使用命名颜色:

private val HEADER_FOREGROUND = JBColor.namedColor(
    "ExamplePanel.headerForeground",
    JBColor(0x1F2328, 0xD1D5DB),
)

原则:

  • 每个 key 都写 description
  • 已发布 key 不要删除,废弃时用 deprecated 并说明替代项。
  • source 指向真实 UI 组件类,方便定位。
  • 自定义 key 命名遵循 Object[.SubObject].[state][Part]Property
  • 不要在 key 里写 darculalightdark 等 look-and-feel 名称。

Key 命名规则

推荐结构:

Object[.SubObject].[state][Part]Property

示例:

Key 含义
ExamplePanel.headerForeground Header 文本色
ExamplePanel.borderColor 边框颜色
ExamplePanel.selectedBackground 选中背景
ExamplePanel.hoverInactiveBackground hover 且 inactive 的背景
ExamplePanel.warningIconColor warning 图标色

命名约束:

  • Object 和 SubObject 首字母大写。
  • property 用 lowerCamelCase。
  • 文本颜色用 foreground,不要用 textColor
  • 边框颜色用 borderColor,不要用 outlineColor
  • 对单一部件颜色使用 <Part>Color,例如 separatorColor
  • 默认 active 状态不写 active
  • Swing 旧 key 不能改名,但新 key 不要模仿旧命名。

查找可覆盖的 UI key

官方推荐的查找方式:

方式 用途
JSON 补全 ui 中输入时查看可用 key 和支持版本
Quick Documentation 查看 key 从哪个版本开始支持
Laf Defaults 按 element 搜索当前默认颜色
UI Inspector 从真实组件查看 foreground/background 和 key 名
平台主题实现 参考 High Contrast 等内置主题

调主题不要靠猜 key。先用 UI Inspector 或 Laf Defaults 确认控件,再在 JSON 中用补全和文档确认版本。

本地运行与预览

预览方式:

  • 在 theme JSON 编辑器中使用 Preview Theme action。
  • 对复杂样式,启动开发 IDE 实例真实测试。
  • DevKit 项目可创建 Plugin run configuration。
  • Gradle 项目可用 runIde 或自定义开发实例任务。

验证路径:

  1. 安装主题插件。
  2. 打开 Settings | Appearance & Behavior | Appearance。
  3. 选择新主题并 Apply。
  4. 打开 Settings、Project View、Search Everywhere、Run/Debug、VCS、Editor、Terminal、Tool Window。
  5. 检查亮/暗、高对比、缩放、不同 OS 字体和滚动条。

只在主题 JSON 预览里看通过不够。Preview 适合快速调色,真实 IDE 实例用于发布前验证。

构建、部署与 Marketplace

DevKit 工作流:

  1. Build | Build Project 或 Build Module。
  2. Build | Prepare Plugin Module for Deployment。
  3. 生成 JAR 或 ZIP。
  4. 从磁盘安装到 IDE。
  5. 在 Appearance 设置中选择主题。

Gradle 工作流:

./gradlew buildPlugin
./gradlew verifyPlugin
./gradlew runPluginVerifier

Marketplace 发布前检查:

  • 插件名和截图清楚表达主题实际效果。
  • 提供亮色/暗色/高对比说明。
  • 截图包含真实 IDE 界面,不只展示色板。
  • pluginIcon.svgpluginIcon_dark.svg 可读。
  • since-build 与实际测试矩阵匹配。
  • 不误导用户以为主题插件提供业务功能。

QA 清单

  • 主题插件保持独立,不混入普通功能。
  • themeProvider ID 稳定且唯一。
  • *.theme.json 能被 IDE 识别并出现在 Appearance 下拉框。
  • 所有颜色使用合法 6 位 RGB 或 8 位 RGBA。
  • 高频颜色抽成命名颜色。
  • hover、pressed、selected、inactive、disabled 状态可读。
  • Validation、Notification、Popup、Tooltip、Editor Tabs、Tool Window Tabs 都检查过。
  • 图标替换仍符合 JetBrains 图标识别习惯。
  • 编辑器 scheme 与 UI theme 视觉协调。
  • VCS 文件状态颜色足够区分。
  • 背景图不会干扰代码和 UI 文本。
  • 自定义 UI 提供 themeMetadataProvider,已发布 key 只废弃不删除。
  • 在最低支持 IDE、最新稳定版和 EAP 上预览过。
  • Marketplace 截图展示真实 IDE 场景。

参考来源