原文: http://zetcode.com/kotlin/swing/

Kotlin Swing 教程展示了如何在 Kotlin 中创建 Swing GUI 应用。 代码示例和图像可从作者的 Github Kotlin-Swing 存储库中获得。

Swing 是 Java 编程语言的主要 GUI 工具包。 它是 JFC(Java 基础类)的一部分,JFC 是用于为 Java 程序提供图形用户界面的 API。

Kotlin Swing JFrame

在第一个示例中,我们在屏幕上显示一个基本窗口。 使用JFrame创建主应用窗口。

KotlinSwingSimpleEx.kt

  1. package com.zetcode
  2. import java.awt.EventQueue
  3. import javax.swing.*
  4. class KotlinSwingSimpleEx(title: String) : JFrame() {
  5. init {
  6. createUI(title)
  7. }
  8. private fun createUI(title: String) {
  9. setTitle(title)
  10. defaultCloseOperation = JFrame.EXIT_ON_CLOSE
  11. setSize(300, 200)
  12. setLocationRelativeTo(null)
  13. }
  14. }
  15. private fun createAndShowGUI() {
  16. val frame = KotlinSwingSimpleEx("Simple")
  17. frame.isVisible = true
  18. }
  19. fun main(args: Array<String>) {
  20. EventQueue.invokeLater(::createAndShowGUI)
  21. }

窗口位于屏幕中央。

  1. class KotlinSwingSimpleEx(title: String) : JFrame() {

KotlinSwingSimpleEx继承自JFrame组件。 JFrame是顶级容器。 容器的目的是保存应用的组件。

  1. setTitle(title)

应用的标题由setTitle()设置。

  1. defaultCloseOperation = JFrame.EXIT_ON_CLOSE

defaultCloseOperation设置关闭框时默认发生的操作。 在我们的情况下,我们退出该应用。

  1. setSize(300, 200)

我们用setSize()设置初始大小。

  1. setLocationRelativeTo(null)

这条线用于使窗口在屏幕上居中。

  1. val frame = KotlinSwingSimpleEx("Simple")
  2. frame.isVisible = true

我们创建应用框架并将其显示在屏幕上。

  1. EventQueue.invokeLater(::createAndShowGUI)

invokeLater()方法将应用放置在 Swing 事件队列中。 它用于确保所有 UI 更新都是并发安全的。

Kotlin Swing 教程 - 图1

图:简单 example

Kotlin Swing JButton

在下一个示例中,我们有一个关闭按钮。 使用JButton创建一个按钮组件。 当我们单击按钮时,应用终止。

KotlinSwingCloseButtonEx.kt

  1. package com.zetcode
  2. import java.awt.EventQueue
  3. import javax.swing.*
  4. class KotlinSwingCloseButtonEx(title: String) : JFrame() {
  5. init {
  6. createUI(title)
  7. }
  8. private fun createUI(title: String) {
  9. setTitle(title)
  10. val closeBtn = JButton("Close")
  11. closeBtn.addActionListener { System.exit(0) }
  12. createLayout(closeBtn)
  13. defaultCloseOperation = JFrame.EXIT_ON_CLOSE
  14. setSize(300, 200)
  15. setLocationRelativeTo(null)
  16. }
  17. private fun createLayout(vararg arg: JComponent) {
  18. val gl = GroupLayout(contentPane)
  19. contentPane.layout = gl
  20. gl.autoCreateContainerGaps = true
  21. gl.setHorizontalGroup(gl.createSequentialGroup()
  22. .addComponent(arg[0])
  23. )
  24. gl.setVerticalGroup(gl.createSequentialGroup()
  25. .addComponent(arg[0])
  26. )
  27. pack()
  28. }
  29. }
  30. private fun createAndShowGUI() {
  31. val frame = KotlinSwingCloseButtonEx("Close button")
  32. frame.isVisible = true
  33. }
  34. fun main(args: Array<String>) {
  35. EventQueue.invokeLater(::createAndShowGUI)
  36. }

我们将JButton放置在窗口上,然后向该按钮添加一个动作监听器。

  1. val closeBtn = JButton("Close")

创建一个按钮组件。 构造器将字符串标签作为参数。

  1. closeBtn.addActionListener { System.exit(0) }

使用addActionListener()将动作监听器添加到按钮。 该操作通过调用System.exit()方法来终止应用。

  1. createLayout(closeBtn)

子组件(在我们的情况下是一个按钮)需要放入容器中。 我们将任务委托给createLayout()方法。

  1. val gl = GroupLayout(contentPane)
  2. contentPane.layout = gl

JFrame的内容窗格是放置子组件的区域。 子级由专门的不可见组件(称为布局管理器)组织。 BorderLayout是内容窗格的默认布局管理器。 该管理器非常简单,仅在少数情况下有用。 我们使用功能更强大,更灵活的GroupLayout管理器。

  1. gl.autoCreateContainerGaps = true

autoCreateContainerGaps属性在组件和容器边缘之间创建间隙。 空间或间隙是每个应用设计的重要组成部分。

  1. gl.setHorizontalGroup(gl.createSequentialGroup()
  2. .addComponent(arg[0])
  3. )
  4. gl.setVerticalGroup(gl.createSequentialGroup()
  5. .addComponent(arg[0])
  6. )

GroupLayout管理器独立定义每个大小的布局。 第一步,我们沿着水平轴布置组件; 在另一步骤中,我们沿垂直轴布置组件。 在两种布局中,我们都可以顺序或并行排列组件。 在水平布局中,一行组件称为顺序组,而一列组件称为并行组。 在垂直布局中,一列组件称为顺序组,一排组件称为并行组。

在我们的示例中,我们只有一个按钮,因此布局非常简单。 对于每个维度,我们以按钮组件作为参数调用addComponent()方法。 (必须为两个维度都添加每个子组件。)

Kotlin Swing 教程 - 图2

图:关闭按钮

Kotlin Swing JLabel

JLabel组件用于显示文本,颜色或图像。

KotlinSwingStandardColoursEx.kt

  1. package com.zetcode
  2. import java.awt.Color
  3. import java.awt.Dimension
  4. import java.awt.EventQueue
  5. import javax.swing.GroupLayout
  6. import javax.swing.JFrame
  7. import javax.swing.JLabel
  8. import javax.swing.SwingConstants.LEADING
  9. class KotlinSwingStandardColoursEx(title: String) : JFrame() {
  10. init {
  11. createUI(title)
  12. }
  13. private fun createUI(title: String) {
  14. val stdCols = arrayOf<Color>(Color.black, Color.blue, Color.cyan,
  15. Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta,
  16. Color.orange, Color.pink, Color.red, Color.white, Color.yellow)
  17. val labels = stdCols.map {
  18. JLabel("", null, LEADING).apply {
  19. minimumSize = Dimension(90, 40)
  20. background = it
  21. isOpaque = true
  22. }
  23. }
  24. createLayout(labels)
  25. setTitle(title)
  26. defaultCloseOperation = JFrame.EXIT_ON_CLOSE
  27. setLocationRelativeTo(null)
  28. }
  29. private fun createLayout(labels: List<JLabel>) {
  30. val gl = GroupLayout(contentPane)
  31. contentPane.layout = gl
  32. gl.autoCreateContainerGaps = true
  33. gl.autoCreateGaps = true
  34. gl.setHorizontalGroup(gl.createParallelGroup()
  35. .addGroup(gl.createSequentialGroup()
  36. .addComponent(labels[0])
  37. .addComponent(labels[1])
  38. .addComponent(labels[2])
  39. .addComponent(labels[3]))
  40. .addGroup(gl.createSequentialGroup()
  41. .addComponent(labels[4])
  42. .addComponent(labels[5])
  43. .addComponent(labels[6])
  44. .addComponent(labels[7]))
  45. .addGroup(gl.createSequentialGroup()
  46. .addComponent(labels[8])
  47. .addComponent(labels[9])
  48. .addComponent(labels[10])
  49. .addComponent(labels[11]))
  50. .addComponent(labels[12])
  51. )
  52. gl.setVerticalGroup(gl.createSequentialGroup()
  53. .addGroup(gl.createParallelGroup()
  54. .addComponent(labels[0])
  55. .addComponent(labels[1])
  56. .addComponent(labels[2])
  57. .addComponent(labels[3]))
  58. .addGroup(gl.createParallelGroup()
  59. .addComponent(labels[4])
  60. .addComponent(labels[5])
  61. .addComponent(labels[6])
  62. .addComponent(labels[7]))
  63. .addGroup(gl.createParallelGroup()
  64. .addComponent(labels[8])
  65. .addComponent(labels[9])
  66. .addComponent(labels[10])
  67. .addComponent(labels[11]))
  68. .addComponent(labels[12])
  69. )
  70. pack()
  71. }
  72. }
  73. private fun createAndShowGUI() {
  74. val frame = KotlinSwingStandardColoursEx("Standard colours")
  75. frame.isVisible = true
  76. }
  77. fun main(args: Array<String>) {
  78. EventQueue.invokeLater(::createAndShowGUI)
  79. }

该示例显示了 13 个JLabel组件; 每个标签具有不同的背景色。 JLabel通常用于显示文本; 但它也可以显示颜色。

  1. val stdCols = arrayOf<Color>(Color.black, Color.blue, Color.cyan,
  2. Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta,
  3. Color.orange, Color.pink, Color.red, Color.white, Color.yellow)

在这里,我们有一个内置颜色值的数组。

  1. val labels = stdCols.map {
  2. JLabel("", null, LEADING).apply {
  3. minimumSize = Dimension(90, 40)
  4. background = it
  5. isOpaque = true
  6. }
  7. }

标签以一定的大小和背景色创建。

Kotlin Swing 教程 - 图3

图:标准颜色

JCheckBox

JCheckBox是带有标签的框,该标签具有两种状态:开和关。 如果选中此复选框,则在复选框中用勾号表示。 复选框可用于在启动时显示或隐藏启动屏幕,切换工具栏的可见性等。

通过JCheckBox可以使用ActionListenerItemListener。 通常使用后一种选项。 ItemListener是用于接收项目事件的接口。 对处理项目事件感兴趣的类,例如观察者,实现此接口。 使用组件的addItemListener()方法向组件注册观察者对象。 发生项目选择事件时,将调用观察者的itemStateChanged()方法。

KotlinSwingCheckBoxEx.kt

  1. package com.zetcode
  2. import java.awt.EventQueue
  3. import java.awt.event.ItemEvent
  4. import javax.swing.GroupLayout
  5. import javax.swing.JCheckBox
  6. import javax.swing.JComponent
  7. import javax.swing.JFrame
  8. class KotlinSwingCheckBoxEx(title: String) : JFrame() {
  9. init {
  10. createUI(title)
  11. }
  12. private fun createUI(title: String) {
  13. setTitle(title)
  14. val checkBox = JCheckBox("Show title", true)
  15. checkBox.addItemListener { e ->
  16. val sel: Int = e.stateChange
  17. if (sel == ItemEvent.SELECTED) {
  18. setTitle("JCheckBox")
  19. } else {
  20. setTitle("")
  21. }
  22. }
  23. createLayout(checkBox)
  24. defaultCloseOperation = JFrame.EXIT_ON_CLOSE
  25. setSize(300, 200)
  26. setLocationRelativeTo(null)
  27. }
  28. private fun createLayout(vararg arg: JComponent) {
  29. val gl = GroupLayout(contentPane)
  30. contentPane.layout = gl
  31. gl.autoCreateContainerGaps = true
  32. gl.setHorizontalGroup(gl.createSequentialGroup()
  33. .addComponent(arg[0])
  34. )
  35. gl.setVerticalGroup(gl.createSequentialGroup()
  36. .addComponent(arg[0])
  37. )
  38. pack()
  39. }
  40. }
  41. private fun createAndShowGUI() {
  42. val frame = KotlinSwingCheckBoxEx("JCheckBox")
  43. frame.isVisible = true
  44. }
  45. fun main(args: Array<String>) {
  46. EventQueue.invokeLater(::createAndShowGUI)
  47. }

我们的代码示例根据是否选中复选框来显示或隐藏窗口的标题。

  1. val checkBox = JCheckBox("Show title", true)

JCheckBox已创建。 此构造器将文本和复选框的状态作为参数。 最初已选中该复选框。

  1. checkBox.addItemListener { e ->
  2. val sel: Int = e.stateChange
  3. if (sel == ItemEvent.SELECTED) {
  4. setTitle("JCheckBox")
  5. } else {
  6. setTitle("")
  7. }
  8. }

项目监听器随addItemListener()添加。 根据复选框的状态,我们显示或隐藏窗口标题。

Kotlin Swing 教程 - 图4

图:JCheckBox

Kotlin Swing 图标

在下一个示例中,我们在JLabel组件中显示图标。

KotlinSwingLabelIconEx.kt

  1. package com.zetcode
  2. import javax.swing.*
  3. class KotlinSwingLabelIconEx(title: String) : JFrame() {
  4. init {
  5. createUI(title)
  6. }
  7. private fun createUI(title: String) {
  8. val lbl1 = JLabel(ImageIcon("src/main/resources/cpu.png"))
  9. val lbl2 = JLabel(ImageIcon("src/main/resources/drive.png"))
  10. val lbl3 = JLabel(ImageIcon("src/main/resources/laptop.png"))
  11. val lbl4 = JLabel(ImageIcon("src/main/resources/player.png"))
  12. createLayout(lbl1, lbl2, lbl3, lbl4)
  13. setTitle(title)
  14. defaultCloseOperation = JFrame.EXIT_ON_CLOSE
  15. setLocationRelativeTo(null)
  16. }
  17. private fun createLayout(vararg arg: JComponent) {
  18. val gl = GroupLayout(contentPane)
  19. contentPane.layout = gl
  20. gl.autoCreateContainerGaps = true
  21. gl.autoCreateGaps = true
  22. gl.setHorizontalGroup(gl.createSequentialGroup()
  23. .addComponent(arg[0])
  24. .addComponent(arg[1])
  25. .addComponent(arg[2])
  26. .addComponent(arg[3])
  27. )
  28. gl.setVerticalGroup(gl.createParallelGroup()
  29. .addComponent(arg[0])
  30. .addComponent(arg[1])
  31. .addComponent(arg[2])
  32. .addComponent(arg[3])
  33. )
  34. pack()
  35. }
  36. }
  37. private fun createAndShowGUI() {
  38. val frame = KotlinSwingLabelIconEx("Icons")
  39. frame.isVisible = true
  40. }
  41. fun main(args: Array<String>) {
  42. SwingUtilities.invokeLater(::createAndShowGUI)
  43. }

该示例在一行中显示了四个图像。

  1. val lbl1 = JLabel(ImageIcon("src/main/resources/cpu.png"))

图像路径被传递到ImageIcon

Kotlin Swing 教程 - 图5

图:图像Icon

Kotlin Swing 菜单示例

JMenuBar实现菜单栏。 JMenu实现菜单,该菜单是包含JMenuItems的弹出窗口,当用户在JMenuBar上选择一个项目时显示。 JMenuItem实现菜单中的项目。 用户选择它来执行操作。

KotlinSwingSimpleMenuExEx.kt

  1. package com.zetcode
  2. import java.awt.EventQueue
  3. import java.awt.event.ActionEvent
  4. import java.awt.event.KeyEvent
  5. import javax.swing.*
  6. class KotlinSwingSimpleMenuExEx(title: String) : JFrame() {
  7. init {
  8. createUI(title)
  9. }
  10. private fun createUI(title: String) {
  11. setTitle(title)
  12. createMenuBar()
  13. defaultCloseOperation = JFrame.EXIT_ON_CLOSE
  14. setSize(300, 200)
  15. setLocationRelativeTo(null)
  16. }
  17. private fun createMenuBar() {
  18. val menubar = JMenuBar()
  19. val icon = ImageIcon("src/main/resources/exit.png")
  20. val file = JMenu("File")
  21. file.mnemonic = KeyEvent.VK_F
  22. val eMenuItem = JMenuItem("Exit", icon)
  23. eMenuItem.mnemonic = KeyEvent.VK_E
  24. eMenuItem.toolTipText = "Exit application"
  25. eMenuItem.addActionListener { _: ActionEvent -> System.exit(0) }
  26. file.add(eMenuItem)
  27. menubar.add(file)
  28. jMenuBar = menubar
  29. }
  30. }
  31. private fun createAndShowGUI() {
  32. val frame = KotlinSwingSimpleMenuExEx("Simple menu")
  33. frame.isVisible = true
  34. }
  35. fun main(args: Array<String>) {
  36. EventQueue.invokeLater(::createAndShowGUI)
  37. }

该示例创建一个带有一个菜单项的简单菜单。 选择退出菜单项,我们关闭应用。

  1. val menubar = JMenuBar()

使用JMenuBar创建菜单栏。

  1. val icon = ImageIcon("src/main/resources/exit.png")

菜单中显示退出图标。

  1. val file = JMenu("File")
  2. file.mnemonic = KeyEvent.VK_F

使用JMenu类创建菜单对象。 也可以通过键盘访问菜单。 要将菜单绑定到特定键,我们使用setMnemonic()方法。 在我们的情况下,可以使用Alt + F + E 打开菜单。

  1. eMenuItem.toolTipText = "Exit application"

此代码行为菜单项创建工具提示。

  1. eMenuItem.addActionListener { _: ActionEvent -> System.exit(0) }

JMenuItem是一种特殊的按钮组件。 我们向它添加一个动作监听器; 选择后将终止应用。

  1. file.add(eMenuItem)
  2. menubar.add(file)

菜单项被添加到菜单对象,菜单对象被插入菜单栏。

  1. jMenuBar = menubar

菜单栏设置为JFramejMenubar属性。

Kotlin Swing 教程 - 图6

图:简单菜单

在本教程中,我们介绍了使用 Kotlin 语言的 Swings 工具包。 您可能也对相关教程感兴趣: Kotlin Hello World 教程Kotlin 控制流Kotlin 读取文件教程Kotlin 写入文件教程