IntelliJ Platform SDK DevGuide

Edit page

Kotlin UI DSL

##布局结构

使用panel创建UI:

panel { row { // child components } }

行从上到下垂直创建,顺序与调用row的代码行相同。

在一行内部,您可以按相同的顺序向工厂方法添加从左到右的组件,或者在每行中显示()

每个组件都有效地放置在自己的网格单元中。

可以将行的标签指定为row方法的参数:

row("Parameters") { ... }

行可以嵌套。 嵌套行块中的组件被视为从属于包含行,并相应地缩进。

row { checkBox(...) row { textField(...) // indented relatively to the checkbox above } }

要将多个组件放在同一个网格单元格中,请将它们包装在cell方法中:

row { // These two components will occupy two columns in the grid label(...) textField(...) // These two components will be placed in the same grid cell cell { label(...) textField(...) } }

要将组件放在网格行的右侧,请使用“right”方法:

row { rememberCheckBox() right { link("Forgot password") } }

##添加组件

There are two ways to add child components. The recommended way is to use factory methods label, button, radioButton, hint, link, etc. It allows you to create consistent UI and reuse common patterns.

note("""Do not have an account? <a href="https://account.jetbrains.com/login">Sign Up</a>""", span, wrap)

These method also support property bindings, allowing you to automatically load the value displayed in the component from a property and to store it back. The easiest way to do that is to pass a reference to a Kotlin bound property:

checkBox("Show tabs in single row", uiSettings::scrollTabLayoutInEditor)

或者,许多工厂方法支持在属性映射更复杂的情况下指定getter/setter对:

checkBox( "Show file extensions in editor tabs", { !uiSettings.hideKnownExtensionInTabs }, { uiSettings.hideKnownExtensionInTabs = !it }

If you want to add a component for which there are no factory methods, you can simply invoke an instance of your component, using the () overloaded operator:

val userField = JTextField(credentials?.userName) panel() { row { userField(grow, wrap) } } // use userField variable somehow

##支持的组件

### 标签

使用label方法:

label("Sample text")

###复选框

见上面的例子。

###单选按钮

单选按钮组使用buttonGroup块创建。 有两种方法可以使用它。 如果所选单选按钮对应于单个特定值

property,将属性绑定传递给buttonGroup方法,将特定值传递给radioButton函数:

buttonGroup(mySettings::providerType) { row { radioButton("In native Keychain", ProviderType.KEYCHAIN) } row { radioButton("In KeePass", ProviderType.KEEPASS) } }

如果所选单选按钮由多个布尔属性控制,则使用不带绑定的buttonGroup,并为除一个单选按钮之外的所有按钮指定属性绑定:

buttonGroup { row { radioButton("The tab on the left") } row { radioButton("The tab on the right", uiSettings::activeRightEditorOnClose) } row { radioButton("Most recently opened tab", uiSettings::activeMruEditorOnClose) } }

###文本字段

textField方法用于简单的文本字段:

row("Parameters:") { textField(settings::mergeParameters) }

要输入数字,请使用intTextField:

intTextField(uiSettings::editorTabLimit, columns = 4, range = EDITOR_TABS_RANGE)

对于密码文本字段,没有可用的工厂函数,因此您需要使用():

val passwordField = JPasswordField() val panel = panel { // ... row { passwordField() } }

要指定文本字段的大小,请传递columns参数,如上面的intTextField示例所示,或指定growPolicy参数:

val userField = JTextField(credentials?.userName) val panel = panel { row("Username:") { userField(growPolicy = GrowPolicy.SHORT_TEXT) } }

###组合框

comboBox方法与bound属性或getter/setter对一起使用:

comboBox(DefaultComboBoxModel<Int>(tabPlacements), uiSettings::editorTabPlacement) comboBox<PgpKey>( pgpListModel, { getSelectedPgpKey() ?: pgpListModel.items.firstOrNull() }, { mySettings.state.pgpKeyId = if (usePgpKey.isSelected) it?.keyId else null })

###纺纱厂

使用spinner方法:

spinner(retypeOptions::retypeDelay, minValue = 0, maxValue = 5000, step = 50)

###链接标签

使用link方法:

link("Forgot password?") { BrowserUtil.browse("https://account.jetbrains.com/forgot-password") }

###分隔符

使用titledRow方法并将分隔符下的控件放入嵌套块中:

titledRow("Appearance") { row { checkBox(...) } }

###解释性文字

使用comment参数:

checkBox(message("checkbox.smart.tab.reuse"), uiSettings::reuseNotModifiedTabs, comment = message("checkbox.smart.tab.reuse.inline.help"))

##使用属性绑定集成面板

panel方法返回的面板是DialogPanel的实例。 该基类支持标准的applyresetisModified方法。

如果您使用此面板作为DialogWrapper的主面板,则在使用OK操作关闭对话框时将自动调用apply方法。 在这种情况下,其他方法未使用。

如果您使用此面板实现Configurable,请使用BoundConfigurable作为基类。 在这种情况下,Configurable方法将自动委托给面板。

##启用和禁用控件

使用enableIf方法将控件的启用状态绑定到在其他控件中输入的值。 该方法的参数是谓词

checkBox("Show tabs in single row", uiSettings::scrollTabLayoutInEditor) .enableIf(myEditorTabPlacement.selectedValueIs(SwingConstants.TOP))

可用的谓词是:    *selected检查复选框或单选按钮的选定状态    *selectedValueIsselectedValueMatches来检查组合框中的选定项目。   

谓词可以与以及`或’中缀函数结合使用:

checkBox("Hide tabs if there is no space", uiSettings::hideTabsIfNeed) .enableIf(myEditorTabPlacement.selectedValueMatches { it != UISettings.TABS_NONE } and myScrollTabLayoutInEditorCheckBox.selected)

##示例

val panel = panel { noteRow("Login to get notified when the submitted\nexceptions are fixed.") row("Username:") { userField() } row("Password:") { passwordField() } row { rememberCheckBox() right { link("Forgot password?") { /* custom action */ } } } noteRow("""Do not have an account? <a href="https://account.jetbrains.com/login">Sign Up</a>""") }

## 常问问题

###一个单元格最小,第二个单元格最大

为第二个单元格中的某个组件设置CCFlags.growXCCFlags.pushX

Last modified: 9 May 2019