Components in Jython Swing

In this part of the Jython Swing programming tutorial, we will cover basic Swing components.

Components are basic building blocks of a GUI application. Over the years, several components became a standard in all toolkits on all OS platforms. For example a button, a check box or a scroll bar. Swing has a rich set of components which cover most of the programming needs. More specialised components can be created as custom components.

JCheckBox

The JCheckBox is a component that has two states: on and off. The On state is visualised by a check mark. It is used to denote some boolean property. The JCheckBox component provides a check box with a text label.

#!/usr/local/bin/jython
# -*- coding: utf-8 -*-

"""
ZetCode Jython Swing tutorial

This program uses JCheckBox
component to show/hide the title
of the window

author: Jan Bodnar
website: www.zetcode.com
last modified: November 2010
"""


from java.awt import Dimension
from javax.swing import Box
from javax.swing import BoxLayout
from javax.swing import JCheckBox
from javax.swing import JFrame


class Example(JFrame):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):


        self.setLayout(BoxLayout(self.getContentPane(), BoxLayout.Y_AXIS))
        self.add(Box.createRigidArea(Dimension(15, 20)))

        cb = JCheckBox("Show Title", True, actionPerformed=self.onSelect)
        cb.setFocusable(False)
        self.add(cb)


        self.setTitle("JCheckBox example")
        self.setSize(280, 200)
        self.setResizable(False)
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setLocationRelativeTo(None)
        self.setVisible(True)


    def onSelect(self, e):

        source = e.getSource()
        isSelected = source.isSelected()

        if isSelected:
            self.setTitle("JCheckBox example")
        else:
            self.setTitle("")


if __name__ == '__main__':
    Example()

In our example, we place a check box on the window. The check box shows/hides the title of the window.

self.setLayout(BoxLayout(self.getContentPane(), BoxLayout.Y_AXIS))
self.add(Box.createRigidArea(Dimension(15, 20)))

In this example, we use a BoxLayout layout manager. We put some space there, so that the check box is not too close to the corner.

cb = JCheckBox("Show Title", True, actionPerformed=self.onSelect)

The JCheckBox component is created. The first parameter of the constructor is its text label. The second parameter is a boolean value indicating the initial selection state. If True the check box is selected. The third parameter specifies the method, which is called when we select or unselect the check box.

cb.setFocusable(False)

We disable the focus for the check box. A JCheckBox that has a focus may be selected or unselected with a spacebar.

source = e.getSource()
isSelected = source.isSelected()

if isSelected:
    self.setTitle("JCheckBox example")
else:
    self.setTitle("")

From the event object, we get the source component. In our case is the a check box. We find out the selection state of the check box. Depending on the state of the check box, we show or hide the title of the window.

JCheckBox
Figure: JCheckBox

JLabel

The JLabel component is used to display text, image or both. No user interaction is available.

#!/usr/local/bin/jython
# -*- coding: utf-8 -*-

"""
ZetCode Jython Swing tutorial

This program uses JLabel component to
show lyrics of a song

author: Jan Bodnar
website: www.zetcode.com
last modified: November 2010
"""

from java.awt import BorderLayout
from java.awt import Font
from javax.swing import BorderFactory
from javax.swing import JFrame
from javax.swing import JLabel
from javax.swing import JPanel


class Example(JFrame):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        lyrics =  """<html>It's way too late to think of<br>
        Someone I would call now<br>
        And neon signs got tired<br>
        Red eye flights help the stars out<br>
        I'm safe in a corner<br>
        Just hours before me<br>
        <br>
        I'm waking with the roaches<br>
        The world has surrendered<br>
        I'm dating ancient ghosts<br>
        The ones I made friends with<br>
        The comfort of fireflies<br>
        Long gone before daylight<br>
        <br>
        And if I had one wishful field tonight<br>
        I'd ask for the sun to never rise<br>
        If God leant his voice for me to speak<br>
        I'd say go to bed, world<br>
        <br>
        I've always been too late<br>
        To see what's before me<br>
        And I know nothing sweeter than<br>
        Champaign from last New Years<br>
        Sweet music in my ears<br>
        And a night full of no fears<br>
        <br>
        But if I had one wishful field tonight<br>
        I'd ask for the sun to never rise<br>
        If God passed a mic to me to speak<br>
        I'd say stay in bed, world<br>
        Sleep in peace</html>"""

        panel = JPanel()
        panel.setLayout(BorderLayout(10, 10))

        label = JLabel(lyrics)
        label.setFont(Font("Georgia", Font.PLAIN, 14))

        panel.add(label, BorderLayout.CENTER)
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10))
        self.add(panel)
        self.pack()

        self.setTitle("No Sleep")
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setLocationRelativeTo(None)
        self.setVisible(True)


if __name__ == '__main__':
    Example()

Our example shows lyrics of a song in the window. We can use HTML tags in JLabel component. We use the <br> tag to separate lines.

lyrics =  """<html>It's way too late to think of<br>
Someone I would call now<br>
And neon signs got tired<br>
...

We define a multi line text.

label = JLabel(lyrics)
label.setFont(Font("Georgia", Font.PLAIN, 14))

Here we create the label component. We set its font to plain Georgia, 14 px tall.

panel.add(label, BorderLayout.CENTER)
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10))

We put the label into the center of the panel. We put 10px around the label.

JLabel component
Figure: JLabel component

JSlider

JSlider is a component that lets the user graphically select a value by sliding a knob within a bounded interval. Our example will show a volume control.

#!/usr/local/bin/jython
# -*- coding: utf-8 -*-

"""
ZetCode Jython Swing tutorial

In this program we use the JSlider
component to create a volume control
user interface

author: Jan Bodnar
website: www.zetcode.com
last modified: November 2010
"""

from java.awt import BorderLayout
from java.awt import Dimension
from javax.swing import BorderFactory
from javax.swing import Box
from javax.swing import BoxLayout
from javax.swing import ImageIcon
from javax.swing import JFrame
from javax.swing import JLabel
from javax.swing import JPanel
from javax.swing import JSlider


class Example(JFrame):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        self.mute = ImageIcon("mute.png")
        self.min = ImageIcon("min.png")
        self.med = ImageIcon("med.png")
        self.max = ImageIcon("max.png")

        panel = JPanel()
        panel.setLayout(BoxLayout(panel, BoxLayout.X_AXIS))
        panel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40))
        self.setLayout(BorderLayout())

        panel.add(Box.createHorizontalGlue())

        slider = JSlider(0, 150, 0, stateChanged=self.onSlide)
        slider.setPreferredSize(Dimension(150, 30))

        panel.add(slider)
        panel.add(Box.createRigidArea(Dimension(5, 0)))

        self.label = JLabel(self.mute, JLabel.CENTER)
        panel.add(self.label)
        panel.add(Box.createHorizontalGlue())
        self.add(panel, BorderLayout.CENTER)

        self.pack()

        self.setTitle("JSlider")
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setLocationRelativeTo(None)
        self.setVisible(True)

    def onSlide(self, e):

        sender = e.getSource()

        value = sender.getValue()

        if value == 0:
            self.label.setIcon(self.mute)
        elif value > 0 and value <= 30:
            self.label.setIcon(self.min)
        elif value > 30 and value < 80:
            self.label.setIcon(self.med)
        else:
            self.label.setIcon(self.max)


if __name__ == '__main__':
    Example()

In the code example, we show a JSlider and a JLabel. By dragging the slider, we change the icon on the label component. We have four images that represent various states of the sound.

self.mute = ImageIcon("mute.png")

Here we create an image icon.

panel.setLayout(BoxLayout(panel, BoxLayout.X_AXIS))

Panel component has a horizontal BoxLayout.

panel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40))

We creare a 40px border around the panel.

panel.add(Box.createHorizontalGlue())

We put resizable space to bo both sides, left and right. It is to prevent JSlider from growing to unnatural sizes.

slider = JSlider(0, 150, 0, stateChanged=self.onSlide)

This is a JSlider constructor. The parameters are minimum value, maximum value and current value. When we slide the knob of the slider, the onSlide() method is being called.

panel.add(Box.createRigidArea(Dimension(5, 0)))

We place a 5px rigid space between the two components. They are too close to each other, when the slider is at the end position.

self.label = JLabel(self.mute, JLabel.CENTER)

This line creates a JLabel instance with the specified image and horizontal alignment. The label is centered vertically in its display area by default.

JSlider component
Figure: JSlider component

JToggleButton

JToggleButton is a button that has two states. Pressed and not pressed. You toggle between these two states by clicking on it. There are situations where this functionality fits well.

#!/usr/local/bin/jython
# -*- coding: utf-8 -*-

"""
ZetCode Jython Swing tutorial

This program uses toggle buttons to
change the background color of
a panel

author: Jan Bodnar
website: www.zetcode.com
last modified: November 2010
"""

from java.awt import Color
from java.awt import Dimension

from javax.swing import BorderFactory
from javax.swing import Box
from javax.swing import BoxLayout
from javax.swing import JFrame
from javax.swing import JPanel
from javax.swing import JToggleButton
from javax.swing.border import LineBorder


class Example(JFrame):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()


    def initUI(self):

        self.setPreferredSize(Dimension(280, 200))


        bottom = JPanel()
        bottom.setLayout(BoxLayout(bottom, BoxLayout.X_AXIS))
        bottom.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20))

        leftPanel = JPanel()
        leftPanel.setLayout(BoxLayout(leftPanel, BoxLayout.Y_AXIS))

        redButton = JToggleButton("red", actionPerformed=self.onToggle)
        greenButton = JToggleButton("green", actionPerformed=self.onToggle)
        blueButton = JToggleButton("blue", actionPerformed=self.onToggle)

        blueButton.setMaximumSize(greenButton.getMaximumSize())
        redButton.setMaximumSize(greenButton.getMaximumSize())

        leftPanel.add(redButton)
        leftPanel.add(Box.createRigidArea(Dimension(25, 7)))
        leftPanel.add(greenButton)
        leftPanel.add(Box.createRigidArea(Dimension(25, 7)))
        leftPanel.add(blueButton)

        bottom.add(leftPanel)
        bottom.add(Box.createRigidArea(Dimension(20, 0)))

        self.display = JPanel()
        self.display.setPreferredSize(Dimension(110, 110))
        self.display.setBorder(LineBorder.createGrayLineBorder())
        self.display.setBackground(Color.black)

        bottom.add(self.display)
        self.add(bottom)

        self.pack()

        self.setTitle("JToggleButton")
        self.setResizable(False)
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setLocationRelativeTo(None)
        self.setVisible(True)

    def onToggle(self, e):

        color = self.display.getBackground()
        red = color.getRed()
        green = color.getGreen()
        blue = color.getBlue()

        if e.getActionCommand() == "red":
            if red == 0:
                red = 255
            else:
                red = 0

        if e.getActionCommand() == "green":
            if green == 0:
                green = 255
            else:
                green = 0

        if e.getActionCommand() == "blue":
            if blue == 0:
                blue = 255
            else:
                blue = 0

        setCol = Color(red, green, blue)
        self.display.setBackground(setCol)


if __name__ == '__main__':
    Example()

In the code example, we use three toggle buttons to change the color of a rectangular component.

redButton = JToggleButton("red", actionPerformed=self.onToggle)

We create a JToggleButton component. When we click on the button, the onToggle() method is launched.

blueButton.setMaximumSize(greenButton.getMaximumSize())
redButton.setMaximumSize(greenButton.getMaximumSize())

We make all three buttons of equal size.

color = self.display.getBackground()
red = color.getRed()
green = color.getGreen()
blue = color.getBlue()

We determine the current red, green, blue parts of the display background color.

if e.getActionCommand() == "red":
    if red == 0:
        red = 255
    else:
        red = 0

We determine, which button was toggled, and update the color part of the RGB value accordingly.

setCol = Color(red, green, blue)
self.display.setBackground(setCol)

Here a new color is created and the display panel is updated to a new color.

JToggleButton component
Figure: JToggleButton component

JList

JList is a component that displays a list of objects. It allows the user to select one or more items.

#!/usr/local/bin/jython
# -*- coding: utf-8 -*-

"""
ZetCode Jython Swing tutorial

This program shows all system fonts
in a JList component

author: Jan Bodnar
website: www.zetcode.com
last modified: November 2010
"""


from java.awt import BorderLayout
from java.awt import Dimension
from java.awt import Font
from java.awt import GraphicsEnvironment

from javax.swing import JFrame
from javax.swing import BorderFactory
from javax.swing import JScrollPane
from javax.swing import JPanel
from javax.swing import JLabel
from javax.swing import JList



class Example(JFrame):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        panel = JPanel()
        panel.setLayout(BorderLayout())
        panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20))

        ge = GraphicsEnvironment.getLocalGraphicsEnvironment()
        fonts = ge.getAvailableFontFamilyNames()

        list = JList(fonts, valueChanged=self.onChanged)

        pane = JScrollPane()
        pane.getViewport().add(list)
        pane.setPreferredSize(Dimension(250, 200))
        panel.add(pane)

        self.label = JLabel("Aguirre, der Zorn Gottes")
        self.label.setFont(Font("Serif", Font.PLAIN, 12))
        self.add(self.label, BorderLayout.SOUTH)

        self.add(panel)
        self.pack()

        self.setTitle("JList")
        self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.setLocationRelativeTo(None)
        self.setVisible(True)

    def onChanged(self, e):

        sender = e.getSource()

        if not e.getValueIsAdjusting():
            name = sender.getSelectedValue()
            font = Font(name, Font.PLAIN, 13)
            self.label.setFont(font)


if __name__ == '__main__':
    Example()

In our example, we will display a JList and a JLabel components. The list component contains a list of all available font family names on our system. If we select an item from the list, the label will be displayed in a font, we have chosen.

ge = GraphicsEnvironment.getLocalGraphicsEnvironment()
fonts = ge.getAvailableFontFamilyNames()

Here we obtain all possible font family names on our system.

list = JList(fonts, valueChanged=self.onChanged)

We create an instance of the JList component. If we select an option from the list, the onChanged() method is called.

if not e.getValueIsAdjusting():

Events in list selection are grouped. We receive events for both selecting and deselecting. To filter only the selecting events, we use the getValueIsAdjusting() method.

name = sender.getSelectedValue()
font = Font(name, Font.PLAIN, 13)
self.label.setFont(font)

We get the selected item and set a new font for the label.

pane = JScrollPane()
pane.getViewport().add(list)

JList component is not scrollable by default. We put the list into the JScrollPane to make it scrollable.

JList component
Figure: JList component

In this part of the Jython Swing tutorial, we have presented several Swing components.