布局管理器LayoutManager
LayoutManager 直接子类:GridLayout, FlowLayout等
调用:java.awt.Container调用doLayout时调用
代码如下 (参考java.awt.Container类)
LayoutManager layoutMgr = this.layoutMgr;
if (layoutMgr != null) {
layoutMgr.layoutContainer(this);
}
接口方法说明:
//目前还没研究出其更多用处
void addLayoutComponent(String name, Component comp);
//目前还没研究出其更多用处
void removeLayoutComponent(Component comp);
//得到此container 的理想尺寸,实现的时候常常根据该container中各个component
//的理想尺寸和布局原则来确定
Dimension preferredLayoutSize(Container parent);
//得到该container的最小尺寸。
Dimension minimumLayoutSize(Container parent);
//container调用此方法用于布局
void layoutContainer(Container parent);
FlowLayout 分析
预备知识(熟悉的人可以忽略这一步)
1.设定的component的大小位置
我们常常看到有很多size方法,如setBounds(),setSize(),setPreferredSize()等,真正在布局用的是
setSize()确定其大小,容器将如实按照此大小来绘制 该component.setLoaction用于确定该component
在container中的的位置,同样,容器将如实按照此位置绘制该component
2.跨平台:由于java是垮平台语言,所以在布局的时候考虑的各个系统坐标方向可能是从左到右,也可能是
从右到左,因此,java在component中包含了getComponentOrientation()用于判断系统的方向,布局的时候,
因充分考虑到此特性
分析
在做任何布局管理器前都应确定布局原则,如FlowLayout的原则就是将component依次加入到container中
如果一行排不满,则换到下一行,可选择从左往右加,也可以选择从右往左加,还可以选择从中间开始排
[pre]//原则是将所有的component取出,并排成一行,取各个component的宽度之和(包括hgap)为container理想宽度
//取最高component的为container理想的高度
public Dimension preferredLayoutSize(Container target) {
//获得锁
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
//得到容器下的所有的component
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) { //不可见的component将不显示
Dimension d = m.getPreferredSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
//component间应有hgap间隙
dim.width += hgap;
}
dim.width += d.width;
}
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
//container将调用此方法来布局
//原则是总是试图将component排到一行,如果container的宽度已经不够,则另起一行,开始排
//下一行
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
//最大宽度
int maxwidth = target.width - (insets.left + insets.right + hgap*2);
int nmembers = target.getComponentCount();
int x = 0, y = insets.top + vgap;
//rowh 用于只是下一行应从哪(y坐标)开始
//start 用于指示新的一行应该是从第几个component开始
int rowh = 0, start = 0;
boolean ltr = target.getComponentOrientation().isLeftToRight();
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
Dimension d = m.getPreferredSize();
m.setSize(d.width, d.height);
if ((x == 0) || ((x + d.width) <= maxwidth)) {
if (x > 0) {
x += hgap;
}
x += d.width;
//确定一行的高度
rowh = Math.max(rowh, d.height);
} else {
//布局该行
//x坐标应是 insets.left + hgap
//y 坐标 vgap + rowh
//从第start开始排,一直排到第i个
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, i, ltr);
x = d.width;
y += vgap + rowh;
rowh = d.height;
start = i;
}
}
}
//布局剩下的一行
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, nmembers, ltr);
}
}[/pre]
制作自己的布局管理器首先,应确定自己的布局原则是什么,如下
1.将JLabel,JTextField(JTextArea,JPanel),JLabel做为一个布局单元
第一个label常用于前缀(为了方便叙说,通称为preLabel),
第二个component则作为输入内容(为了叙说方便,成为inputComponent),
第三个label作为附加说明,通常做为后缀(为了方便叙说,通成为suffixLabel。
2。容器可以设定列数,表示每行可以放多少个布局单元,每列的宽度为容器实际宽度/列数
3。对于容器中的每列, 实际是又按照preLable,inputComponent,suffixLabel分成三列
第一列的宽度为所有属于该列的布局单元中所有preLabel的最大宽度
第三列宽度同上,为有属于该列的布局单元中所有suffixLabel的最大宽度
第二列宽度为剩下的值,随着容器大小而动态改变
[pre]import java.awt.*;
import java.util.*;
import javax.swing.*;
import dl.*;
public class DialogLayout
implements LayoutManager
{
protected int m_divider = -1;
protected int m_hGap = 10;
protected int m_vGap = 5;
//如果inputComponent为JTextField则认为该布局单元的高度为25
public static int HEIGHT = 25;
//容器平均分成多少列
int col = 2;
public DialogLayout(int col)
{
this.col = col;
}
public DialogLayout()
{
this.col = 2;
}
public DialogLayout(int hGap, int vGap,int col)
{
m_hGap = hGap;
m_vGap = vGap;
this.col = col;
}
public void addLayoutComponent(String name, Component comp) {}
public void removeLayoutComponent(Component comp) {}
public Dimension preferredLayoutSize(Container parent)
{
int thisWidth=0;;
int thisHeight = 0;
Insets insets = parent.getInsets();
Vector[] v = this.getSimpleComponents(parent,col);
for(int i =0 ;i {
Dimension d = this.getPreferredSize(v[i],parent);
thisWidth = thisWidth+d.width;
thisHeight = Math.max(thisHeight,d.height);
}
Vector ve = this.getComplexComponents(parent);
int height = 0;
for(int i= 0;i {
Component jc = (Component)ve.get(i);
Dimension d = jc.getPreferredSize();
height+=d.height+m_vGap;
//height+=HEIGHTER+m_vGap;
}
return new Dimension(thisWidth,thisHeight+height);
}
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
public void layoutContainer(Container parent)
{
Insets insets = parent.getInsets();
int startx = insets.left;
int starty = insets.top;
//得到实际尺寸;??
Dimension d =parent.getSize();
int partWidth = d.width/col;
Vector[] v = this.getSimpleComponents(parent,col);
Divider[] divider = new Divider[col];
for(int i = 0;i {
divider[i] = this.getDivider(v[i],parent);
if(i==0)
{
//比较第一列的label最大值
divider[i].left = Math.max(divider[i].left,this.getComplexDivider(parent));
}
}
int cols=-1; ;
for(int i=1,count=0;i {
Component mjc = (Component)parent.getComponent(i);
Component label = (Component)parent.getComponent(i-1);
Component suffix = (Component)parent.getComponent(i+1);
if(isLongTextFields(mjc))
{
startx = insets.left;
//starty =starty+this.m_vGap;
label.setBounds(startx,starty,divider[0].left,HEIGHT);
mjc.setBounds(startx+divider[0].left+m_hGap,starty,
d.width-(insets.right+insets.left+divider[divider.length-1].right+divider[0].left+2*m_hGap),mjc.getPreferredSize().height);
starty = starty + mjc.getPreferredSize().height+this.m_vGap;
//找到一个textArea,计数器加一
//mjc.setBounds(startx,starty,d.width,HEIGHT);
//count++;
cols = -1 ;
continue;
}
else
{
//int cols = (i-1-count)/col;//得到所在列
cols = (cols+1)%col;
startx = partWidth*cols+insets.left;
int w = partWidth - divider[cols].left - divider[cols].right-2*this.m_hGap;
label.setBounds(startx,starty,divider[cols].left,HEIGHT);
//label.setBounds(3,3,30,20);
mjc.setBounds(startx+divider[cols].left+m_hGap,starty,w,HEIGHT);
suffix.setBounds(startx+w+divider[cols].left+2*m_hGap,starty,divider[cols].right,HEIGHT);
//mjc.setBounds(startx,starty,partWidth,HEIGHT);
//starty+=HEIGHT+m_vGap;
if(cols == divider.length-1)
{
starty+=HEIGHT+m_vGap;//下一行
cols = -1;
continue;
}
if(parent.getComponentCount()>(i+3))
{
Component mjc1 = (Component)parent.getComponent(i+3);
if(isLongTextFields(mjc1))
{
starty+=HEIGHT+m_vGap;
}
}
}
}
}
public int getHGap()
{
return m_hGap;
}
public int getVGap()
{
return m_vGap;
}
public String toString()
{
return "javamonkey";
}
//-----------------
protected Dimension getPreferredSize(Vector v,Container parent)
{
int iSize = v.size();
//int cSize = parent.getPreferredSize();
int lbWidth = 0;
int sfWidth = 0;
int mjcWidth = 0;
int height = 0;
Insets insets = parent.getInsets();
for(int i = 0;i {
Component mjc = (Component)v.get(i);
int count = this.find(parent,mjc);
Component label = parent.getComponent(count-1);
Component suffix = parent.getComponent(count+1);
lbWidth = Math.max(lbWidth,label.getPreferredSize().width);
sfWidth = Math.max(sfWidth,suffix.getPreferredSize().width);
mjcWidth = Math.max(mjcWidth,mjc.getPreferredSize().width);
//高度都定为label高度
//height = height+label.getPreferredSize().height+m_vGap;
height = height+HEIGHT+m_vGap;
}
int thisWidth = lbWidth+m_hGap+mjcWidth+m_hGap+sfWidth;
int thisHeight = height;
return new Dimension(thisWidth,thisHeight);
}
private Divider getDivider(Vector v,Container parent)
{
int iSize = v.size();
//int cSize = parent.getPreferredSize();
int lbWidth = 0;
int sfWidth = 0;
int mjcWidth = 0;
for(int i = 0;i {
Component mjc = (Component)v.get(i);
int count = this.find(parent,mjc);
Component label = parent.getComponent(count-1);
Component suffix = parent.getComponent(count+1);
lbWidth = Math.max(lbWidth,label.getPreferredSize().width);
sfWidth = Math.max(sfWidth,suffix.getPreferredSize().width);
mjcWidth = Math.max(mjcWidth,mjc.getPreferredSize().width);
}
return new Divider(lbWidth,sfWidth);
}
private Vector[] getSimpleComponents(Container parent,int col)
{
Vector v = new Vector();
for (int k=1 ; k {
Component mjc = (Component)parent.getComponent(k);
if(!isLongTextFields(mjc))v.add(mjc);;
}
Vector[] array = new Vector[col];
for (int k=0 ; k {
array[k] = new Vector();
}
for (int k=0 ; k {
int cols = k%col;
Component mjc = (Component)v.get(k);
array[cols].add(mjc);
}
return array;
}
private Vector getComplexComponents(Container parent)
{
Vector v = new Vector();
for (int k=1 ; k {
Component mjc = (Component)parent.getComponent(k);
if(isLongTextFields(mjc))v.add(mjc);;
}
return v;
}
private int getComplexDivider(Container parent)
{
Vector v = getComplexComponents(parent);
int iSize = v.size();
int lbWidth = 0;
for(int i = 0;i {
Component mjc = (Component)v.get(i);
int count = this.find(parent,mjc);
Component label = parent.getComponent(count-1);
lbWidth = Math.max(lbWidth,label.getPreferredSize().width);
}
return lbWidth;
}
private boolean isLongTextFields(Component mjc)
{
if(mjc instanceof javax.swing.JTextArea) return true;
if(mjc instanceof javax.swing.JPanel) return true;
else
{
return false;
}
}
private int find(Container parent,Component cp)
{
Component[] cps = parent.getComponents();
for(int i=0;i {
if(cp.equals(cps[i]))return i;
}
return -1;
}
}
//用于表示每个列的所有preLable,suffixLabel最大值
class Divider
{
int left;
int right;
public Divider(int left,int right)
{
this.left = left;
this.right =right;
}
}[/pre]
应用布局管理器
凡是刚接触swing的,无不对布局头疼,以下是flowLayout和DialogLayout的综合使用,可以看到,只用它们俩个(有时候,还需要用BorderLayout用于宏观布局),就可以轻松做出比较美观的复杂界面
列子如下
[pre]import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
*
*
*
* @author javamonkey
* @version 1.0
*/
public class Frame4 extends JFrame {
private JPanel contentPane;
//Construct the frame
public Frame4() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
//Component initialization
private void jbInit() throws Exception {
//setIconImage(Toolkit.getDefaultToolkit().createImage(Frame4.class.getResource("[Your Icon]")));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(new DialogLayout());
//第一组布局单元
contentPane.add(new JLabel("date:"));
contentPane.add( new JTextField());
contentPane.add( new suffixLabel());
//第二组布局单元
contentPane.add( new JLabel("from:"));
contentPane.add( new JTextField());
contentPane.add( new suffixLabel());
//第三组布局单元
contentPane.add( new JLabel("memo:"));
JTextArea tx = new JTextArea();
tx.setPreferredSize(new Dimension(0,50));
contentPane.add(tx );
contentPane.add( new suffixLabel());
//第四组布局单元
contentPane.add( new JLabel("cash:"));
contentPane.add(new JTextField());
contentPane.add( new suffixLabel("$"));
//第五组布局单元
JPanel pl = new JPanel();
pl.setLayout(new FlowLayout(FlowLayout.LEFT));
pl.setBorder(BorderFactory.createEtchedBorder());
pl.add(new JLabel("性别:"));
pl.add(new JRadioButton("男"));
pl.add(new JRadioButton("女"));
contentPane.add(new Label());
contentPane.add(pl);
contentPane.add(new suffixLabel());
//
this.setSize(new Dimension(400, 300));
this.setTitle("Frame Title");
}
//Overridden so we can exit when window is closed
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
class suffixLabel extends JLabel
{
public suffixLabel(String str)
{
super(str);
this.setPreferredSize(new Dimension(10,0));
}
public suffixLabel()
{
super();
}
}[/pre]
LayoutManager 直接子类:GridLayout, FlowLayout等
调用:java.awt.Container调用doLayout时调用
代码如下 (参考java.awt.Container类)
LayoutManager layoutMgr = this.layoutMgr;
if (layoutMgr != null) {
layoutMgr.layoutContainer(this);
}
接口方法说明:
//目前还没研究出其更多用处
void addLayoutComponent(String name, Component comp);
//目前还没研究出其更多用处
void removeLayoutComponent(Component comp);
//得到此container 的理想尺寸,实现的时候常常根据该container中各个component
//的理想尺寸和布局原则来确定
Dimension preferredLayoutSize(Container parent);
//得到该container的最小尺寸。
Dimension minimumLayoutSize(Container parent);
//container调用此方法用于布局
void layoutContainer(Container parent);
FlowLayout 分析
预备知识(熟悉的人可以忽略这一步)
1.设定的component的大小位置
我们常常看到有很多size方法,如setBounds(),setSize(),setPreferredSize()等,真正在布局用的是
setSize()确定其大小,容器将如实按照此大小来绘制 该component.setLoaction用于确定该component
在container中的的位置,同样,容器将如实按照此位置绘制该component
2.跨平台:由于java是垮平台语言,所以在布局的时候考虑的各个系统坐标方向可能是从左到右,也可能是
从右到左,因此,java在component中包含了getComponentOrientation()用于判断系统的方向,布局的时候,
因充分考虑到此特性
分析
在做任何布局管理器前都应确定布局原则,如FlowLayout的原则就是将component依次加入到container中
如果一行排不满,则换到下一行,可选择从左往右加,也可以选择从右往左加,还可以选择从中间开始排
[pre]//原则是将所有的component取出,并排成一行,取各个component的宽度之和(包括hgap)为container理想宽度
//取最高component的为container理想的高度
public Dimension preferredLayoutSize(Container target) {
//获得锁
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
//得到容器下的所有的component
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) { //不可见的component将不显示
Dimension d = m.getPreferredSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
//component间应有hgap间隙
dim.width += hgap;
}
dim.width += d.width;
}
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
//container将调用此方法来布局
//原则是总是试图将component排到一行,如果container的宽度已经不够,则另起一行,开始排
//下一行
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
//最大宽度
int maxwidth = target.width - (insets.left + insets.right + hgap*2);
int nmembers = target.getComponentCount();
int x = 0, y = insets.top + vgap;
//rowh 用于只是下一行应从哪(y坐标)开始
//start 用于指示新的一行应该是从第几个component开始
int rowh = 0, start = 0;
boolean ltr = target.getComponentOrientation().isLeftToRight();
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
Dimension d = m.getPreferredSize();
m.setSize(d.width, d.height);
if ((x == 0) || ((x + d.width) <= maxwidth)) {
if (x > 0) {
x += hgap;
}
x += d.width;
//确定一行的高度
rowh = Math.max(rowh, d.height);
} else {
//布局该行
//x坐标应是 insets.left + hgap
//y 坐标 vgap + rowh
//从第start开始排,一直排到第i个
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, i, ltr);
x = d.width;
y += vgap + rowh;
rowh = d.height;
start = i;
}
}
}
//布局剩下的一行
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, nmembers, ltr);
}
}[/pre]
制作自己的布局管理器首先,应确定自己的布局原则是什么,如下
1.将JLabel,JTextField(JTextArea,JPanel),JLabel做为一个布局单元
第一个label常用于前缀(为了方便叙说,通称为preLabel),
第二个component则作为输入内容(为了叙说方便,成为inputComponent),
第三个label作为附加说明,通常做为后缀(为了方便叙说,通成为suffixLabel。
2。容器可以设定列数,表示每行可以放多少个布局单元,每列的宽度为容器实际宽度/列数
3。对于容器中的每列, 实际是又按照preLable,inputComponent,suffixLabel分成三列
第一列的宽度为所有属于该列的布局单元中所有preLabel的最大宽度
第三列宽度同上,为有属于该列的布局单元中所有suffixLabel的最大宽度
第二列宽度为剩下的值,随着容器大小而动态改变
[pre]import java.awt.*;
import java.util.*;
import javax.swing.*;
import dl.*;
public class DialogLayout
implements LayoutManager
{
protected int m_divider = -1;
protected int m_hGap = 10;
protected int m_vGap = 5;
//如果inputComponent为JTextField则认为该布局单元的高度为25
public static int HEIGHT = 25;
//容器平均分成多少列
int col = 2;
public DialogLayout(int col)
{
this.col = col;
}
public DialogLayout()
{
this.col = 2;
}
public DialogLayout(int hGap, int vGap,int col)
{
m_hGap = hGap;
m_vGap = vGap;
this.col = col;
}
public void addLayoutComponent(String name, Component comp) {}
public void removeLayoutComponent(Component comp) {}
public Dimension preferredLayoutSize(Container parent)
{
int thisWidth=0;;
int thisHeight = 0;
Insets insets = parent.getInsets();
Vector[] v = this.getSimpleComponents(parent,col);
for(int i =0 ;i {
Dimension d = this.getPreferredSize(v[i],parent);
thisWidth = thisWidth+d.width;
thisHeight = Math.max(thisHeight,d.height);
}
Vector ve = this.getComplexComponents(parent);
int height = 0;
for(int i= 0;i {
Component jc = (Component)ve.get(i);
Dimension d = jc.getPreferredSize();
height+=d.height+m_vGap;
//height+=HEIGHTER+m_vGap;
}
return new Dimension(thisWidth,thisHeight+height);
}
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
public void layoutContainer(Container parent)
{
Insets insets = parent.getInsets();
int startx = insets.left;
int starty = insets.top;
//得到实际尺寸;??
Dimension d =parent.getSize();
int partWidth = d.width/col;
Vector[] v = this.getSimpleComponents(parent,col);
Divider[] divider = new Divider[col];
for(int i = 0;i {
divider[i] = this.getDivider(v[i],parent);
if(i==0)
{
//比较第一列的label最大值
divider[i].left = Math.max(divider[i].left,this.getComplexDivider(parent));
}
}
int cols=-1; ;
for(int i=1,count=0;i {
Component mjc = (Component)parent.getComponent(i);
Component label = (Component)parent.getComponent(i-1);
Component suffix = (Component)parent.getComponent(i+1);
if(isLongTextFields(mjc))
{
startx = insets.left;
//starty =starty+this.m_vGap;
label.setBounds(startx,starty,divider[0].left,HEIGHT);
mjc.setBounds(startx+divider[0].left+m_hGap,starty,
d.width-(insets.right+insets.left+divider[divider.length-1].right+divider[0].left+2*m_hGap),mjc.getPreferredSize().height);
starty = starty + mjc.getPreferredSize().height+this.m_vGap;
//找到一个textArea,计数器加一
//mjc.setBounds(startx,starty,d.width,HEIGHT);
//count++;
cols = -1 ;
continue;
}
else
{
//int cols = (i-1-count)/col;//得到所在列
cols = (cols+1)%col;
startx = partWidth*cols+insets.left;
int w = partWidth - divider[cols].left - divider[cols].right-2*this.m_hGap;
label.setBounds(startx,starty,divider[cols].left,HEIGHT);
//label.setBounds(3,3,30,20);
mjc.setBounds(startx+divider[cols].left+m_hGap,starty,w,HEIGHT);
suffix.setBounds(startx+w+divider[cols].left+2*m_hGap,starty,divider[cols].right,HEIGHT);
//mjc.setBounds(startx,starty,partWidth,HEIGHT);
//starty+=HEIGHT+m_vGap;
if(cols == divider.length-1)
{
starty+=HEIGHT+m_vGap;//下一行
cols = -1;
continue;
}
if(parent.getComponentCount()>(i+3))
{
Component mjc1 = (Component)parent.getComponent(i+3);
if(isLongTextFields(mjc1))
{
starty+=HEIGHT+m_vGap;
}
}
}
}
}
public int getHGap()
{
return m_hGap;
}
public int getVGap()
{
return m_vGap;
}
public String toString()
{
return "javamonkey";
}
//-----------------
protected Dimension getPreferredSize(Vector v,Container parent)
{
int iSize = v.size();
//int cSize = parent.getPreferredSize();
int lbWidth = 0;
int sfWidth = 0;
int mjcWidth = 0;
int height = 0;
Insets insets = parent.getInsets();
for(int i = 0;i {
Component mjc = (Component)v.get(i);
int count = this.find(parent,mjc);
Component label = parent.getComponent(count-1);
Component suffix = parent.getComponent(count+1);
lbWidth = Math.max(lbWidth,label.getPreferredSize().width);
sfWidth = Math.max(sfWidth,suffix.getPreferredSize().width);
mjcWidth = Math.max(mjcWidth,mjc.getPreferredSize().width);
//高度都定为label高度
//height = height+label.getPreferredSize().height+m_vGap;
height = height+HEIGHT+m_vGap;
}
int thisWidth = lbWidth+m_hGap+mjcWidth+m_hGap+sfWidth;
int thisHeight = height;
return new Dimension(thisWidth,thisHeight);
}
private Divider getDivider(Vector v,Container parent)
{
int iSize = v.size();
//int cSize = parent.getPreferredSize();
int lbWidth = 0;
int sfWidth = 0;
int mjcWidth = 0;
for(int i = 0;i {
Component mjc = (Component)v.get(i);
int count = this.find(parent,mjc);
Component label = parent.getComponent(count-1);
Component suffix = parent.getComponent(count+1);
lbWidth = Math.max(lbWidth,label.getPreferredSize().width);
sfWidth = Math.max(sfWidth,suffix.getPreferredSize().width);
mjcWidth = Math.max(mjcWidth,mjc.getPreferredSize().width);
}
return new Divider(lbWidth,sfWidth);
}
private Vector[] getSimpleComponents(Container parent,int col)
{
Vector v = new Vector();
for (int k=1 ; k {
Component mjc = (Component)parent.getComponent(k);
if(!isLongTextFields(mjc))v.add(mjc);;
}
Vector[] array = new Vector[col];
for (int k=0 ; k {
array[k] = new Vector();
}
for (int k=0 ; k {
int cols = k%col;
Component mjc = (Component)v.get(k);
array[cols].add(mjc);
}
return array;
}
private Vector getComplexComponents(Container parent)
{
Vector v = new Vector();
for (int k=1 ; k {
Component mjc = (Component)parent.getComponent(k);
if(isLongTextFields(mjc))v.add(mjc);;
}
return v;
}
private int getComplexDivider(Container parent)
{
Vector v = getComplexComponents(parent);
int iSize = v.size();
int lbWidth = 0;
for(int i = 0;i {
Component mjc = (Component)v.get(i);
int count = this.find(parent,mjc);
Component label = parent.getComponent(count-1);
lbWidth = Math.max(lbWidth,label.getPreferredSize().width);
}
return lbWidth;
}
private boolean isLongTextFields(Component mjc)
{
if(mjc instanceof javax.swing.JTextArea) return true;
if(mjc instanceof javax.swing.JPanel) return true;
else
{
return false;
}
}
private int find(Container parent,Component cp)
{
Component[] cps = parent.getComponents();
for(int i=0;i {
if(cp.equals(cps[i]))return i;
}
return -1;
}
}
//用于表示每个列的所有preLable,suffixLabel最大值
class Divider
{
int left;
int right;
public Divider(int left,int right)
{
this.left = left;
this.right =right;
}
}[/pre]
应用布局管理器
凡是刚接触swing的,无不对布局头疼,以下是flowLayout和DialogLayout的综合使用,可以看到,只用它们俩个(有时候,还需要用BorderLayout用于宏观布局),就可以轻松做出比较美观的复杂界面
列子如下
[pre]import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
Title:
*
Description:
*
Copyright: Copyright (c) 2002
*
Company:
* @author javamonkey
* @version 1.0
*/
public class Frame4 extends JFrame {
private JPanel contentPane;
//Construct the frame
public Frame4() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
//Component initialization
private void jbInit() throws Exception {
//setIconImage(Toolkit.getDefaultToolkit().createImage(Frame4.class.getResource("[Your Icon]")));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(new DialogLayout());
//第一组布局单元
contentPane.add(new JLabel("date:"));
contentPane.add( new JTextField());
contentPane.add( new suffixLabel());
//第二组布局单元
contentPane.add( new JLabel("from:"));
contentPane.add( new JTextField());
contentPane.add( new suffixLabel());
//第三组布局单元
contentPane.add( new JLabel("memo:"));
JTextArea tx = new JTextArea();
tx.setPreferredSize(new Dimension(0,50));
contentPane.add(tx );
contentPane.add( new suffixLabel());
//第四组布局单元
contentPane.add( new JLabel("cash:"));
contentPane.add(new JTextField());
contentPane.add( new suffixLabel("$"));
//第五组布局单元
JPanel pl = new JPanel();
pl.setLayout(new FlowLayout(FlowLayout.LEFT));
pl.setBorder(BorderFactory.createEtchedBorder());
pl.add(new JLabel("性别:"));
pl.add(new JRadioButton("男"));
pl.add(new JRadioButton("女"));
contentPane.add(new Label());
contentPane.add(pl);
contentPane.add(new suffixLabel());
//
this.setSize(new Dimension(400, 300));
this.setTitle("Frame Title");
}
//Overridden so we can exit when window is closed
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
class suffixLabel extends JLabel
{
public suffixLabel(String str)
{
super(str);
this.setPreferredSize(new Dimension(10,0));
}
public suffixLabel()
{
super();
}
}[/pre]
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130880/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/374079/viewspace-130880/