在 Jython Swing 编程教程的这一部分中,我们将介绍布局管理器。
在设计应用的 GUI 时,我们决定要使用哪些组件以及如何在应用中组织这些组件。 为了组织我们的组件,我们使用专门的不可见对象,称为布局管理器。 Swing 工具箱包含两种组件:容器和子组件。 容器将子项分组为合适的布局。 要创建布局,我们使用布局管理器。
绝对定位
在大多数情况下,程序员应使用布局管理器。 在某些情况下,我们可以使用绝对定位。 在绝对定位中,程序员以像素为单位指定每个小部件的位置和大小。 如果我们调整窗口大小,则小部件的大小和位置不会改变。 在各种平台上,应用看起来都不同,在 Linux 上看起来不错,在 Mac OS 上看起来不太正常。 在应用中更改字体可能会破坏布局。 如果将应用翻译成另一种语言,则必须重做布局。 对于所有这些问题,仅在有理由时才使用绝对定位。
#!/usr/local/bin/jython# -*- coding: utf-8 -*-"""ZetCode Jython Swing tutorialIn this program, we lay out widgetsusing absolute positioningauthor: Jan Bodnarwebsite: www.zetcode.comlast modified: November 2010"""from java.awt import Colorfrom javax.swing import ImageIconfrom javax.swing import JFramefrom javax.swing import JPanelfrom javax.swing import JLabelclass Example(JFrame):def __init__(self):super(Example, self).__init__()self.initUI()def initUI(self):panel = JPanel()panel.setLayout(None)panel.setBackground(Color(66, 66, 66))self.getContentPane().add(panel)rot = ImageIcon("rotunda.jpg")rotLabel = JLabel(rot)rotLabel.setBounds(20, 20, rot.getIconWidth(), rot.getIconHeight())min = ImageIcon("mincol.jpg")minLabel = JLabel(min)minLabel.setBounds(40, 160, min.getIconWidth(), min.getIconHeight())bar = ImageIcon("bardejov.jpg")barLabel = JLabel(bar)barLabel.setBounds(170, 50, bar.getIconWidth(), bar.getIconHeight())panel.add(rotLabel)panel.add(minLabel)panel.add(barLabel)self.setTitle("Absolute")self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)self.setSize(350, 300)self.setLocationRelativeTo(None)self.setVisible(True)if __name__ == '__main__':Example()
在此示例中,我们使用绝对定位显示了三幅图像。
panel.setLayout(None)
Swing 中的容器已经具有默认的布局管理器。 JPanel具有FlowLayout管理器作为其默认布局管理器。 我们将setLayout()方法与无参数一起使用,以删除默认的布局管理器,而改用绝对定位。
rot = ImageIcon("rotunda.jpg")rotLabel = JLabel(rot)rotLabel.setBounds(20, 20, rot.getIconWidth(), rot.getIconHeight())
我们创建一个ImageIcon对象。 我们将图标放入JLabel组件中以显示它。 然后,我们使用setBounds()方法将标签放置在面板上。 前两个参数是标签的 x,y 位置。 第 3 和第 4 个参数是图标的宽度和高度。
panel.add(rotLabel)
我们将标签添加到面板容器中。

图:绝对定位
按钮示例
在下面的示例中,我们将在窗口的右下角放置两个按钮。
#!/usr/local/bin/jython# -*- coding: utf-8 -*-"""ZetCode Jython Swing tutorialIn this program, use box layoutsto position two buttons in thebottom right corner of the windowauthor: Jan Bodnarwebsite: www.zetcode.comlast modified: November 2010"""from java.awt import Dimensionfrom javax.swing import JButtonfrom javax.swing import JFramefrom javax.swing import JPanelfrom javax.swing import BoxLayoutfrom javax.swing import Boxclass Example(JFrame):def __init__(self):super(Example, self).__init__()self.initUI()def initUI(self):basic = JPanel()basic.setLayout(BoxLayout(basic, BoxLayout.Y_AXIS))self.add(basic)basic.add(Box.createVerticalGlue())bottom = JPanel()bottom.setAlignmentX(1.0)bottom.setLayout(BoxLayout(bottom, BoxLayout.X_AXIS))okButton = JButton("OK")closeButton = JButton("Close")bottom.add(okButton)bottom.add(Box.createRigidArea(Dimension(5, 0)))bottom.add(closeButton)bottom.add(Box.createRigidArea(Dimension(15, 0)))basic.add(bottom)basic.add(Box.createRigidArea(Dimension(0, 15)))self.setTitle("Buttons")self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)self.setSize(300, 150)self.setLocationRelativeTo(None)self.setVisible(True)if __name__ == '__main__':Example()
我们将创建两个面板。 基本面板具有垂直框布局。 底部面板有一个水平面板。 我们将在基础面板中放置一个底部面板。 我们将右对齐底部面板。 窗口顶部和底部面板之间的空间是可扩展的。 这是通过垂直胶水完成的。
basic = JPanel()basic.setLayout(BoxLayout(basic, BoxLayout.Y_AXIS))...bottom = JPanel()...bottom.setLayout(BoxLayout(bottom, BoxLayout.X_AXIS))
基本面板具有垂直框布局。 底部面板具有水平框布局。
bottom.setAlignmentX(1.0)
底部面板右对齐。
basic.add(Box.createVerticalGlue())
我们创建一个垂直胶水。 胶水是垂直可扩展的白色空间,它将带有按钮的水平框推到底部。
okButton = JButton("OK")closeButton = JButton("Close")
这是两个将进入窗口右下角的按钮。
bottom.add(okButton)bottom.add(Box.createRigidArea(Dimension(5, 0)))
我们将“确定”按钮放入水平框中。 我们在按钮旁边放置了一些刚性空间。 这样两个按钮之间会有一些空间。
basic.add(Box.createRigidArea(Dimension(0, 15)))
我们在按钮和窗口的边框之间留出一些空间。

图:按钮示例
Windows 示例
以下示例使用GroupLayout管理器创建 Windows 对话框。 该对话框来自 JDeveloper 应用。
GroupLayout管理器将布局的创建分为两个步骤。 第一步,我们沿着水平轴布置组件。 在第二步中,我们沿垂直轴布置组件。 这在布局管理器中是一个不寻常的想法,但效果很好。
有两种类型的安排:顺序安排和并行安排。 在两种布局中,我们都可以顺序或并行排列组件。 在水平布局中,一行组件称为顺序组。 一列组件称为并行组。 在垂直布局中,一列组件称为顺序组。 一排组件称为并行组。 您必须正确理解这些定义才能与GroupLayout管理器一起使用。
#!/usr/local/bin/jython# -*- coding: utf-8 -*-"""ZetCode Jython Swing tutorialThis code lays out componentsusing the GroupLayout managerauthor: Jan Bodnarwebsite: www.zetcode.comlast modified: November 2010"""from java.awt import Dimensionfrom java.awt import Colorfrom javax.swing import JButtonfrom javax.swing import SwingConstantsfrom javax.swing import JFramefrom javax.swing import JLabelfrom javax.swing import JTextAreafrom javax.swing import BorderFactoryfrom javax.swing import GroupLayoutclass Example(JFrame):def __init__(self):super(Example, self).__init__()self.initUI()def initUI(self):layout = GroupLayout(self.getContentPane())self.getContentPane().setLayout(layout)layout.setAutoCreateGaps(True)layout.setAutoCreateContainerGaps(True)self.setPreferredSize(Dimension(350, 300))windows = JLabel("Windows")area = JTextArea()area.setEditable(False)area.setBorder(BorderFactory.createLineBorder(Color.gray))activate = JButton("Activate")close = JButton("Close")help = JButton("Help")ok = JButton("OK")layout.setHorizontalGroup(layout.createSequentialGroup().addGroup(layout.createParallelGroup().addComponent(windows).addComponent(area).addComponent(help)).addGroup(layout.createParallelGroup().addComponent(activate).addComponent(close).addComponent(ok)))layout.setVerticalGroup(layout.createSequentialGroup().addComponent(windows).addGroup(layout.createParallelGroup().addComponent(area).addGroup(layout.createSequentialGroup().addComponent(activate).addComponent(close))).addGroup(layout.createParallelGroup().addComponent(help).addComponent(ok)))layout.linkSize(SwingConstants.HORIZONTAL, [ok, help, close, activate])self.pack()self.setTitle("Windows")self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)self.setLocationRelativeTo(None)self.setVisible(True)if __name__ == '__main__':Example()
在上面的示例中,我们看到了addComponent()方法的链式调用。 这是可能的,因为addComponent()方法返回了调用它的组。 因此,我们不需要局部变量来保存组。 另请注意,代码已适当缩进以提高可读性。
layout.setHorizontalGroup(layout.createSequentialGroup().addGroup(layout.createParallelGroup().addComponent(windows).addComponent(area).addComponent(help)).addGroup(layout.createParallelGroup().addComponent(activate).addComponent(close).addComponent(ok)))
第一步,我们有一个水平布局。 它由两组平行的三个部分组成。
layout.setVerticalGroup(layout.createSequentialGroup().addComponent(windows).addGroup(layout.createParallelGroup().addComponent(area).addGroup(layout.createSequentialGroup().addComponent(activate).addComponent(close))).addGroup(layout.createParallelGroup().addComponent(help).addComponent(ok)))
垂直布局有点复杂。 首先,我们添加一个组件。 然后,我们添加一个包含单个组件的并行组和一个包含两个组件的顺序组。 最后,我们添加两个组件的并行组。
layout.linkSize(SwingConstants.HORIZONTAL, [ok, help, close, activate])
此行使所有按钮的大小相同。 我们只需要设置它们的宽度,因为默认情况下它们的高度已经相同。

图:窗口示例
查看示例的屏幕截图。 注意,可以将组件分为垂直和水平组件集。 例如,标签区域和“帮助”按钮组件可以形成垂直的组件组。 这正是GroupLayout管理器所做的。 它通过形成组件的垂直和水平组来布局组件。
在 Jython Swing 教程的这一部分中,我们提到了小部件的布局管理。
