last modified January 29, 2024
This article shows how to create Swing GUI applications in Kotlin. The code examples and image are available at the author’s Github Kotlin-Swing repository.
Swing is the principal GUI toolkit for JVM. It is a library which enables us to create powerful GUI applications.
In the first example, we show a basic window on the screen. The main application window is created with 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) }
The window is placed in the center of the screen.
class SimpleEx(title: String) : JFrame() {
SimpleEx inherits from the JFrame component. JFrame is a top-level container. The purpose of containers is to hold components of the application.
setTitle(title)
The title of the application is set with setTitle.
defaultCloseOperation = EXIT_ON_CLOSE
The defaultCloseOperation sets the operation that will happen by default when closes the frame. In our case, we exit the application.
setSize(400, 300)
We set the initial size with setSize.
setLocationRelativeTo(null)
This line is used to center the window on the screen.
val frame = SimpleEx(“Simple”) frame.isVisible = true
We create the application frame and show it on screen.
EventQueue.invokeLater(::createAndShowGUI)
The invokeLater method places the application on the Swing Event Queue. It is used to ensure that all UI updates are concurrency-safe.
Figure: Simple example
In the next example, we have a close button. A button component is created with JButton. When we click on the button, the application terminates.
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) }
We position a JButton on the window and add an action listener to this button.
val closeBtn = JButton(“Close”)
A button component is created. The constructor takes a string label as a parameter.
closeBtn.addActionListener { exitProcess(0) }
An action listener is added to the button with addActionListener. The action terminates the application by calling the exitProcess method.
createLayout(closeBtn)
The child components, in our case one button, need to be placed into containers. We delegate the task to the createLayout method.
val gl = GroupLayout(contentPane) contentPane.layout = gl
The content pane of a JFrame is an area where child components are placed. The children are organised by specialised non-visible components called layout managers. BorderLayout is the default layout manager of a content pane. This manager is very simple and is useful only in limited cases. We use the GroupLayout manager which is more powerful and flexible.
gl.autoCreateContainerGaps = true
The autoCreateContainerGaps attribute creates gaps between components and the edges of the container. Space or gaps are important part of the design of each application.
gl.setHorizontalGroup( gl.createSequentialGroup() .addComponent(arg[0]) )
gl.setVerticalGroup( gl.createSequentialGroup() .addComponent(arg[0]) )
GroupLayout manager defines the layout for each dimension independently. In one step, we lay out components alongside the horizontal axis; in the other step, we lay out components along the vertical axis. In both kinds of layouts we can arrange components sequentially or in parallel. In a horizontal layout, a row of components is called a sequential group and a column of components is called a parallel group. In a vertical layout, a column of components is called a sequential group and a row of components a parallel group.
In our example we have only one button, so the layout is very simple. For each dimension, we call the addComponent method with the button component as a parameter. (Each child component must be added for both dimensions.)
Figure: Close button
JLabel component is used to display text, colours, or images.
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) }
The example shows thirteen JLabel components; each of the labels has a different background colour. JLabel is usually used to display text; but it can display colours, too.
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)
Here we have an array of the built-in colour values.
val labels = stdCols.map { JLabel("", null, LEADING).apply {
minimumSize = Dimension(90, 40)
background = it
isOpaque = true
}
}
The labels are created with a certain size and background colour.
Figure: Standard colours
In the following example, we display a text and an image.
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) }
There are two labels in the program. One displays a title and one a JPEG image.
val title2 = JLabel(“Sid the sloth”) title2.font = title2.font.deriveFont(18f)
This label displays text. The font is enlarged.
val img = JLabel(ImageIcon(“src/main/resources/sid.jpg”))
This label displays an image.
contentPane.background = Color(0x358ae6)
For a better contrast, we change the background to some bluish colour.
gl.setHorizontalGroup( gl.createParallelGroup(GroupLayout.Alignment.CENTER) .addGap(60, 150, Integer.MAX_VALUE) .addComponent(arg[0]) .addComponent(arg[1]) )
With GroupLayout.Alignment.CENTER alignment, we center the components horizontally according to the size of the largest item. Since we have inserted a gap with a very large maximum size, the labels are contered on the window in the horizontal diretion.
Figure: JLabel
JCheckBox is a box with a label that has two states: on and off. If the check box is selected, it is represented by a tick in a box. A check box can be used to show or hide a splashscreen at startup, toggle visibility of a toolbar etc.
With JCheckBox it is possible to use an ActionListener or an ItemListener. Usually the latter option is used. ItemListener is the interface for receiving item events. The class that is interested in processing an item event, e.g. the observer, implements this interface. The observer object is registered with a component using the component’s addItemListener method. When an item selection event occurs, the observer’s itemStateChanged method is invoked.
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) }
Our code example shows or hides the title of the window depending whether the check box is selected.
val checkBox = JCheckBox(“Show title”, true)
JCheckBox is created. This constructor takes a text and the state of the check box as parameters. The check box is initially selected.
checkBox.addItemListener { e ->
val sel: Int = e.stateChange
if (sel == ItemEvent.SELECTED) {
setTitle("JCheckBox")
} else {
setTitle("")
}
}
An item listener is added with addItemListener. Depending on the state of the check box, we show or hide the window title.
Figure: JCheckBox
JSlider is a component that lets the user graphically select a value by sliding a knob within a bounded interval. Whe the slider’s knob is moved, the stateChanged method of the slider’s ChangeListener is called.
JSlider can optionally show tick marks for the range of its values. The tick marks are set with the setMinorTickSpacing, setMajorTickSpacing, and setPaintTicks methods.
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) }
A selected value from a slider is displayed in the adjacent label component.
slider = JSlider(0, 100, 0)
A JSlider is created with the minimum, maximum, and current values as parameters.
slider.minorTickSpacing = 5 slider.majorTickSpacing = 10
We set the distances between minor a major tick marks.
slider.paintTicks = true
The paintTicks property determines whether tick marks are painted on the slider.
slider.addChangeListener {
val value: Int = slider.value
lbl.text = value.toString()
}
A ChangeEvent is triggered when the slider has changed in some way. We get the current value of the slider with ChangeEvent , convert the integer into a string with toString and set it to the label through the text property.
Figure: JSlider
JComboBox is a component that combines a button or editable field and a drop-down list. The user can select a value from the drop-down list, which appears at the user’s request. If we make the combo box editable, then the combo box includes an editable field into which the user can type a value.
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) }
We have a combo box and a label. The combo box contains a list of Linux distributions. The selected item from the combo box is displayed in the adjacent label. The combo box uses its ItemListener to detect changes.
class ComboBoxEx(title: String) : JFrame(), ItemListener {
The ComboBoxEx implements the ItemListener; it must override the itemStateChanged function.
val distros = arrayOf( “Ubuntu”, “Redhat”, “Arch”, “Debian”, “Mint” )
box = JComboBox<String>(distros)
A JComboBox is created.
box.font = box.font.deriveFont(14f)
We increase the font of the combo box.
box.addItemListener(this)
The implementation of the item listener’s contract function is within this class.
gl.setVerticalGroup( gl.createParallelGroup(BASELINE) .addComponent(arg[0]) .addComponent(arg[1]) )
Vertically, the two components will be aligned to the baseline of their text.
override fun itemStateChanged(e: ItemEvent) {
if (e.stateChange == ItemEvent.SELECTED) {
display.text = e.item.toString()
}
}
The itemStateChanged is invoked when an item has been selected or deselected by the user. We check for ItemEvent.SELECTED state and set the combo box’s selected item to the label.
Figure: JComboBox
In the next example, we show icons in a JLabel component.
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) }
The example shows four images in one row.
val lbl1 = JLabel(ImageIcon(“src/main/resources/cpu.png”))
The image path is passed to the ImageIcon.
Figure: ImageIcon
JMenuBar implements a menu bar. JMenu implements a menu, which is a popup window containing JMenuItems that is displayed when the user selects an item on the JMenuBar. JMenuItem implements an item in a menu. It is selected by the user to perform an action.
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) }
The example creates a simple menu with one menu item. Selecting the Exit menu item we close the application.
val menubar = JMenuBar()
A menubar is created with JMenuBar.
val icon = ImageIcon(“src/main/resources/exit.png”)
An Exit icon is displayed in the menu.
val file = JMenu(“File”) file.mnemonic = KeyEvent.VK_F
A menu object is created with the JMenu class. The menus can be accessed via keyboard as well. To bind a menu to a particular key, we use the setMnemonic method. In our case, the menu can be opened with the Alt+F+E.
eMenuItem.toolTipText = “Exit application”
This code line creates a tooltip for the menu item.
eMenuItem.addActionListener { _: ActionEvent -> exitProcess(0) }
JMenuItem is a special kind of a button component. We add an action listener to it; it terminates the application when selected.
file.add(eMenuItem) menubar.add(file)
The menu item is added to the menu object and the menu object is inserted into the menubar.
jMenuBar = menubar
The menubar is set to the jMenubar property of the JFrame.
Figure: Simple menu
In the following example, we paint shapes on the window.
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) }
We draw six basic shapes on the panel: a square, a rectangle, a rounded rectangle, an ellipse, an arc, and a circle.
public override fun paintComponent(g: Graphics) { super.paintComponent(g)
doDrawing(g)
}
The drawing is done in the paintComponent method. We delegate the drawing routines to the doDrawing method.
val g2d = g as Graphics2D
The Graphics2D is the interface to the Swing drawing API.
val rh = RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ) rh[RenderingHints.KEY_RENDERING] = RenderingHints.VALUE_RENDER_QUALITY g2d.setRenderingHints(rh)
We set rendering hints to have high rendering quality.
g2d.fillRect(30, 20, 50, 50) g2d.fillRect(120, 20, 90, 60)
The fillRect method is used to draw both a rectangle and a square. The first two parameters are x, y coordinates of a shape to be drawn. The last two parameters are the width and the height of the shape.
g2d.fillRoundRect(250, 20, 70, 60, 25, 25)
Here we create a rounded rectangle. The last two parameters are the horizontal and vertical diameters of the arc at the four corners.
g2d.fill(Ellipse2D.Double(10.0, 100.0, 80.0, 100.0))
The fill method draws the interior of the given shape—an ellipse.
g2d.fillArc(120, 130, 110, 100, 5, 150)
The fillArc method fills a circular or elliptical arc covering the specified rectangle. An arc is a portion of the circumference of a circle.
g2d.fillOval(270, 130, 50, 50)
A circle is drawn using the fillOval method.
Figure: Shapes
In this article we have introduced Swing toolkit with Kotlin language.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all Kotlin tutorials.