Swing图形界面之布局
Swing常用容器
AWT
和Swing
都提供了容器。Swing是在AWT基础上引入的成分,并且比AWT功能上强。这里我们说一些常用的容器。
框架
JFrame
是一种独立存在的容器,是Frame
类的子类,他的对象包含边框。他的构造函数如下:
- public JFrame()
是创建一个框架。
- public JFrame(String title)
是创建一个带标题的框架。
通过
Swing
创建的框架一开始是不可见的,必须调用Window
类的show()
方法或Component
类的setVisible()
方法来显示框架。
例如定义一个JFrame
子类:
import javax.swing.*;
class subJFrame extends JFrame{
public subJFrame(){}
public subJFrame(String title){
super(title);
}
protected void frameInit(){
super.frameInit();
// shut down the Frame
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
需要注意的是我们点击窗口(框架)上的关闭按钮时,并不会关闭程序,需要自己写代码来实现关闭窗口
setDefaultCloseOperation(EXIT_ON_CLOSE)
# 并且我们把这段代码创建单独的subJFrame.java
文件。以后需要每次使用,并且要放在同一个package
中。
布局管理器
为了保持GUI程序的平台独立性,也为了使基本组件的排列更加有规范,Java提供了布局管理器来完成这个任务。
FlowLayout布局
该布局将组件按加入的先后顺序从左至右排列,一行满了换行继续排。默认下,将组件放置在每行中央居中显示。对齐方式有三种:
- align 对齐方式
- hor 水平间隔
- ver 垂直间隔
该布局的构造函数如下:
- public FlowLayout()
生成一个默认对象,居中对齐,垂直和水平间隔为5。
- public FlowLayout(int align)
生成指定对齐方式的对象,垂直和水平间隔为5。
- public FlowLayout(int align, int hor, int ver)
生成指定对齐方式,垂直和水平间隔的对象。
实验效果
import java.awt.*;
import javax.swing.*;
public class FlowLayoutTest {
JFrame frame;
Container contentPane;
JPanel jp;
FlowLayout layout;
public static void main(String[] AUG){
FlowLayoutTest obj = new FlowLayoutTest();
obj.testFlow();
obj.changeAlign();
}
private void changeAlign() {
for (int i = 0; i < 100; i++) {
try{
Thread.sleep(500); // Freshing layout every 0.5s
}catch(Exception e){
e.printStackTrace();
}
switch (i % 3){
case 0:
layout.setAlignment(FlowLayout.LEFT);
break;
case 1:
layout.setAlignment(FlowLayout.CENTER);
break;
case 2:
layout.setAlignment(FlowLayout.RIGHT);
break;
}
layout.layoutContainer(contentPane);
}
}
private void testFlow() {
frame = new subJFrame("FlowLayoutTest");
contentPane = frame.getContentPane();
jp = new JPanel();
layout = new FlowLayout();
fillComponent(jp);
contentPane.add(jp);
layout = new FlowLayout(FlowLayout.CENTER, 20, 50);
contentPane.setLayout(layout);
frame.setSize(400, 200);
frame.setVisible(true);
}
private static void fillComponent(Container c) {
for (int i = 0; i < 3; i++) {
c.add(new JButton("Button" + i));
}
}
}
运行实例:
BorderLayout布局
该布局通过划分空间(即窗口)来将组件添加至里面,划分为东、南、西、北、中6个方位。当窗口缩放时,中间的组件缩放变化最大,其他组件只是在需要时改变来填充窗口。
同样,该布局构造函数如下:
- public BorderLayout()
生成默认对象,其中组件垂直和水平间隔为0.
- public BorderLayout(int hgap, int vgap)
生成指定组件的垂直和水平间隔的对象。
需要注意的是,放入窗口时,需要指定组件的方位,如
add(position, object)
实验效果
import java.awt.*;
import javax.swing.*;
public class BorderLayoutTest {
JFrame frame;
Container contentPanel;
BorderLayout layout;
JButton buttons[];
String names[] = {"North", "South", "East", "West", "Center"};
private void fillComponent(Container c){
buttons = new JButton[names.length];
for (int i = 0; i < names.length; i++) {
buttons[i] = new JButton(names[i]);
}
// add Buttons to the position.
c.add(buttons[0], BorderLayout.NORTH);
c.add(buttons[1], BorderLayout.SOUTH);
c.add(buttons[2], BorderLayout.WEST);
c.add(buttons[3], BorderLayout.EAST);
c.add(buttons[4], BorderLayout.CENTER);
}
public void testBorder(){
frame = new subJFrame("BorderLayoutTest");
contentPanel = frame.getContentPane();
layout = new BorderLayout(5, 5);
contentPanel.setLayout(layout);
fillComponent(contentPanel);
frame.setSize(600, 400);
frame.setVisible(true);
}
public void hidenButton(){
for (int i = 0; i < names.length; i++) {
try{
Thread.sleep(500); // Freshing layout every 0.5s
}catch(Exception e){
e.printStackTrace();
}
buttons[i].setVisible(false);
layout.layoutContainer(contentPanel);
}
}
public void showButton(){
for (int i = names.length-1; i >= 0; i--) {
try{
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
buttons[i].setVisible(true);
layout.layoutContainer(contentPanel);
}
}
public static void main(String[] AUG){
BorderLayoutTest obj = new BorderLayoutTest();
obj.testBorder();
while(true) {
obj.hidenButton();
obj.showButton();
}
}
}
运行实例:
GridLayout布局
该容器将容器空间划分为网格状,各组件占据大小相同的区域。其构造函数如下:
- public GridLayout()
生成默认的对象,行数为1。
- public GridLayout(int rows, int cols)
生成指定行数和列数的对象。
- public GridLayout(int rows, int cols, int hgap, int vgap)
生成指定行数、列数、水平和垂直间隔的对象。
在填写rows或者cols时,当其中一项为0时,表示任意数量的行或列。但两者不能同时为0
实验效果
import java.awt.*;
import javax.swing.*;
public class GridLayoutTest {
JFrame frame;
Container contentPane;
GridLayout grid_1, grid_2;
JButton buttons[];
String names[] = {"One", "Two", "Three", "Four", "Five", " Six"};
boolean change; // setting a signal
public GridLayoutTest(){
frame = new subJFrame("GridLayoutTest");
contentPane = frame.getContentPane();
// setting a 2 rows and 3 clos layout
grid_1 = new GridLayout(2,3,5,5);
// setting a 3 rows and 2 clos layout
grid_2 = new GridLayout(3,2);
contentPane.setLayout(grid_1);
fillComponent(contentPane);
change = true;
frame.setSize(500, 400);
frame.setVisible(true);
}
private void fillComponent(Container c){
buttons = new JButton[names.length];
for (int i = 0; i < names.length; i++) {
buttons[i] = new JButton(names[i]);
c.add(buttons[i]);
}
}
public void GridTest(){
while(true){
try{
Thread.sleep(500); // Freshing layout every 0.5s
}catch(Exception e){
e.printStackTrace();
}
if(change){
contentPane.setLayout(grid_1);
}else{
contentPane.setLayout(grid_2);
}
change = !change; // Reverse signal
contentPane.validate(); // Make the changed layout effective
}
}
public static void main(String[] AUG) {
GridLayoutTest obj = new GridLayoutTest();
obj.GridTest();
}
}
运行实例:
CardLayout布局
有时候需要多种组件,但限于屏幕大小有限,不能同时显示,那就把组件分为组,每组放在一个面板中,按照该布局的方式放置在窗口中。这样窗口的同一显示区放置多个不同组件,而每一刻只显示其中一组。但该组件比较复杂。
1. 创建一个布局对象和一个承载该对象的面板。
2. 采用该对象设置面板的布局管理器。
3. 调用 add()
方法将组件添加到面板对象中。
其常用方法如下:
- public CardLayout()
生成默认对象,各卡片之间垂直和水平间隔为0
- public CardLayout(int hgap, int vgap)
生成指定卡片之间的垂直和水平间隔的对象
- public void first(Container parent)
显示第一张卡片
- public void last(Container parent)
显示最后一张卡片
- public void next(Container parent)
显示下一张卡片(可循环)
- public void previous(Container parent)
显示前一张卡片(可循环)
实验效果
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardLayoutTest implements ActionListener{
Frame frame;
Container contentPanel;
JPanel deck;
CardLayout cardManager;
JButton buttons[];
String names[] = {"First", "Next", "Previous", "Last"};
public CardLayoutTest(){
frame = new subJFrame("CardLayoutTest");
contentPanel = ((subJFrame) frame).getContentPane();
deck = new JPanel();
cardManager = new CardLayout(); // define a layout manager
deck.setLayout(cardManager); // setting a layout of content
// setting card_1
JPanel card_1 = new JPanel();
JLabel lab_1 = new JLabel("No.1 Card");
card_1.add(lab_1);
deck.add(card_1, lab_1.getText());
// setting card_2
JPanel card_2 = new JPanel();
JTextField field = new JTextField("No.2 Card");
card_2.add(field);
deck.add(card_2, field.getText());
// setting card_3
JPanel card_3 = new JPanel();
JLabel lab_3 = new JLabel("No.3 Card");
card_3.setLayout(new BorderLayout());
card_3.add(new JButton("North"), BorderLayout.NORTH);
card_3.add(new JButton("South"), BorderLayout.SOUTH);
card_3.add(new JButton("West"), BorderLayout.WEST);
card_3.add(new JButton("East"), BorderLayout.EAST);
card_3.add(lab_3, BorderLayout.CENTER);
deck.add(card_3, lab_3.getText());
// setting controlPanel
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(2, 2));
buttons = new JButton[names.length];
for (int i = 0; i < names.length; i++) {
buttons[i] = new JButton(names[i]);
buttons[i].addActionListener(this);
controls.add(buttons[i]);
}
// add to the deck
contentPanel.add(controls, BorderLayout.WEST);
contentPanel.add(deck, BorderLayout.EAST);
frame.setSize(600, 400);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == buttons[0]) // show the first card
cardManager.first(deck);
else if(e.getSource() == buttons[1]) // show the next card
cardManager.next(deck);
else if(e.getSource() == buttons[2]) // show the previous card
cardManager.previous(deck);
else if(e.getSource() == buttons[3]) // show the last card
cardManager.last(deck);
}
public static void main(String[] AUG) {
new CardLayoutTest();
}
}
运行实例:
你们看到这里说明那你是个优秀的读者,你能仔细看完,那就是你的财富。
叨叨几句... NOTHING