布局管理器
为了跨平台java引入了布局管理器来管理界面,JAVA一共有6种布局管理器,下面是介绍
BorderLayout
界面分东西南北中5个方向,最多只能显示5个控件,默认放入中间,下面的程序将panel和panel2放在了中间和南边。放在中间的空间大小默认有内容大小为剩余的部分,不可设置。就如下面的程序,不能设置panel2的大小
this.getContentPane().add(panel,BorderLayout.SOUTH);
this.getContentPane().add(panel2,BorderLayout.CENTER);
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BorderFrame extends JFrame{
JButton btOK = new JButton("OK");
JButton btNO = new JButton("NO");
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JPanel panel2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
public BorderFrame(){
this.getContentPane().add(panel,BorderLayout.SOUTH);
this.getContentPane().add(panel2,BorderLayout.CENTER);
panel2.setBackground(Color.black);
panel2.setSize(100,200);
this.setBackground(Color.red);
panel.add(btOK);
panel.add(btNO);
panel.setBackground(Color.blue);
this.setSize(300,200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
BorderFrame frame = new BorderFrame();
}
}
FlowLayout
看作行集,行高不能用setSize设置,由内容决定,可以设置左中右居,还有。就如上面的程序,panel不能设置大小,panel2也不能,之所有有这么大是因为发在了BorderLayout有东西填充。若将panel2放在上边,效果如下
this.getContentPane().add(panel2,BorderLayout.NORTH);
放在左边效果有如下 :
this.getContentPane().add(panel2,BorderLayout.WEST);
GridLayout
网格管理器,把容器的显示位置化格子,然后把控件放到等宽等高的格子,
GridLayout layout = new GridLayout(行数,列数);
// 当行数为0时,增加控件时会保持一个列的情况下随控件增长;列数为0时亦是如此。但不能同时为0
一个对话框例子
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import java.awt.event.*;
public class LoginDialogDemo extends JFrame {
JButton button = new JButton("Click Me");
JPanel panel = new JPanel(new FlowLayout());
public LoginDialogDemo(){
final JFrame frame = this;
// BorderLayout管理器
this.getContentPane().add(panel, BorderLayout.SOUTH);
panel.add(button);
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
showLoginDialog(frame);
}
});
this.setSize(400,200);
this.setTitle("显示登陆对话框");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
void showLoginDialog(JFrame frame){
// gridLayout自增
JPanel p = new JPanel(new GridLayout(0,1));
JTextField tfUserName = new JTextField();
JPasswordField tfPassword = new JPasswordField();
p.add(new JLabel("Username:"));
p.add(tfUserName);
p.add(new JLabel("Password:"));
p.add(tfPassword);
if(JOptionPane.showConfirmDialog(frame,
p,
"Login",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE)==
JOptionPane.OK_OPTION){
System.out.println("User Name:"+tfUserName.getText());
System.out.println("Password:"+new String(tfPassword.getName()));
}
}
public static void main(String[] args){
LoginDialogDemo frame = new LoginDialogDemo();
}
}
BoxLayout
允许控件按X/Y抽摆放。
public BoxLayout(Container target,int axis)
// target表示当前管理的容器,若为this则管理自己所在的容器
import java.awt.TextArea;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class BoxLayoutFrame extends JFrame{
BoxLayoutTest panel = new BoxLayoutTest();
public BoxLayoutFrame(){
this.getContentPane().add(panel);
this.setSize(500,500);
this.setTitle("测试界面布局");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
BoxLayoutFrame frame = new BoxLayoutFrame();
}
}
class BoxLayoutTest extends JPanel{
BoxLayoutTest(){
//set the layout to a X-axis BoxLayout
setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
//Create three components
JTextField textField = new JTextField(); //单行文本输入框
// JTextArea构造具有指定行数和列数的新的空 TextArea。
TextArea textArea = new TextArea(4,20);
JButton button = new JButton("this is a Button");
//add the three components to the BoxLayouts
add(new JLabel("TextField:"));
add(textField);
add(new JLabel("TextArea:"));
add(textArea);
add(new JLabel("button:"));
add(button);
}
}
CardLayout
CardLayout布局,某个界面像放动画一样贴换内容。比如实现一个界面内多个
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import java.awt.Panel;
import java.awt.event.*;
public class CardLayoutFrame extends JFrame {
JButton btnPrevious = new JButton("Previous");
JButton btnNext = new JButton("Next");
JPanel panelFlow = new JPanel(new FlowLayout());
JPanel panelCard = new JPanel(new CardLayout());
int currentIndex = 0;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CardLayoutFrame frame = new CardLayoutFrame();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public CardLayoutFrame() {
this.getContentPane().add(panelFlow, BorderLayout.SOUTH);
this.getContentPane().add(panelCard,BorderLayout.CENTER );
panelCard.add(createCard(1), "Card1");
panelCard.add(createCard(2), "Card2");
panelFlow.add(btnPrevious);
panelFlow.add(btnNext);
ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent e){
switchCard();
};
};
btnPrevious.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
switchCard();
};
});
btnNext.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
switchCard();
};
});
this.setSize(300,200);
this.setTitle("测试界面布局");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
// 生产卡片
JPanel createCard(int Index){
JPanel panel = new JPanel(new BorderLayout());
JLabel label = new JLabel("<html><h1 style = color:red>"+
"This is Panel"+ Index+"</h1></html>");
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label);
return panel;
}
void switchCard(){
CardLayout c1 = (CardLayout) panelCard.getLayout();
if(currentIndex == 0){
currentIndex ++;
c1.show(panelCard, "Card2");
}else{
currentIndex--;
c1.show(panelCard, "Card1");
}
}
}
GridBagLayout
每个加入容器的控件创建一个GridBagConstraints对象,下面分析这个对象的构造函数的参数
public GridBagConstraints(
int gridx,int gridy, //控件的位置,单位为网格
int gridwidth,int gridheight, // 组件占几列几行
double weightx,double weighty, // 水平和垂直拉伸权值
int anchor, // 停靠方向,默认CENTER,有NORTHEAST,EAST,SOUTHEAST,SOUTH,SOUTHWEST等
int fill, // 拉伸的方向,有NONE,HORIZONTAL,VERTICAL
insets insets(上,左,下,右), // 外部填充,填充的区域是组件与所处格子边框之间的部分。 当组件不能填满其格时,通过 insets来指定四周(即上下左右)所留空隙
int ipadx,ipady // 组件间的横纵向间距
)
一个单例使用实例
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class GridBagLayoutFrame extends JFrame {
JButton btnOK = new JButton("OK");
JButton btnCancel = new JButton("Cancel");
JPanel panelFlow = new JPanel(new FlowLayout());
JPanel panelGrid;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GridBagLayoutFrame frame = new GridBagLayoutFrame();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GridBagLayoutFrame() {
panelGrid = createPanelGridBag();
this.getContentPane().add(panelFlow, BorderLayout.SOUTH);
this.getContentPane().add(panelGrid,BorderLayout.CENTER);
panelFlow.add(btnOK);
panelFlow.add(btnCancel);
this.setTitle("测试界面");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack(); //窗口自适应组件大小
this.setVisible(true);
}
JPanel createPanelGridBag(){
JPanel panelGridBag = new JPanel(new GridBagLayout());
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JLabel label3 = new JLabel();
JLabel label4 = new JLabel();
JTextField textField1 = new JTextField();
JTextField textField2 = new JTextField();
JTextField textField3 = new JTextField();
JTextField textField4 = new JTextField();
label1.setText("User Name:");
label2.setText("Telephone:");
label3.setText("Address:");
label4.setText("Company:");
textField1.setText("Your Name");
textField2.setText("88888888");
textField3.setText("Shanghai,China");
textField4.setText("Your company");
// Insets(int top, int left, int bottom, int right)
// 创建并初始化具有指定顶部、左边、底部、右边 inset 的新 Insets 对象。
panelGridBag.add(label1,
new GridBagConstraints(0,0,1,1,0.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.NONE,
new Insets(45, 50, 0, 0),20,0
)
);
panelGridBag.add(label2,
new GridBagConstraints(0,1,1,1,0.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.NONE,
new Insets(34,50,0,0),20,0
)
);
panelGridBag.add(label3,
new GridBagConstraints(0,2,1,1,0.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.NONE,
new Insets(28,50,0,0),33,0
)
);
panelGridBag.add(label4,
new GridBagConstraints(0,3,1,1,0.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.NONE,
new Insets(28,50,50,0),26,0
)
);
panelGridBag.add(textField1,
new GridBagConstraints(1,0,1,1,1.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
new Insets(44,25,0,84),97,0
)
);
panelGridBag.add(textField2,
new GridBagConstraints(1,1,1,1,1.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
new Insets(31,25,0,84),97,0
)
);
panelGridBag.add(textField3,
new GridBagConstraints(1,2,1,1,1.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
new Insets(25,25,0,84),97,0
)
);
panelGridBag.add(textField4,
new GridBagConstraints(1,3,1,1,1.0,0.0,
GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
new Insets(26,25,50,84),97,0
)
);
return panelGridBag;
}
}
难点: weightx,weighty
在书上看到这两个值设为[0,1],然后自个好奇就随便调了几个值,结果UI依然不受影响,然后通过查阅才知道其实这两个值得取值无限制,只要合理即可,每个组件的这两个值还与其他因素有关。详细请看论文
java的拉伸作用规则:
1. 跨多个格子且是第一列(行)则作用于最右(下)边的格子;若非出现在第一行或列且weight为0,则作用于最右下格子,否则按比例值(某个x或y上所有某个weight占总weight的值)拉伸。
2. 拉伸值为0时不一定不能拉伸,只要所在行存在拉伸对象,就能跟着拉伸。
下面给出论文中的一个源码:
import java.awt.*;
import javax.swing.*;
public class DWPMessGrigBag extends JFrame {
JButton Ding,Wei,Ping,Exit,Help;
JLabel address,family;
JPanel panel;
JTextField textField,mousePosition;
JList familyList,addrList;
JTextArea textArea;
/**
* Create the frame.
*/
public DWPMessGrigBag() {
Ding = new JButton("丁");
Wei = new JButton("卫");
Help = new JButton("帮助");
Ping = new JButton("平");
family = new JLabel("丁家成员");
address = new JLabel("地址信息");
String[] str = {"丁卫平","张燕","丁培桓"};
String[] addstr = {"湖南","桃花","灰山港"};
textField = new JTextField();
textField.setBackground(Color.green);
mousePosition = new JTextField();
Exit = new JButton("退出");
familyList = new JList(str);
familyList.setBackground(Color.yellow);
addrList = new JList (addstr);
addrList.setBackground(Color.green);
textArea = new JTextArea();
textArea.setBackground(Color.lightGray.brighter());
GridBagLayout layout = new GridBagLayout();
this.setLayout(layout);
GridBagConstraints s = new GridBagConstraints();
s.fill = GridBagConstraints.BOTH;
s.gridwidth = 1;
s.weightx = 0;
s.weighty = 0;
layout.setConstraints(Ding,s);
layout.setConstraints(Wei,s);
layout.setConstraints(Ping,s);
s.gridx = 4;
s.gridy = 0;
layout.setConstraints(Help, s);
s.gridx = 0;
s.gridy = 1;
s.gridwidth = 2;
layout.setConstraints(family, s);
s.gridx = 2;
s.gridy = 1;
s.weightx = 13;
layout.setConstraints(textField, s);
s.gridx = 4;
s.gridwidth = 1;
s.weightx = 0;
layout.setConstraints(Exit, s);
s.gridx = 0;
s.gridy = 2;
s.gridwidth = 2;
s.weightx = 0;
s.weighty = 90;
layout.setConstraints(familyList, s);
s.gridx = 2;
s.gridheight = 4;
s.gridwidth = 3;
s.weightx = 31;
s.weighty = 44;
layout.setConstraints(textArea,s);
s.gridx = 0;
s.gridy = 3;
s.gridwidth = 2;
s.weightx = 0;
s.weighty = 0;
s.gridheight = 1;
layout.setConstraints(address, s);
s.gridy = 4;
s.weighty = 30;
layout.setConstraints(addrList, s);
s.weighty = 0;
s.gridy = 5;
layout.setConstraints(mousePosition, s);
this.add(Ding);
this.add(Wei);
this.add(Ping);
this.add(Help);
this.add(family);
this.add(textField);
this.add(Exit);
this.add(familyList);
this.add(textArea);
this.add(address);
this.add(addrList);
this.add(mousePosition);
this.setSize(600,600);
this.setVisible(true);
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
DWPMessGrigBag frame = new DWPMessGrigBag();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
参考:
《JAVA编程实践指南》,邵荣,清华大学出版社
GridBagLayout 以及 GridBagConstraints 用法
GridBagConstrains类成员weightx和weighty的使用方法研究