ZetCode

Kotlin Swing

最后修改于 2024 年 1 月 29 日

本文介绍了如何使用 Kotlin 创建 Swing GUI 应用程序。 代码示例和图片可在作者的 Github Kotlin-Swing 存储库中找到。

Swing 是 JVM 的主要 GUI 工具包。 这是一个库,使我们能够创建强大的 GUI 应用程序。

Kotlin Swing JFrame

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

SimpleEx.kt
package com.zetcode

import java.awt.EventQueue
import javax.swing.JFrame

class SimpleEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

        defaultCloseOperation = EXIT_ON_CLOSE
        setSize(400, 300)
        setLocationRelativeTo(null)
    }
}

private fun createAndShowGUI() {

    val frame = SimpleEx("Simple")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

窗口放置在屏幕的中心。

class SimpleEx(title: String) : JFrame() {

SimpleEx 继承自 JFrame 组件。 JFrame 是一个顶级容器。 容器的目的是保存应用程序的组件。

setTitle(title)

应用程序的标题使用 setTitle 设置。

defaultCloseOperation = EXIT_ON_CLOSE

defaultCloseOperation 设置关闭框架时默认发生的操作。 在我们的例子中,我们退出应用程序。

setSize(400, 300)

我们使用 setSize 设置初始大小。

setLocationRelativeTo(null)

此行用于将窗口置于屏幕中心。

val frame = SimpleEx("Simple")
frame.isVisible = true

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

EventQueue.invokeLater(::createAndShowGUI)

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

Simple example
图:简单示例

Kotlin Swing JButton

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

CloseButtonEx.kt
package com.zetcode

import java.awt.EventQueue
import javax.swing.GroupLayout
import javax.swing.JButton
import javax.swing.JComponent
import javax.swing.JFrame

import kotlin.system.exitProcess

class CloseButtonEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

        val closeBtn = JButton("Close")

        closeBtn.addActionListener { exitProcess(0) }

        createLayout(closeBtn)

        defaultCloseOperation = EXIT_ON_CLOSE
        setSize(400, 300)
        setLocationRelativeTo(null)
    }


    private fun createLayout(vararg arg: JComponent) {

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

        gl.autoCreateContainerGaps = true

        gl.setHorizontalGroup(
            gl.createSequentialGroup()
                .addComponent(arg[0])
        )

        gl.setVerticalGroup(
            gl.createSequentialGroup()
                .addComponent(arg[0])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = CloseButtonEx("Close button")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

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

val closeBtn = JButton("Close")

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

closeBtn.addActionListener { exitProcess(0) }

使用 addActionListener 将动作监听器添加到按钮。 此操作通过调用 exitProcess 方法终止应用程序。

createLayout(closeBtn)

子组件,在我们的例子中是一个按钮,需要放置到容器中。 我们将任务委托给 createLayout 方法。

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

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

gl.autoCreateContainerGaps = true

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

gl.setHorizontalGroup(
    gl.createSequentialGroup()
        .addComponent(arg[0])
)

gl.setVerticalGroup(
    gl.createSequentialGroup()
        .addComponent(arg[0])
)

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

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

Close button
图:关闭按钮

Kotlin Swing JLabel

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

StandardColoursEx.kt
package com.zetcode

import java.awt.Color
import java.awt.Dimension
import java.awt.EventQueue
import javax.swing.GroupLayout
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.SwingConstants.LEADING


class StandardColoursEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

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

        val labels = stdCols.map {
            JLabel("", null, LEADING).apply {

                minimumSize = Dimension(90, 40)
                background = it
                isOpaque = true
            }
        }

        createLayout(labels)

        setTitle(title)
        defaultCloseOperation = EXIT_ON_CLOSE
        setLocationRelativeTo(null)
    }

    private fun createLayout(labels: List<JLabel>) {

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

        gl.autoCreateContainerGaps = true
        gl.autoCreateGaps = true

        gl.setHorizontalGroup(
            gl.createParallelGroup()
                .addGroup(
                    gl.createSequentialGroup()
                        .addComponent(labels[0])
                        .addComponent(labels[1])
                        .addComponent(labels[2])
                        .addComponent(labels[3])
                )
                .addGroup(
                    gl.createSequentialGroup()
                        .addComponent(labels[4])
                        .addComponent(labels[5])
                        .addComponent(labels[6])
                        .addComponent(labels[7])
                )
                .addGroup(
                    gl.createSequentialGroup()
                        .addComponent(labels[8])
                        .addComponent(labels[9])
                        .addComponent(labels[10])
                        .addComponent(labels[11])
                )
                .addComponent(labels[12])
        )

        gl.setVerticalGroup(
            gl.createSequentialGroup()
                .addGroup(
                    gl.createParallelGroup()
                        .addComponent(labels[0])
                        .addComponent(labels[1])
                        .addComponent(labels[2])
                        .addComponent(labels[3])
                )
                .addGroup(
                    gl.createParallelGroup()
                        .addComponent(labels[4])
                        .addComponent(labels[5])
                        .addComponent(labels[6])
                        .addComponent(labels[7])
                )
                .addGroup(
                    gl.createParallelGroup()
                        .addComponent(labels[8])
                        .addComponent(labels[9])
                        .addComponent(labels[10])
                        .addComponent(labels[11])
                )
                .addComponent(labels[12])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = StandardColoursEx("Standard colours")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

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

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

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

val labels = stdCols.map {
    JLabel("", null, LEADING).apply {

        minimumSize = Dimension(90, 40)
        background = it
        isOpaque = true
    }
}

标签是使用特定大小和背景颜色创建的。

Standard colours
图:标准颜色

在下面的示例中,我们显示文本和图像。

Labels.kt
package com.zetcode

import java.awt.Color
import java.awt.EventQueue
import javax.swing.GroupLayout
import javax.swing.ImageIcon
import javax.swing.JComponent
import javax.swing.JFrame
import javax.swing.JLabel

class LabelsEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        val title2 = JLabel("Sid the sloth")
        title2.font = title2.font.deriveFont(18f)

        val img = JLabel(ImageIcon("src/main/resources/sid.jpg"))

        createLayout(title2, img)

        contentPane.background = Color(0x358ae6)

        setTitle(title)

        defaultCloseOperation = EXIT_ON_CLOSE
        setLocationRelativeTo(null)
    }

    private fun createLayout(vararg arg: JComponent) {

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

        gl.autoCreateContainerGaps = true

        gl.setHorizontalGroup(
            gl.createParallelGroup(GroupLayout.Alignment.CENTER)
                .addGap(60, 150, Integer.MAX_VALUE)
                .addComponent(arg[0])
                .addComponent(arg[1])
        )

        gl.setVerticalGroup(
            gl.createSequentialGroup()
                .addComponent(arg[0])
                .addGap(30)
                .addComponent(arg[1])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = LabelsEx("JLabel")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

程序中有两个标签。 一个显示标题,一个显示 JPEG 图像。

val title2 = JLabel("Sid the sloth")
title2.font = title2.font.deriveFont(18f)

此标签显示文本。 字体已放大。

val img = JLabel(ImageIcon("src/main/resources/sid.jpg"))

此标签显示图像。

contentPane.background = Color(0x358ae6)

为了获得更好的对比度,我们将背景更改为某种蓝色。

gl.setHorizontalGroup(
    gl.createParallelGroup(GroupLayout.Alignment.CENTER)
        .addGap(60, 150, Integer.MAX_VALUE)
        .addComponent(arg[0])
        .addComponent(arg[1])
)

使用 GroupLayout.Alignment.CENTER 对齐,我们根据最大项目的大小水平居中组件。 由于我们插入了一个具有非常大最大尺寸的间隙,因此标签在水平方向上在窗口中居中。

labels
图:JLabel

Kotlin Swing JCheckBox

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

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

CheckBoxEx.kt
package com.zetcode

import java.awt.EventQueue
import java.awt.event.ItemEvent
import javax.swing.GroupLayout
import javax.swing.JCheckBox
import javax.swing.JComponent
import javax.swing.JFrame

class CheckBoxEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

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

        checkBox.addItemListener { e ->

            val sel: Int = e.stateChange

            if (sel == ItemEvent.SELECTED) {
                setTitle("JCheckBox")
            } else {
                setTitle("")
            }
        }

        createLayout(checkBox)

        defaultCloseOperation = EXIT_ON_CLOSE
        setSize(400, 300)
        setLocationRelativeTo(null)
    }

    private fun createLayout(vararg arg: JComponent) {

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

        gl.autoCreateContainerGaps = true

        gl.setHorizontalGroup(gl.createSequentialGroup()
            .addComponent(arg[0])
        )

        gl.setVerticalGroup(gl.createSequentialGroup()
            .addComponent(arg[0])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = CheckBoxEx("JCheckBox")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

我们的代码示例显示或隐藏窗口的标题,具体取决于是否选中复选框。

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

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

checkBox.addItemListener { e ->

    val sel: Int = e.stateChange

    if (sel == ItemEvent.SELECTED) {
        setTitle("JCheckBox")
    } else {
        setTitle("")
    }
}

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

JCheckBox
图:JCheckBox

Kotlin Swing JSlider

JSlider 是一个组件,允许用户通过在有界区间内滑动旋钮来以图形方式选择一个值。 当滑块的旋钮移动时,将调用滑块的 ChangeListenerstateChanged 方法。

JSlider 可以选择性地为其值的范围显示刻度线。 使用 setMinorTickSpacingsetMajorTickSpacingsetPaintTicks 方法设置刻度线。

SliderEx.kt
package com.zetcode

import java.awt.EventQueue
import javax.swing.GroupLayout
import javax.swing.JComponent
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JSlider

class SliderEx(title: String) : JFrame() {

    private lateinit var slider: JSlider
    private lateinit var lbl: JLabel

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        slider = JSlider(0, 100, 0)
        slider.minorTickSpacing = 5
        slider.majorTickSpacing = 10
        slider.paintTicks = true

        slider.addChangeListener {

            val value: Int = slider.value
            lbl.text = value.toString()
        }

        lbl = JLabel("...")

        createLayout(slider, lbl)
        setTitle(title)

        defaultCloseOperation = EXIT_ON_CLOSE
        setSize(400, 350)
        setLocationRelativeTo(null)
    }


    private fun createLayout(vararg arg: JComponent) {

        val pane = contentPane
        val gl = GroupLayout(pane)
        pane.layout = gl

        gl.autoCreateContainerGaps = true
        gl.autoCreateGaps = true

        gl.setHorizontalGroup(
            gl.createParallelGroup()
                .addComponent(arg[0])
                .addComponent(arg[1])
        )
        gl.setVerticalGroup(
            gl.createSequentialGroup()
                .addComponent(arg[0])
                .addComponent(arg[1])
        )
        pack()
    }
}

private fun createAndShowGUI() {

    val frame = SliderEx("Slider")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

从滑块中选择的值显示在相邻的标签组件中。

slider = JSlider(0, 100, 0)

使用最小、最大和当前值作为参数创建一个 JSlider

slider.minorTickSpacing = 5
slider.majorTickSpacing = 10

我们设置次要刻度和主要刻度之间的距离。

slider.paintTicks = true

paintTicks 属性确定是否在滑块上绘制刻度线。

slider.addChangeListener {

    val value: Int = slider.value
    lbl.text = value.toString()
}

当滑块以某种方式发生变化时,会触发一个 ChangeEvent。 我们使用 ChangeEvent 获取滑块的当前值,使用 toString 将整数转换为字符串,并通过 text 属性将其设置为标签。

JSlider
图:JSlider

Kotlin Swing JComboBox

JComboBox 是一个组合了按钮或可编辑字段和下拉列表的组件。 用户可以从下拉列表中选择一个值,该下拉列表在用户请求时出现。 如果我们使组合框可编辑,则组合框包含一个可编辑字段,用户可以在其中键入一个值。

ComboBoxEx.kt
package com.zetcode

import java.awt.EventQueue
import java.awt.event.ItemEvent
import java.awt.event.ItemListener
import javax.swing.GroupLayout
import javax.swing.GroupLayout.Alignment.BASELINE
import javax.swing.JComboBox
import javax.swing.JComponent
import javax.swing.JFrame
import javax.swing.JLabel

class ComboBoxEx(title: String) : JFrame(), ItemListener {

    private lateinit var display: JLabel
    private lateinit var box: JComboBox<String>

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        val distros = arrayOf(
            "Ubuntu", "Redhat", "Arch",
            "Debian", "Mint"
        )

        box = JComboBox<String>(distros)
        box.font = box.font.deriveFont(14f)
        box.addItemListener(this)

        display = JLabel("Ubuntu")
        display.font = display.font.deriveFont(14f)

        createLayout(box, display)

        setTitle(title)

        defaultCloseOperation = EXIT_ON_CLOSE
        setSize(400, 350)
        setLocationRelativeTo(null)
    }

    override fun itemStateChanged(e: ItemEvent) {

        if (e.stateChange == ItemEvent.SELECTED) {
            display.text = e.item.toString()
        }
    }

    private fun createLayout(vararg arg: JComponent) {

        val pane = contentPane
        val gl = GroupLayout(pane)
        pane.layout = gl

        gl.autoCreateContainerGaps = true
        gl.autoCreateGaps = true

        gl.setHorizontalGroup(
            gl.createSequentialGroup()
                .addComponent(arg[0])
                .addComponent(arg[1])
        )
        gl.setVerticalGroup(
            gl.createParallelGroup(BASELINE)
                .addComponent(arg[0])
                .addComponent(arg[1])
        )
        pack()
    }
}

private fun createAndShowGUI() {

    val frame = ComboBoxEx("JComboBox")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

我们有一个组合框和一个标签。 组合框包含一个 Linux 发行版的列表。 从组合框中选择的项显示在相邻的标签中。 组合框使用其 ItemListener 来检测更改。

class ComboBoxEx(title: String) : JFrame(), ItemListener {

ComboBoxEx 实现了 ItemListener; 它必须覆盖 itemStateChanged 函数。

val distros = arrayOf(
    "Ubuntu", "Redhat", "Arch",
    "Debian", "Mint"
)

box = JComboBox<String>(distros)

创建一个 JComboBox

box.font = box.font.deriveFont(14f)

我们增加组合框的字体。

box.addItemListener(this)

项目监听器的契约函数的实现在此类中。

gl.setVerticalGroup(
    gl.createParallelGroup(BASELINE)
        .addComponent(arg[0])
        .addComponent(arg[1])
)

在垂直方向上,这两个组件将与它们的文本的基线对齐。

override fun itemStateChanged(e: ItemEvent) {

    if (e.stateChange == ItemEvent.SELECTED) {
        display.text = e.item.toString()
    }
}

当用户选择或取消选择项目时,调用 itemStateChanged。 我们检查 ItemEvent.SELECTED 状态并将组合框的选定项设置为标签。

JComboBox
图:JComboBox

Swing 图标

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

LabelIconsEx.kt
package com.zetcode

import java.awt.EventQueue
import javax.swing.GroupLayout
import javax.swing.ImageIcon
import javax.swing.JComponent
import javax.swing.JFrame
import javax.swing.JLabel

class LabelIconsEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        val lbl1 = JLabel(ImageIcon("src/main/resources/cpu.png"))
        val lbl2 = JLabel(ImageIcon("src/main/resources/drive.png"))
        val lbl3 = JLabel(ImageIcon("src/main/resources/laptop.png"))
        val lbl4 = JLabel(ImageIcon("src/main/resources/player.png"))

        createLayout(lbl1, lbl2, lbl3, lbl4)

        setTitle(title)
        defaultCloseOperation = EXIT_ON_CLOSE
        setLocationRelativeTo(null)
    }

    private fun createLayout(vararg arg: JComponent) {

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

        gl.autoCreateContainerGaps = true
        gl.autoCreateGaps = true

        gl.setHorizontalGroup(
            gl.createSequentialGroup()
                .addComponent(arg[0])
                .addComponent(arg[1])
                .addComponent(arg[2])
                .addComponent(arg[3])
        )

        gl.setVerticalGroup(
            gl.createParallelGroup()
                .addComponent(arg[0])
                .addComponent(arg[1])
                .addComponent(arg[2])
                .addComponent(arg[3])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = LabelIconsEx("Icons")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

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

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

图像路径被传递给 ImageIcon

ImageIcon
图:ImageIcon

Kotlin Swing 菜单示例

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

SimpleMenuEx.kt
package com.zetcode

import java.awt.EventQueue
import java.awt.event.ActionEvent
import java.awt.event.KeyEvent
import javax.swing.ImageIcon
import javax.swing.JFrame
import javax.swing.JMenu
import javax.swing.JMenuBar
import javax.swing.JMenuItem
import kotlin.system.exitProcess

class SimpleMenuEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

        createMenuBar()

        defaultCloseOperation = EXIT_ON_CLOSE
        setSize(400, 300)
        setLocationRelativeTo(null)
    }

    private fun createMenuBar() {

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

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

        val eMenuItem = JMenuItem("Exit", icon)
        eMenuItem.mnemonic = KeyEvent.VK_E
        eMenuItem.toolTipText = "Exit application"
        eMenuItem.addActionListener { _: ActionEvent -> exitProcess(0) }

        file.add(eMenuItem)

        menubar.add(file)

        jMenuBar = menubar
    }
}

private fun createAndShowGUI() {

    val frame = SimpleMenuEx("Simple menu")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

该示例创建一个包含一个菜单项的简单菜单。 选择“退出”菜单项将关闭应用程序。

val menubar = JMenuBar()

使用 JMenuBar 创建菜单栏。

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

“退出”图标显示在菜单中。

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

使用 JMenu 类创建菜单对象。 也可以通过键盘访问菜单。 为了将菜单绑定到特定的键,我们使用 setMnemonic 方法。 在我们的例子中,可以使用 Alt+F+E 打开菜单。

eMenuItem.toolTipText = "Exit application"

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

eMenuItem.addActionListener { _: ActionEvent -> exitProcess(0) }

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

file.add(eMenuItem)
menubar.add(file)

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

jMenuBar = menubar

菜单栏被设置为 JFramejMenubar 属性。

Simple menu
图:简单菜单

Kotlin Swing 绘制形状

在下面的示例中,我们在窗口上绘制形状。

ShapesEx.kt
package com.zetcode

import java.awt.Color
import java.awt.EventQueue
import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.RenderingHints
import java.awt.geom.Ellipse2D
import javax.swing.JFrame
import javax.swing.JPanel

class Surface : JPanel() {

    private fun doDrawing(g: Graphics) {

        val g2d = g as Graphics2D
        g2d.paint = Color(150, 150, 150)

        val rh = RenderingHints(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON
        )
        rh[RenderingHints.KEY_RENDERING] = RenderingHints.VALUE_RENDER_QUALITY
        g2d.setRenderingHints(rh)

        g2d.fillRect(30, 20, 50, 50)
        g2d.fillRect(120, 20, 90, 60)
        g2d.fillRoundRect(250, 20, 70, 60, 25, 25)
        g2d.fill(Ellipse2D.Double(10.0, 100.0, 80.0, 100.0))
        g2d.fillArc(120, 130, 110, 100, 5, 150)
        g2d.fillOval(270, 130, 50, 50)
    }

    public override fun paintComponent(g: Graphics) {
        super.paintComponent(g)

        doDrawing(g)
    }
}

class ShapesEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        add(Surface())

        setTitle(title)

        defaultCloseOperation = EXIT_ON_CLOSE
        setSize(400, 350)
        setLocationRelativeTo(null)
    }
}

private fun createAndShowGUI() {

    val frame = ShapesEx("Shapes")
    frame.isVisible = true
}

fun main() {
    EventQueue.invokeLater(::createAndShowGUI)
}

我们在面板上绘制六个基本形状:正方形、矩形、圆角矩形、椭圆、弧形和圆形。

public override fun paintComponent(g: Graphics) {
    super.paintComponent(g)

    doDrawing(g)
}

绘图在 paintComponent 方法中完成。 我们将绘图例程委托给 doDrawing 方法。

val g2d = g as Graphics2D

Graphics2D 是 Swing 绘图 API 的接口。

val rh = RenderingHints(
    RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_ON
)
rh[RenderingHints.KEY_RENDERING] = RenderingHints.VALUE_RENDER_QUALITY
g2d.setRenderingHints(rh)

我们设置渲染提示以获得高质量的渲染。

g2d.fillRect(30, 20, 50, 50)
g2d.fillRect(120, 20, 90, 60)

fillRect 方法用于绘制矩形和正方形。 前两个参数是要绘制的形状的 x、y 坐标。 最后两个参数是形状的宽度和高度。

g2d.fillRoundRect(250, 20, 70, 60, 25, 25)

这里我们创建一个圆角矩形。 最后两个参数是四个角的弧的水平和垂直直径。

g2d.fill(Ellipse2D.Double(10.0, 100.0, 80.0, 100.0))

fill 方法绘制给定形状(椭圆)的内部。

g2d.fillArc(120, 130, 110, 100, 5, 150)

fillArc 方法填充覆盖指定矩形的圆形或椭圆形弧。 弧是圆周的一部分。

g2d.fillOval(270, 130, 50, 50)

使用 fillOval 方法绘制一个圆。

Shapes
图:图形

来源

Swing 文档

在本文中,我们使用 Kotlin 语言介绍了 Swing 工具包。

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出 所有 Kotlin 教程