【java】浅析java组件中的布局管理器
这篇博文笔者介绍一下java组件中,常用的布局管理器。java组件中的布局方式有好几十种,所有的这些布局管理器都实现了java.awt.LayoutManager接口。接下来笔者介绍一下常用的5种布局管理器,FlowLayout、BorderLayout、GridLayout、GridBagLayout、CardLayout、BoxLayout。如果不希望使用布局管理器,可以调用组件的 setLayout(null); ,但是不建议设置layout为null,因为这样就失去了跨平台特性,和java的设计理念相违背。
1.FlowLayout
FlowLayout流式布局管理器,组件像水流一样向某方向流动(排列),遇到障碍(边界)就折回,重头开始排列。在默认情况下,FlowLayout布局管理器从左向右排列所有组件,遇到边界就会折回下一行重新开始。
在电脑上输入一篇文章时,所使用的就是FlowLayout布局管理器,所有的文字默认从左向右排列,遇到边界就会折回下一行重新开始。AWT中的FlowLayout布局管理器于此完全类似,只是此时排列的是AWT组件,而不是文字。
JPanel组件默认使用的就是FlowLayout。
FlowLayout组件中有三个静态常量,分别为FlowLayout.LEFT、FlowLayout.CENTER、FlowLayout.RIGHT,分别表明FlowLayout中组件的排列方向为从左向右排列、从中间向两边排列、从右边向左边排列。
JFrame f=new JFrame("测试窗口");
//JFrame容器默认使用BorderLayout布局管理器
//设置JFrame容器使用FlowLayout布局管理器,从左向右排列,水平间距为20,垂直间距为5
f.setLayout(new FlowLayout(FlowLayout.LEFT,20,5));
for(int i=0;i<10;i++){
f.add(new JButton("按钮"+i));
}
f.pack();
f.setVisible(true);
2.BorderLayout
BorderLayout将组件分为EAST、SOUTH、WEST、NORTH、CENTER 五个区域,普通组件可以被放置在这五个区域中的任何一个。
当改变BorderLayout的容器大小时,NORTH、SOUTH和CENTER区域水平调整,而EAST、WEST和CENTER区域垂直调整。
常见的组件JFrame,JDialog,JScrollPanl默认使用的就是BorderLayout,使用BorderLayout需要注意如下两点:
1.当向使用BorderLayout布局管理器的容器中添加组件时,需要指定要添加到那个区域中。如果没有指定添加到那个区域中,则默认添加到中间区域。
2.如果向某个区域添加多个组件的话,后放入的组件会覆盖先放入的组件,在实际情况中,可以放入一个JPanel组件,然后再在JPanel组件中放入其它组件。
JFrame f=new JFrame("测试窗口");
//设置为BorderLayout,水平间距30,垂直间距为5
f.setLayout(new BorderLayout(30,5));
f.add(new JButton("WEST"),BorderLayout.WEST);
f.add(new JButton("EAST"),BorderLayout.EAST);
f.add(new JButton("NORTH"),BorderLayout.NORTH);
f.add(new JButton("SOUTH"),BorderLayout.SOUTH);
f.add(new JButton("CENTER"),BorderLayout.CENTER);
//f.add(new JButton("CENTER")); f.pack();
f.setVisible(true);
3.GridLayout
GridLayout网格布局管理器,该布局管理器将容器分割成纵横线分隔的网格,每个网格所占的区域大小相同。当向使用GridLayout布局管理器的容器中添加组件时,默认从左向右、从上往下依次添加到每个网格中。
JFrame f=new JFrame("窗口测试");
f.setLayout(new BorderLayout()); JPanel p1=new JPanel();
p1.add(new JTextField(30));
f.add(p1,BorderLayout.NORTH); JPanel p2=new JPanel();
//设计JPanel使用GridLayout布局管理器,3行,5列,水平间距和垂直间距都为4
p2.setLayout(new GridLayout(3,5,4,4));
String[] names={"0","1","2","3","4",
"5","6","7","8","9",
"+","-","*","/","="};
//往JPanel中添加15个按钮
for(int i=0;i<15;i++){
p2.add(new JButton(names[i]));
}
f.add(p2);
f.pack();
f.setVisible(true);
4.GridBagLayout
GridBagLayout布局管理器功能最强大,但也最复杂,与GridLayout不同的是,在GridBagLayout布局管理器中,一个组件可以跨域一个或多个网格,并可以设置各网格的大小各不相同,从而增加了布局的灵活性。为了处理GridBagLayout中GUI组件的大小,跨域形,Java提供了GridBagConstraints对象,该对象与特定的GUI组件关联,用于控制GUI组件的大小、跨越性。
下面是使用GridBagLayout布局管理器的步骤:
1.创建GridBagLayout布局管理器,并且指定GUI容器使用该布局管理器
GridBagLayout gb=new GridBagLayout();
container.setLayout(gb);
2.创建GridBagConstraints对象,并且设置该对象的相关属性(用于设置该受该对象控制的GUI组件的大小、跨域形等)
gbc.gridx=2;//设置受该对象控制的GUI组件位于网格的横向索引
gbc.gridy=1;//设置受该对象控制的GUI组件位于网格的纵向索引
gbc.gridwidth=2;//设置受该对象控制的GUI组件横向跨域多少格
gbc.gridheight=1;//设置受该对象控制的GUI组件纵向跨域多少格
3.调用GridBagLayout对象的方法来建立GridBagConstraints对象和受控制组件之间的关系
gb.setConstraints(c,gbc);//设置组件c受gbc对象控制
4.添加组件,与采用普通布局管理器添加组件的方法完全一样
container.add(c);
因此使用GridBagLayout的关键在于GridBagConstraints,它才是精确控制每个GUI组件的核心类,CridBagConstraints类有几个属性:
1.gridX、gridY 设置受该对象控制的GUI组件左上角所在网格的横向索引和纵向索引(GridBagLayout左上角网格的索引为0、0)。这两个值还可以是GridBagConstraints.RELATIVE(默认值),它表明当前组件紧跟在上一个组件之后。
2.gridwidth、gridheight 设置受该对象控制的GUI组件横向、纵向可以跨域多少个网格,两个属性值的默认值都是1。如果设置这两个属性值为GridBagConstraints.REMAINDER,表明受该对象控制的GUI组件是横向、纵向最后一个组件;如果设置这两个属性为GridBagConstraints.RELATIVE,表明该独享控制的GUI组件是横向、纵向控制的倒数第二个组件,或是让这个组件紧跟在前面添加的组件之后。
3.fill 设置受该对象控制的GUI组件如何占据空白区域,该属性的取值如下,
GridBagConstraints.NONE :GUI组件不扩大
GridBagConstraints.HORIZONTAL :GUI组件水平扩大以占据空白区域
GridBagConstraints.VERTICAL :GUI组件垂直扩大以占据空白区域
GridBagConstraints.BOTH :GUI组件水平垂直同时扩大以占据空白区域
4.ipadx、ipady 设置受该对象控制的GUI组件横向、纵向填充的大小,及在该组件最小尺寸的基础上还需要增大多少。如果设置了这两个属性,则组件横向的大小为最小宽度再加上ipadx*2像素,纵向的大小为最小高度再加上ipady*2像素。
5.insets 设置受该对象控制的GUI组件的外部填充的大小,及该组件边界和显示区域边界的距离。
6.anchor 设置受该对象控制的GUI组件在其显示区域中的定位方式。定位方式如下:
GridBagConstraints.CENTER (中间)
GridBagConstraints.NORTH(上中)
GridBagConstraints.NORTHWEST(左上角 )
GridBagConstraints.NORTHEAST(右上角)
GridBagConstraints.SOUTH(下中)
GridBagConstraints.SOUTHEAST(右下角)
GridBagConstraints.SOUTHWEST(左下角)
GridBagConstraints.EAST(右中)
GridBagConstraints.WEST(左中)
7.weightx、weighty 设置受该对象控制的GUI组件占用多余空间的水平、垂直增加比例(也叫权重,即weight的直译),这两个属性的默认值是0,即该组件不占用多余的空间。假设某个容器的水平线上包括三个GUI组件,他们的水平增加比例分别为1、2、3,当容器宽度增加60的时候,第一个组件的宽度增加10,第二个组件的宽度增加20,第三个组件的宽度增加30。如果增加比率为0,表示不会增加。
如果希望某个组件的大小随着容器的增加而增加,则必须同时设置该组件的GridBagConstraints对象的fill属性和weightX、weightY属性。
例如:
public class GridBagLayoutTest {
private JFrame f=new JFrame();
private GridBagLayout gb=new GridBagLayout();
private GridBagConstraints gbc=new GridBagConstraints();
private JButton[] bs=new JButton[10]; private void init(){
f.setLayout(gb);
for(int i=0;i<bs.length;i++){
bs[i]=new JButton("按钮"+i);
}
//设置所有组件都可以在横向和纵向上扩大
gbc.fill=GridBagConstraints.BOTH;
gbc.weightx=1;
gbc.weighty=1; addJButton(gbc,bs[0]);
addJButton(gbc,bs[1]);
addJButton(gbc,bs[2]); //设置该gbc控制的组件为横向的最后一个
gbc.gridwidth=GridBagConstraints.REMAINDER;
addJButton(gbc,bs[3]);
addJButton(gbc,bs[4]); //设置该gbc控制的组件不会横向扩大
gbc.gridwidth=GridBagConstraints.RELATIVE;
gbc.weightx=0;
gbc.gridwidth=2;//设置该gbc控制的组件可以占两格
addJButton(gbc,bs[5]); //设置为横向最后一个组件
gbc.gridwidth=GridBagConstraints.REMAINDER;
addJButton(gbc,bs[6]); //设置该GridBagConstraints控制的组件横向跨越一格,纵向跨越两格
gbc.gridwidth=1;
gbc.gridheight=2; addJButton(gbc,bs[7]); //设置纵向不会扩大
gbc.weighty=0;
//设置该GridBagConstraints控制的组件将成为横向的最后一个组件
gbc.gridwidth=GridBagConstraints.REMAINDER;
//设置该GridBagConstraints控制的组件纵向跨域1格
gbc.gridheight=1; addJButton(gbc,bs[8]);
addJButton(gbc,bs[9]); f.pack();
f.setVisible(true);
}
private void addJButton(GridBagConstraints gbc,JButton b){
gb.setConstraints(b, gbc);
f.add(b);
} public static void main(String[] args) {
new GridBagLayoutTest().init();
}
}
5.CardLayout
CardLayout布局管理器以时间而非空间的方式来管理它里面的组件,它将加入容器的所有组件看成一叠卡片,每次只有最上面的那个Component可见。就好像一副扑克牌,他们叠在一起,每次只有最上面的那张扑克牌可见。
因为CardLayout布局管理器这种特性,所以在实现AWT页面跳转的时候,可以使用该布局管理器来实现。有一点需要注意,往cardLayout中添加的组件,默认情况下,第一个被显示的组件是会聚焦的,即使在后来换成了cardlayout中的其它组件,聚焦还是不会变,如果不聚焦的话将会导致一些功能不能使用(例如键盘响应事件),所以在换了cardLayout中的组件中,必需要手动聚焦,键盘事件才会起作用,调用方法: jpanel1.requestFocus(); 。
例如:
public void mousePressed(MouseEvent e) {
//开始跳转画面
layout.show(layoutPanel, "game");
//必须要显式聚焦,gamePanel才能聚焦,键盘事件才会起作用
gamePanel.requestFocus();
}
案例:
JFrame f=new JFrame("窗口测试");
CardLayout layout=new CardLayout();
String[] names={"第一张","第二张","第三张","第四张","第五张"};
JPanel p1=new JPanel();
JPanel p2=new JPanel(); public void init(){
p1.setLayout(layout);
for(int i=0;i<names.length;i++){
p1.add(names[i], new Button(names[i]));
}
ActionListener listener=new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name=e.getActionCommand();
if("上一张".equals(name)){
layout.previous(p1);
}else if("下一张".equals(name)){
layout.next(p1);
}else if("第一张".equals(name)){
layout.first(p1);
}else if("最后一张".equals(name)){
layout.last(p1);
}else if("第三张".equals(name)){
layout.show(p1, name);
}
}
}; JButton previous=new JButton("上一张");
previous.addActionListener(listener);
p2.add(previous);
JButton next=new JButton("下一张");
next.addActionListener(listener);
p2.add(next);
JButton first=new JButton("第一张");
first.addActionListener(listener);
p2.add(first);
JButton last=new JButton("最后一张");
last.addActionListener(listener);
p2.add(last);
JButton three=new JButton("第三张");
three.addActionListener(listener);
p2.add(three); f.add(p1);
f.add(p2,BorderLayout.SOUTH);
f.pack();
f.setSize(500,300);
f.setVisible(true);
}
public static void main(String[] args) {
new CardLayoutTest().init();
}
6.BoxLayout
GridBagLayout的功能虽然强大,但是实在太过复杂,所以Swing引入了一个新的布局管理器BoxLayout,BoxLayout保留了GridBagLayout的许多优点,同时又没有那么复杂。
BoxLayout可以被设置到其它组件(例如JFrame,JPanel等等),但是BoxLayout一般和Box组件搭配使用,Box组件优点像Panel容器,但该容器使用的是BoxLayout布局管理器。
下面是BoxLayou的一些常用方法:
Box.createHorizontalBox();//水平摆放的组件
Box.createVerticalBox();//垂直摆放的组件
Box.createGlue();//可在两个方向同时拉伸的间距
Box.createHorizontalGlue();//可在水平方向拉伸的间距
Box.createVerticalGlue();//可在垂直方向拉伸的间距
Box.createHorizontalStrut(int width);//创建一个指定宽度的间距,可在垂直方向拉伸间距
Box.createVerticalStrut(int height);//创建一个指定高度的间距,可在水平方向拉伸间距
Box.createRigidArea(Dimension d);//创建一个指定宽度和高度的间距,水平和垂直方向都不可拉伸间距
案例:
JFrame f=new JFrame("窗口测试");
//定义水平摆放的组件
Box horizontal=Box.createHorizontalBox();
//定义垂直摆放的组件
Box vertical=Box.createVerticalBox(); public void init(){
horizontal.add(new JButton("水平按钮一"));
horizontal.add(Box.createHorizontalGlue());//水平方向可拉伸的间距
horizontal.add(new JButton("水平按钮二"));
horizontal.add(Box.createHorizontalStrut(10));//水平方向不可拉伸的组件
horizontal.add(new JButton("水平按钮三")); vertical.add(new JButton("垂直按钮一"));
vertical.add(Box.createVerticalGlue());//垂直方向可拉伸的组件
vertical.add(new JButton("垂直按钮二"));
vertical.add(Box.createVerticalStrut(10));//垂直方向不可拉伸的组件
vertical.add(new JButton("垂直按钮三")); f.add(horizontal,BorderLayout.NORTH);
f.add(vertical);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new BoxLayoutTest().init();
}
【java】浅析java组件中的布局管理器的更多相关文章
- JAVA中GridBagLayout布局管理器应用详解
很多情况下,我们已经不需要通过编写代码来实现一个应用程序的图形界面,而是通过强大的IDE工具通过拖拽辅以简单的事件处理代码即可很轻松的完成.但是我们不得不面对这样操作存在的一些问题,有时候我们希望能够 ...
- Qt中的布局管理器
1. 布局管理器提供相关的类对界面组件进行布局管理,能够自动排列窗口中的界面组件,窗口变化后能自动更新界面组件的大小. 2. QLayout是Qt布局管理器的抽象基类,通过继承QLayout实现了功能 ...
- Draw2d中的布局管理器Layout比较
最近在研究Eclipse中的GEF开发,在跟着GEF-whole-upload教程做一个GEF应用程序的例子时,发现Figure上的控件无法显示,谷歌了很久也没找到解决方案,最后终于发现是Layout ...
- Java——布局管理器
在Swing中使用的所有布局管理器都可以实现LayoutManager接口,在Swing中主要使用的5种布局管理器:FlowLayout.BorderLayout.GridLayout.CardLay ...
- Java可视化编程,基于布局管理器的UI设计
在<事件驱动模型>讲述了如何将用户与功能实现代码联系到一起.怎么样便于用户理解和符合用户的使用习惯? 本篇还是就此问题作分析,站在用户角度上分析UI各组件倒底该如何设计呈现. 优秀的UI会 ...
- 第1组UI组件:布局管理器
1 布局管理的来源 为了让UI在不同的手机屏幕上都能运行良好----不同手机屏幕的分辨率/尺寸并不完全相同,如果让程序手动控制每个组件的大小.位置,会给编程带来巨大的麻烦.为了解决这个问题.andro ...
- Swing布局管理器
在Swing中使用的所有布局管理器都可以实现LayoutManager接口.Swing中有五种常见的布局管理器分别为FlowLayout.BorderLayout.GridLayout.CardLay ...
- 【Android 应用开发】AndroidUI设计之 布局管理器 - 详细解析布局实现
写完博客的总结 : 以前没有弄清楚的概念清晰化 父容器与本容器属性 : android_layout...属性是本容器的属性, 定义在这个布局管理器的LayoutParams内部类中, 每个布局管理器 ...
- Swing——布局管理器
前言 在编写图形界面时,总是需要考虑的就是组件放在哪里,组件怎么大才合适.在Swing中就有现成的布局管理器帮我们做这些事情,我们不必写代码去一一安排.下面将介绍什么是布局管理器.Swing中常用布局 ...
随机推荐
- mongodb自动关闭:页面文件太小,无法完成操作
在一台两G内存的win server 2008电脑上运行一个程序,一段时间后mongod自动停止,发现日志文件最后有这样的错误: 2014-11-30T00:32:32.914+0800 [conn3 ...
- ArcGIS Add-in ValidateAddInXMLTask”任务意外失败
晚上收假回来调一Add-In程序,遇到编译错误:"ValidateAddInXMLTask"任务意外失败. error MSB4018: System.IO.FileNotFoun ...
- iOS 8 swift 键盘不出来 ios 8 uitextfield keyboard not appearing
ios 8 uitextfield keyboard not appearing //发现在iphone 6 and iPhone plus 上面键盘不出来.后来查了下原来要在模拟器里设置下 var ...
- 使用docker api
前提: 系统centos 7 docker version 1.10.3 使用systemd启动docker 访问方式: 修改/usr/lib/systemd/system/docker.servic ...
- 微信小程序 - 日期(起止)选择器组件
2019-01-03 : 修复了日期day-1,新增了年月日(除去时分秒),删除了不必要的touchmove 新增: column: ""(年月日) 配置: pickerConfi ...
- 跟我学AngularJS:全局变量设置之value vs constant vs rootscope vs 服务[转]
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文要讲讲Angular中value vs. constant以及全局变量的设置 本教程 ...
- The ECDSA host key for XXX has changed
运行Hadoop时出现了: 导致运行失败.仔细分析后发现,这是因为以前192.168.1.201的主机名为master,后来把192.168.1.202改名为master,由于两台主机的公钥不一样,所 ...
- C# ACCESS数据库链接
private void button1_Click(object sender, EventArgs e) { string strConnection = "Provide ...
- ios网络学习------9 播放网络视频
IOS提供了叫做MPMoviePlayerController MPMoviePlayerViewController两个类.能够轻松用来实现视频播放. MPMoviePlayerViewContr ...
- org.apache.commons.lang.exception包的ExceptionUtils工具类获取getFullStackTrace
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreem ...