目录
idea plugin 布局学习
/  

idea plugin 布局学习

在 IntelliJ IDEA 插件开发中,UI 开发主要基于 Java Swing,但 JetBrains 提供了许多增强组件(JB 系列)和现代化的 Kotlin UI DSL。本文基于一个 Java 与 Kotlin 混用的实战项目,总结了从传统布局到现代 DSL 的核心知识点。

项目Demo地址:https://github.com/umuo/jetbrains-plugin-samples/tree/master/kotlin-layout-demo

1. 项目基础:Java 与 Kotlin 混用

build.gradle.kts 中配置好 Kotlin 插件后,项目可以完美支持双语混合开发。

  • 目录结构:
    • src/main/java: 存放遗留代码或纯算法逻辑。
    • src/main/kotlin: 存放 UI 代码、新的业务逻辑(推荐)。
  • 互操作性: Java 和 Kotlin 可以互相调用,几乎无缝。

注意: 插件开发中,请优先使用 JBPanel, JBLabel, JBTextField 等以 JB 开头的组件,它们能自动适配 IDEA 的明亮/暗黑主题。


2. 传统 Swing 布局管理器 (Layout Managers)

2.1 BorderLayout (边界布局)

最常用的顶层容器布局,将容器划分为 5 个区域。

  • 特点:
    • Center 区域会自动占据剩余的所有空间。
    • North/South 只看高度,忽略宽度。
    • East/West 只看宽度,忽略高度。
  • 适用场景: 页面整体骨架(如:顶部搜索栏 + 中间列表 + 底部状态栏)。
+-----------------------------------------------------+
|                  North (PAGE_START)                 |
|          (横向拉伸,高度取决于组件本身)                 |
+----------+-------------------------------+----------+
|          |                               |          |
|   West   |                               |   East   |
| (LINE_   |            Center             | (LINE_   |
|  START)  |         (双向自动拉伸)          |   END)   |
|          |    (占据所有剩余的空白区域)      |          |
|          |                               |          |
+----------+-------------------------------+----------+
|                  South (PAGE_END)                   |
+-----------------------------------------------------+
JBPanel<JBPanel<?>> panel = new JBPanel<>(new BorderLayout());
panel.add(new JButton("Top"), BorderLayout.NORTH);
panel.add(new JButton("Left"), BorderLayout.WEST);
panel.add(new JScrollPane(new JTextArea("Center")), BorderLayout.CENTER); // 自动填满

2.2 FlowLayout (流式布局)

  • 特点: 组件像文字一样从左到右排列,一行满了自动换行。
  • 适用场景: 按钮组、简单的标签云。
+-----------------------------------------------------+
| [Button 1]  [Button 2]  [Button 3 is Long] [Btn 4]  |
|                                                     |
| [Btn 5]  [Btn 6]                                    |
|                                                     |
| (↑ 剩下的空间是空的)                                |
+-----------------------------------------------------+
| 说明: 自动换行,组件保持原有大小,不进行拉伸        |
+-----------------------------------------------------+
// 左对齐,水平垂直间距均为 20
JBPanel<JBPanel<?>> panel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT, 20, 20));
panel.add(new JButton("Btn 1"));
panel.add(new JButton("Btn 2"));

2.3 BoxLayout (盒子布局)

  • 特点: 像堆积木一样,强制垂直(Y_AXIS)或水平(X_AXIS)单行排列。
  • 技巧: 使用 Box.createVerticalGlue() 可以制作“弹簧”效果,把组件顶到最上方或最下方。
  • 适用场景: 简单的侧边栏列表。
+--------------------------+
| [   Item 1 (Fixed)     ] |
+--------------------------+
| [   Item 2 (Fixed)     ] |
+--------------------------+
|           ^              |
|           |              |
|    Vertical Glue         |
| (弹簧: 撑开剩余空间)     |
|           |              |
|           v              |
+--------------------------+
| [   Item 3 (Bottom)    ] |
+--------------------------+
JBPanel<JBPanel<?>> panel = new JBPanel<>();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(new JButton("Item 1"));
panel.add(Box.createVerticalStrut(10)); // 固定间距
panel.add(new JButton("Item 2"));

2.4 GridLayout (网格布局)

  • 特点: 强制所有单元格 等宽等高
  • 缺点: 不灵活,一个很短的 Label 也会占用很大的空间。
  • 适用场景: 计算器、整齐的图标阵列。
+---------------------+---------------------+
|                     |                     |
|      (0,0)          |      (0,1)          |
|   [Label short]     |  [Text Field Long]  |
|                     |                     |
+---------------------+---------------------+
|                     |                     |
|      (1,0)          |      (1,1)          |
|   [   Button  ]     |  [   Button  ]      |
|                     |                     |
+---------------------+---------------------+
| 说明: 即使 (0,0) 内容很少,也被强制拉大   |
|       以匹配 (0,1) 的大小。               |
+---------------------+---------------------+
// 3行 2列
JBPanel<JBPanel<?>> panel = new JBPanel<>(new GridLayout(3, 2));

3. 进阶布局:GridBagLayout (网格包布局)

这是 Swing 中最强大但也最复杂的布局。它是 Kotlin UI DSL 的底层核心

  • 特点: * 单元格大小可变。
    • 支持组件跨行(GridHeight)、跨列(GridWidth)。
    • 通过权重(Weight)精确控制拉伸行为。
  • 核心参数 (GridBagConstraints):
    • gridx, gridy: 坐标。
    • weightx, weighty: 抢占空间的权重 (0.0 不拉伸,1.0 抢占剩余空间)。
    • fill: 当格子比组件大时,组件如何变形(HORIZONTAL, BOTH, NONE)。
    • anchor: 当组件比格子小时,组件靠哪边停靠(LINE_START, LINE_END)。
+----------------+------------------------------------+
|  [ Label ]     |  [      Text Field (Resizes)    ]  |
| (weightx=0)    |  (weightx=1.0, fill=Horizontal)    |
+----------------+------------------------------------+
|  [      Title Spanning 2 Columns (gridwidth=2)   ]  |
+----------------+------------------------------------+
|                |  ^                                 |
|  [ Side Menu ] |  |                                 |
|                |  |  Text Area (Resizes Both)       |
|  (gridheight=2)|  |  (weightx=1.0, weighty=1.0)     |
|                |  v                                 |
+----------------+------------------------------------+
|  [ Cancel ]    |               [  Submit (Right) ]  |
+----------------+------------------------------------+
JBPanel panel = new JBPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

// 需要手动配置每一行代码
c.gridx = 0; c.gridy = 0;
c.weightx = 0; 
panel.add(new JLabel("Label:"), c);

c.gridx = 1; c.gridy = 0;
c.weightx = 1.0; // 抢占水平空间
c.fill = GridBagConstraints.HORIZONTAL;
panel.add(new JTextField(), c);

4. 终极方案:Kotlin UI DSL v2

JetBrains 官方强烈推荐的声明式布局方式。它底层封装了 GridBagLayout,但提供了极简的 API。

4.1 基础写法

无需计算坐标,代码结构即 UI 结构。

fun createPanel(): DialogPanel {
    return panel {
        row("Username:") {
            textField()
                .comment("Enter your name")
        }
        row {
            checkBox("I agree")
        }
    }
}

5. 总结:如何选择布局?

布局方式适用场景复杂度推荐指数
BorderLayout页面主框架(上下左右中)⭐⭐⭐⭐⭐
FlowLayout简单的按钮组⭐⭐⭐
BoxLayout简单的垂直列表⭐⭐⭐⭐
GridLayout必须等宽等高的格子
GridBagLayout极其复杂的定制布局⭐⭐⭐⭐⭐⭐ (除非为了练手)
Kotlin UI DSL表单、设置页、所有复杂交互⭐⭐⭐⭐⭐⭐⭐ (官方推荐)

标题:idea plugin 布局学习
作者:gitsilence
地址:https://blog.lacknb.cn/articles/2026/01/03/1767411863152.html