Java窗体中关于默认布局管理器容易踩的坑及解决
作者:灰小猿
Java窗体关于默认布局管理器容易踩的坑
JFrame窗体的默认布局管理器是边界布局管理器,在使用之前应该先使用setLayout(null)取消该布局管理器。
最近在使用Java窗体进行界面布局设置时,遇到这样一个问题,就是无论如何进行控件的布局,结果窗体上就只会布满整一个控件,代码和结果如下这样。
这就很疑惑了,明明给控件设置了坐标以及长宽,为什么在显示的时候还是会布满整个窗体?
之后查阅了很多发现是因为在不指定窗体布局的情况下,Swing组件的布局模式是边界布局管理器(BorderLayout),该布局管理器有一个特点就是在容器中放置一个组件之后,该组件是被放置在窗体中间的,并且整个组件会占据窗体的整个空间,这也就造成了在添加了组件之后,无论如何设置空间位置,空间仍然处于窗体中间并且布满的状态。
了解了这个时候,我使用了setLayout(null)来取消窗体的默认布局管理器,也就是告知窗体不再使用边界布局管理器。
但是意外又来了,在我添加了setLayout(null)之后,发现界面仍然没有变化,如下所示,
这就很奇怪了,明明已经取消了边界布局管理器,为什么在设置了控件之后还是没有效果?
经过仔细研究发现,是显示窗体可见的代码setVisible(true);放在了取消布局管理器代码的前面,这就造成了窗体先显示出来,然后才取消了边界布局,这样导致了setLayout(null)就没有了意义。
最后将setLayout(null)放在了显示窗体可见的代码setVisible(true)之前
问题解决,结果如下:
在这里需要注意的就是:
JFrame窗体的默认布局管理器是边界布局管理器,在使用之前应该先使用setLayout(null)取消该布局管理器,同时,应该在设置好之后,最后再设置setVisible(true)使窗体页面可见,否则设置的属性将无意义。
java的布局管理器
组件
组件是构成图形 用户界面的基本成分和核心元素,组件是具有以下特性的对象:运行时可见,具有位置坐标、尺寸、字体、颜色等属性,可以拥有并管理其他组件,可以获得输入焦点,可以响应事件。
容器
容器(container)是一种特殊组件,它能容纳其他组件,在其可视区域内显示这些组件。容器中各组件的大小位置由容器的布局管理进行控制。一个容器可放置其他容器,使用多层容器可以表达复杂的布局。
窗口和面板
container容器类的子类有:window窗口类和panel面板类。
Container cp = this.getContentPane();
container顶级容器,相当于定义一个顶级容器,把获取的值,附给顶级容器。如果要向顶级容器上添加其他组件或者容器,就需要调用以下方法:
Container contentPane=getContentPane(); contentPane.add(组件名);
布局管理
java.awt布局管理器主要有:FlowLayout流、BorderLayout流、GridLayout网格和GridBagLayout网格包。
布局是容器类的特性,每种容器都有一种默认布局,若果一个容器需要改变其默认布局管理器,可以调用Container容器类的setLayout()方法。
流布局管理器:
FlowLayout(流式布局),组件按照加入的先后顺序按照设置的对齐方式(居中、左对齐、右对齐)从左向右排列,一行排满到下一行开始继续排列
构造函数:
名称 | 用途 |
---|---|
FlowLayout() | 构造一个新的 FlowLayout,它是默认居中对齐的,默认的水平和垂直间隙是5个像素 |
FlowLayout(int align) | 构造一个新的 FlowLayout,它具有指定的对齐方式,默认的水平和垂直间隙是 5 个像素,五个参数值及含义如下:0或FlowLayout.lEFT ,控件左对齐。1或FlowLayout.CENTER ,居中对齐。2或FlowLayout.RIGHT ,右对齐。3或FlowLayout.LEADING,控件与容器方向开始边对应。4或FlowLayout.TRAILING,控件与容器方向结束边对应。如果是0、1、2、3、4之外的整数,则为左对齐 |
FlowLayout(int align, int hgap, int vgap) | 创建一个新的流布局管理器,它具有指定的对齐方式以及指定的水平和垂直间隙。 |
package qijingliang; import java.awt.FlowLayout; import java.awt.Font; import javax.swing.JButton; import javax.swing.JFrame; public class FlowLayoutDemo extends JFrame{ public FlowLayoutDemo(){ setLayout(new FlowLayout());//设置窗体为流式布局,无参数默认为居中对齐 setFont(new Font("Helvetica", Font.PLAIN, 14));//设置窗体中显示的字体样式 getContentPane().add(new JButton("Button 1")); getContentPane().add(new JButton("Button 2")); getContentPane().add(new JButton("Button3")); getContentPane().add(new JButton("Button 4")); } public static void main(String[] args){ FlowLayoutDemo window=new FlowLayoutDemo(); window.setTitle("流式布局"); window.pack(); window.setVisible(true); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setLocationRelativeTo(null);//让窗体居中显示 } }
注意:FlowLayout布局管理器中组件的相对位置随窗口大小而变化。
网格布局:
GrideLayout布局管理器将容器划分为大小相等的若干行乘若干列的网格,组件大小随容器大小而变化.
构造方法摘要:
GridLayout()
: 创建具有默认值的网格布局,即每个组件占据一行一列。GridLayout(int rows, int cols)
:创建具有指定行数和列数的网格布局。Rows为行数,cols为列数。GridLayout(int rows, int cols, int hgap, int vgap)
:创建具有指定行数、列数以及组件水平、纵向一定间距的网格布局。
package qijingliang; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextArea; public class GridFrame extends JFrame{ //定义面板,并设置为网格布局,4行4列,组件水平、垂直间距均为3 JPanel panel=new JPanel(new GridLayout(4,4,3,3)); JTextArea t=new JTextArea();//定义文本框 String str[]={"7","8","9","/","4","5","6","*","1","2","3","-","0",".","=","+"}; public GridFrame(String s){ super(s); setLayout(new BorderLayout());//定义窗体布局为边界布局 JButton btn[];//声明数组按钮 btn=new JButton[str.length];//创建按钮数组 //循环定义按钮,并添加到面板中 for(int i=0;i<str.length;i++){ btn[i]=new JButton(str[i]); panel.add(btn[i]); } //将文本框放置在窗体NORTH位置 getContentPane().add(t, BorderLayout.NORTH); //将面板放置在窗体CENTER位置 getContentPane().add(panel, BorderLayout.CENTER); setVisible(true); setSize(500, 400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null);//让窗体居中显示 } public static void main(String[] args){ GridFrame gl=new GridFrame("网格布局计算器"); } }
setDefaultCloseOperation()参数得使用说明
System.exit(0)
是退出整个程序,如果有多个窗口,全部都销毁退出。setDefaultCloseOperation()
是设置用户在此窗体上发起 “close” 时默认执行的操作。必须指定以下选项之一:DO_NOTHING_ON_CLOSE
(在 WindowConstants 中定义):不执行任何操作;要求程序在已注册的 WindowListener 对象的 windowClosing 方法中处理该操作。HIDE_ON_CLOSE
(在 WindowConstants 中定义):调用任意已注册的 WindowListener 对象后自动隐藏该窗体。DISPOSE_ON_CLOSE
(在 WindowConstants 中定义):调用任意已注册 WindowListener 的对象后自动隐藏并释放该窗体。EXIT_ON_CLOSE
(在 JFrame 中定义):使用 System exit 方法退出应用程序。仅在应用程序中使用。
默认情况下,该值被设置为 HIDE_ON_CLOSE
也就是说没有设置的话,默认点关闭时只是隐藏窗体,在后台进程中还可以看到,如果有多个窗口,只是销毁调用dispose的窗口,其他窗口仍然存在,整个应用程序还是处于运行状态。
setLocationRelativeTo
public void setLocationRelativeTo(Component c)
设置窗口相对于指定组件的位置。
如果组件当前未显示,或者 c 为 null,则此窗口将置于屏幕的中央。
(容易出现的问题:(调用居中后,窗体跑到右下角去了)对于一个新的JFrame来讲,基本可以认为是0x0大小的,你在填充内容前调用这个函数,等于是把窗口的左上角放在了屏幕中央。然后你后面再添加了别的子组件之后pack或者setSize,JFrame窗口变大,但是左上角还在屏幕中央。 )
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。