Layout management
In this part of the JRuby Swing programming tutorial, we will introduce layout managers.
When we design the GUI of our application, we decide what components we will use and how we will organize those components in the application. To organize our components, we use specialized non visible objects called layout managers. The Swing toolkit has two kind of components. Containers and children. The containers group children into suitable layouts. To create layouts, we use layout managers.
Absolute positioning
In most cases, programmers should use layout managers. There are a few situations, where we can use absolute positioning. In absolute positioning, the programmer specifies the position and the size of each component in pixels. The size and the position of a component do not change, if you resize a window. Applications look different on various platforms, and what looks OK on Linux, might not look OK on Mac. Changing fonts in your application might spoil the layout. If you translate your application into another language, you must redo your layout. For all these issues, use the absolute positioning only when you have a reason to do so.
#!/usr/local/bin/jruby
# ZetCode JRuby Swing tutorial
#
# In this program, we lay out three images
# using absolute positioning.
#
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010
include Java
import java.awt.Color
import javax.swing.ImageIcon
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.JFrame
class Example < JFrame
def initialize
super "Absolute"
self.initUI
end
def initUI
panel = JPanel.new
panel.setLayout nil
panel.setBackground Color.new 66, 66, 66
self.getContentPane.add panel
rot = ImageIcon.new "rotunda.jpg"
rotLabel = JLabel.new rot
rotLabel.setBounds 20, 20, rot.getIconWidth, rot.getIconHeight
min = ImageIcon.new "mincol.jpg"
minLabel = JLabel.new min
minLabel.setBounds 40, 160, min.getIconWidth, min.getIconHeight
bar = ImageIcon.new "bardejov.jpg"
barLabel = JLabel.new bar
barLabel.setBounds 170, 50, bar.getIconWidth, bar.getIconHeight
panel.add rotLabel
panel.add minLabel
panel.add barLabel
self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
self.setSize 350, 300
self.setLocationRelativeTo nil
self.setVisible true
end
end
Example.new
In this example, we show three images using absolute positioning.
panel.setLayout nil
Containers in Swing already have a default layout manager. JPanel
has a FlowLayout manager as its default layout manager.
We use the setLayout method with a nil parameter to remove
the default layout manager and use
absolute positioning instead.
rot = ImageIcon.new "rotunda.jpg" rotLabel = JLabel.new rot rotLabel.setBounds 20, 20, rot.getIconWidth, rot.getIconHeight
We create an ImageIcon object. We put the icon into the JLabel
component to display it. Then we use the setBounds method to
position the label on the panel. The first two parameters are the x, y positions
of the label. The 3th and 4th parameters are the width and the height of the icon.
panel.add rotLabel
We add the label to the panel container.
Buttons example
In the following example, we will position two buttons in the bottom right corner of the window.
#!/usr/local/bin/jruby
# ZetCode JRuby Swing tutorial
#
# In this program, we use the BoxLayout
# manager to position two buttons in the
# bottom right corner of the window.
#
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010
include Java
import java.awt.Dimension
import javax.swing.JButton
import javax.swing.JPanel
import javax.swing.JFrame
import javax.swing.BoxLayout
import javax.swing.Box
class Example < JFrame
def initialize
super "Buttons"
self.initUI
end
def initUI
basic = JPanel.new
basic.setLayout BoxLayout.new basic, BoxLayout::Y_AXIS
self.add basic
basic.add Box.createVerticalGlue
bottom = JPanel.new
bottom.setLayout BoxLayout.new bottom, BoxLayout::X_AXIS
bottom.setAlignmentX 1.0
okButton = JButton.new "OK"
closeButton = JButton.new "Close"
bottom.add okButton
bottom.add Box.createRigidArea Dimension.new 5, 0
bottom.add closeButton
bottom.add Box.createRigidArea Dimension.new 15, 0
basic.add bottom
basic.add Box.createRigidArea Dimension.new 0, 15
self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
self.setSize 300, 200
self.setLocationRelativeTo nil
self.setVisible true
end
end
Example.new
We will create two panels. The basic panel has a vertical box layout. The bottom panel has a horizontal one. We will put a bottom panel into the basic panel. We will right align the bottom panel. The space between the top of the window and the bottom panel is expandable. It is done by the vertical glue.
basic = JPanel.new basic.setLayout BoxLayout.new basic, BoxLayout::Y_AXIS ... bottom = JPanel.new bottom.setLayout BoxLayout.new bottom, BoxLayout::X_AXIS
The basic panel has a vertical box layout. The bottom panel has a horizontal box layout.
bottom.setAlignmentX 1.0
The bottom panel is right aligned.
basic.add Box.createVerticalGlue
We create a vertical glue. The glue is vertically expandable white space, which will push the horizontal box with the buttons to the bottom.
okButton = JButton.new "OK" closeButton = JButton.new "Close"
These are the two buttons, that will go into the bottom right corner of the window.
bottom.add okButton bottom.add Box.createRigidArea Dimension.new 5, 0
We put the OK button into the horizontal box. We put some rigid space next to the button. So that there is some space between the two buttons.
basic.add Box.createRigidArea Dimension.new 0, 15
We put some space between the buttons and the border of the window.
Windows example
The following example creates the windows dialog using the
GroupLayout manager. The dialog comes from
the JDeveloper application.
The GroupLayout manager divides the creation of the layout into two
steps. In one step, we lay out components alongside the horizontal axis. In
the second step, we lay out components along the vertical axis. This is an
unusual idea within layout managers, but it works well.
There are two types of arrangements. Sequential and parallel. 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.
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
is called a parallel group. You must understand these definitions right in
order to work with the GroupLayout manager.
#!/usr/local/bin/jruby
# ZetCode JRuby Swing tutorial
#
# In this program, GroupLayout
# manager to create a Windows
# example.
#
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010
include Java
import java.awt.Dimension
import java.awt.Color
import javax.swing.JButton
import javax.swing.SwingConstants
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JTextArea
import javax.swing.BorderFactory
import javax.swing.GroupLayout
class Example < JFrame
def initialize
super "Windows"
self.initUI
end
def initUI
layout = GroupLayout.new self.getContentPane
self.getContentPane.setLayout layout
layout.setAutoCreateGaps true
layout.setAutoCreateContainerGaps true
self.setPreferredSize Dimension.new 350, 300
windows = JLabel.new "Windows"
area = JTextArea.new
area.setEditable false
area.setBorder BorderFactory.createLineBorder Color.gray
activateButton = JButton.new "Activate"
closeButton = JButton.new "Close"
helpButton = JButton.new "Help"
okButton = JButton.new "OK"
sg = layout.createSequentialGroup
pg1 = layout.createParallelGroup
pg2 = layout.createParallelGroup
pg1.addComponent windows
pg1.addComponent area
pg1.addComponent helpButton
sg.addGroup pg1
pg2.addComponent activateButton
pg2.addComponent closeButton
pg2.addComponent okButton
sg.addGroup pg2
layout.setHorizontalGroup sg
sg1 = layout.createSequentialGroup
sg2 = layout.createSequentialGroup
pg1 = layout.createParallelGroup
pg2 = layout.createParallelGroup
sg1.addComponent windows
pg1.addComponent area
sg2.addComponent activateButton
sg2.addComponent closeButton
pg1.addGroup sg2
sg1.addGroup pg1
pg2.addComponent helpButton
pg2.addComponent okButton
sg1.addGroup pg2
layout.setVerticalGroup sg1
layout.linkSize SwingConstants::HORIZONTAL,
okButton, helpButton, closeButton, activateButton
self.pack
self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
self.setLocationRelativeTo nil
self.setVisible true
end
end
Example.new
We use GroupLayout manager to create a layout
which consists of six components. Groups of components are formed
along both axes.
sg = layout.createSequentialGroup pg1 = layout.createParallelGroup pg2 = layout.createParallelGroup pg1.addComponent windows pg1.addComponent area pg1.addComponent helpButton sg.addGroup pg1 pg2.addComponent activateButton pg2.addComponent closeButton pg2.addComponent okButton sg.addGroup pg2 layout.setHorizontalGroup sg
In the first step, we have a horizontal layout. It consists of two parallel groups of three components.
sg1 = layout.createSequentialGroup sg2 = layout.createSequentialGroup pg1 = layout.createParallelGroup pg2 = layout.createParallelGroup sg1.addComponent windows pg1.addComponent area sg2.addComponent activateButton sg2.addComponent closeButton pg1.addGroup sg2 sg1.addGroup pg1 pg2.addComponent helpButton pg2.addComponent okButton sg1.addGroup pg2 layout.setVerticalGroup sg1
Vertical layout is a bit more complex. First, we add a single component. Then we add a parallel group of a single component and a sequential group of two components. Finally, we add a parallel group of two components.
layout.linkSize SwingConstants::HORIZONTAL,
okButton, helpButton, closeButton, activateButton
This code makes all buttons the same size. We only need to set their width, because their height is already the same by default.
Look at the screenshot of the example. Notice, that components can be grouped
into vertical and horizontal sets of components. For example, the label, the area
and the Help button components can form a vertical group of components. This is exactly
what the GroupLayout manager does. It lays out components by
forming vertical and horizontal groups of components.
In this part of the JRuby Swing tutorial, we mentioned layout management of components.