存档

文章标签 ‘introduce’

Java 布局管理器不完全指南

2010年6月20日 低调の华丽 2 条评论

绝大多数的Java程序员都不太热衷于写Java桌面应用程序,他们都觉得用Java写界面既丑,速度又慢,而且很复杂。许多人认为,Java写不了好的桌面程序。好多初学Java的人,在刚学会Java语法之后,直接跳过桌面程序,成为了JavaEE程序员

确实,对于VB或者VC来说,用Java写桌面程序难度差的不是一个数量级。Java语言,本来就不适合快速开发,对于Java大部分的开发框架,本不是针对快速开发而言,而是为了更好的扩展与重构。

个人认为,Swing的难点在于复杂的布局管理器。只要吃透了这个,写Java桌面程序就简单了。

1.流式布局 (FlowLayout)

这是面板(JPanel)的默认布局管理器。流式布局管理器的特点是在一行上水平排列组件,直到没有足够的空间为止,这时开始新的一行。当用户缩放容器时,布局管理器自动地调整组件的位置使其填充可用的空间。

FlowLayout有三种构造方法,

  • FlowLayout() : 使用居中的对齐方式,组件间水平和垂直间距都为5。
  • FlowLayout(int align) : align表示对齐方式,可以是LEFT,CENTER或RIGHT。
  • FlowLayout(int align, int hgap, int vgap) : hgap 水平间距,vgap 垂直间距。

2.边界布局 (BorderLayout)

这是每个JFrame的内容窗格的默认布局管理器( JFrame.getContentPane() ).

边界布局管理器把组件分成5个区域,NORTH,SOUTH,EAST,WEST,CENTER。先放入边缘组件,当容器缩放的时候,边缘组件不会改变,而中部组件的大小会发生相应变化。

但是BorderLayout有一个问题,就是当添加多个组件到一个区域时,只显示最新添加的组件,而且组件会充满整个区域。解决的方法是在区域上添加一个面板(JPanel),在面板上放置多个组件。

 

3.箱式布局 (BoxLayout)

要想创建一个使用箱式布局的新容器,可以调用:

Box b = Box.createHorizontalBox();


或者

Box b = Box.createVerticalBox();


下面是添加组件的常用方法:

b.add(okButton);
b.add(cancelButtn);

在水平的箱子里,组件从左到右排列.在垂直的箱子里,组件从上到下排列。

下面详细的研究一下水平布局。

每个组件有三个尺寸,首选尺寸,最大尺寸,最小尺寸。

下面是箱式布局管理器的工作细节:

  1. 计算最高组件的最大高度。
  2. 尝试把所有的组件在垂直方向上增至这个高度。
  3. 如果一个组件没有增至这个高度,那么它的y对齐方式要通过调用getAlignmentY()方法获得。这个方法将返回一个介于0(顶端对齐)到1(底端对齐)之间的浮点数,组件的默认值是0.5。
  4. 获得每个组件的首选宽度,然后把所有首选宽度累加起来。
  5. 如果所有的首选宽度的总和小于箱的宽度,那么组件的宽度就会延伸到不超过最大宽度的值,直到适应箱的宽度为止。组件从左到右依次排列,并且相邻的组件之间没有空间。如果所有的首选宽度的总和大于箱的宽度,组件就会被压缩,但不会小于各自的最小宽度,直到适应箱子的宽度为止。如果组件的最小宽度之和大于箱的宽度,有些组件就会显示不出来。

默认情况下,箱式布局各组件是没有间距的。如果需要添加间距,可以添加不可见的填充件。有这样三种填充件:支柱,固定区,胶水。

b.add(label)
b.add(Box.createHorizontalStrut(10));
b.add(textField);


固定区填充件有点像一对支柱。例如:

b.add(Box.createRightArea(new Dimension(5,20)));

将添加一个宽度为5像素,高度是20像素的不可见区域。

胶水将组件互相拉开,直至充满整个空间。例如

b.add(button1);
b.add(Box.createGlue());
b.add(button2);

如果这个箱子不包含其他的组件,那么button1就会被放在最左边,button2就会被放置到最右边。

4.网格组布局 (GridBagLayout)

网格组布局是所有布局管理器之首。可以认为网格组布局是没有限制的网格布局。在网格组布局中,行和列的尺寸都可以改变。可以通过将响铃的单元合并来适应更大的组件。使用网格组布局可能相当复杂,但是它最灵活且使用范围最广。

要想使用网格组布局管理器进行布局,必须经过下列过程:

  1. 建立GridBagLayout类型的对象。不需要指定网格的行数和列数,布局管理器会根据后面所给的信息猜测出来。
  2. 把GridBagLayout对象设置成组件的布局管理器。
  3. 为每个组件建立一个GridBagConstraints类型的对象。设置GridBagConstraints对象的域值以便制定组件在网格组中的布局方案。
  4. 最后通过下面的调用添加组件的约束。
add(component,constrants);


示例代码:

JPanel panel = new JPanel();
JLabel label = new JLabel("Test");
 
GridBagLayout layout = new GridBagLayout();
panel.setLayout(layout);
GridBagConstraints constrants = new GridBagConstraints();
constrants.weightx = 100;
constrants.weighty = 100;
constrants.gridx = 0;
constrants.gridy = 2;
constrants.gridwidth = 2;
constrants.gridheight = 1;
panel.add(label, constrants);

 

知道如何设置GridBagConstraints对象的状态是很重要的,下面详细介绍GridBagConstraints的约束属性。

1.gridxgridy,gridwidth,gridheight

gridx,gridy表示组件在网格中的行列位置(第N行,第N列,从0开始计算)。gridwidth,gridheight表示组件所占的网格的行数和列数。示例代码中constrants应用的组件在第0行,第2列,横向占用2格,纵向占用1格。

2.weightx,weighty

增量字段,如果增量字段设置为0,这个区域永远是初始尺寸。默认增量字段的值为1,代表等比例拉伸组件大小。

3.fill

表示组件填充当前网格的属性。它有四个有效值,NONE,HORIZONTAL,VERTICAL,BOTH (为GridBagConstraints的static final成员变量),分表代表:不填充,横向填充,纵向填充,填充整个区域。

4.anchor

表示当组件在当前网格区域中的位置。有效值可以设置为CENTER,NORTH,SOUTH,NORTHEAST,EAST等。仅当组件没有充满整个区域时有效。

5.insets

表示外部填塞,用来设置组件周围增加的空白区域。通过设置Insets对象的left,right,top,button值在设置组件周围的空间量。

6.ipadx,ipady

表示内部填塞,该参数用以设置组件的最小尺寸。如果参数值为正值则组件的最小尺寸将比原始最小尺寸大,如果为负值,则组件的最小尺寸将会变得比原始的最小尺寸小。该参数也可以理解为直接为组件指定大小,这个设置的大小就是组件的最小尺寸。其设置后组件的大小为组件的原始最小尺寸加上ipadx(y)*2个像素。

对于GridBagLayout对象来说,本身也有columnWidths,rowHeights,columnWidths,rowWeights这四个属性。

1.columnWidths,rowHeights 设置一个int数组对象来表示各个网格的长度和宽度。例如

gbl.columnWidths = new int[] { 30, 80, 80, 80, 30 };
gbl.rowHeights = new int[] { 45, 200, 30, 45 };

表示网格中的前四列宽度为30,80,80,80,30,前四行宽度为45,200,30,45。

2.columnWeights,rowWeights 设置一个double数组对象来表示各个网格的长度和宽度的权重。当面板被拉伸时,会根据权重拉伸相对应的网格。权重为0表示不拉伸网格。为1表示等比例拉伸。

个人认为这个属性和GridBagConstraints中的weightx,weighty是一个意思,只是一个针对面板上的所有组件,一个针对相应组件而已。不过在实际的设计中,个人比较倾向于使用columnWeights, rowWeights而不是weightx,weighty。因为这样更全局,也更直观。

在使用GridBagLayout布局时,最好使用GridBagContraints帮助类(GBC)代替GridBagContraints类.这样会使得代码更加易读而且便于调试。

public class GBC extends GridBagConstraints {
 
	private static final long serialVersionUID = 2242355893259876283L;
 
	public GBC(int gridx, int gridy) {
		this.gridx = gridx;
		this.gridy = gridy;
	}
 
 
	public GBC(int gridx, int gridy, int gridwidth, int gridheight) {
		this.gridx = gridx;
		this.gridy = gridy;
		this.gridwidth = gridwidth;
		this.gridheight = gridheight;
	}
 
	public GBC setAnchor(int anchor) {
		this.anchor = anchor;
		return this;
	}
 
	public GBC setFill(int fill) {
		this.fill = fill;
		return this;
	}
 
	public GBC setWeight(double weightx, double weighty) {
		this.weightx = weightx;
		this.weighty = weighty;
		return this;
	}
 
	public GBC setInsets(int distance) {
		this.insets = new Insets(distance, distance, distance, distance);
		return this;
	}
 
	public GBC setIpad(int ipadx, int ipady) {
		this.ipadx = ipadx;
		this.ipady = ipady;
		return this;
	}
 
}


下面是帮助类的使用方法

panel.add(label,new GBC(0,2,2,1).setFill(GBC.BOTH).setInsets(1));

 

注:本文参考《Java2核心技术卷一:基础知识》部分内容。

分类: Java 标签: , ,

Log4J使用不完全指南

2010年5月4日 低调の华丽 没有评论

准备


登录apache.org,下载log4j最新jar文件。将jar文件导入到项目中.


快速应用



1.Log4J应用Demo

package com.log4j.test;
 
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
 
public class StartUp {
 
	public static Logger logger;
 
	public static void main(String[] args) {
		StartUp s = new StartUp();
		s.configLog4J();
		s.go();
	}
 
	private void configLog4J() {
		// 1.获取日志记录器,Name一般取本类的名字
		logger = Logger.getLogger(getClass().getName());
		// 2.配置Log4j环境
		// BasicConfigurator.configure();自动快速地使用缺省Log4j环境。
		// PropertyConfigurator.configure ( String configFilename);
		// 读取使用Java的特性文件编写的配置文件。
		// DOMConfigurator.configure ( String filename ) :读取XML形式的配置文件。
		PropertyConfigurator.configure("Log4j.properties");
 
	}
 
	private void go() {
		for (int i=0;i<100;i++) {
			logger.debug("test debug");
			logger.log(Level.INFO, "test info");
		}
	}
}

2.新建配置文件 Log4j.properties

log4j.rootLogger=INFO, A1 ,A2
 
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%-5p] [%t] %c - %m%n
 
log4j.appender.A2=org.apache.log4j.FileAppender
log4j.appender.A2.File=A2.log
log4j.appender.A2.Append=true
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=[%-5p] [%t] %c - %m%n

3.运行Demo即可看到效果

Log4J详细配置


log4j.rootLogger=INFO, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%-5p] [%t] %l - %m%n

1.配置根Logger,其语法为:

log4j.rootLogger = [ level ] , appenderName, appenderName, …

其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。

Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。
比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

2.配置日志信息输出目的地Appender,其语法为

log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.option = valueN
其中,Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

其中,Log4j提供的layout有以下几种:

org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

3.pattern

%c 输出类的名字,默认是输出全名,可以指定输出多少层次,比如
%c{2}这样配置的话 "a.b.c" 是全类名,会输出"b.c".
%d 用来输出log事件发生的时间。
可以指定格式,比如:%d{yyyy-MM-dd HH:mm:ss}会输出
2007-04-26 20:12:03
%F    输出log事件发生的文件。
%l    输出log事件发生的位置,会输出全类名和在源码的哪一行。
%L    输出log事件发生在源码的第几行。
%m    输出message的内容,就是logger.info(message)的内容。
%M    输出log事件发生的方法名。
%n    输出一个换行符。不用担心系统的问题。
%p    输出log事件的级别,即info,debug,warn等。
%r    输出log事件所用的时间。
%t    输出log事件所在的线程。
%x    输出NDC(不明白什么意思,没试验出来)
%X    输出MDC
%%    输出%
分类: Java 标签: , ,

一起来锐推

2010年2月27日 低调の华丽 3 条评论

微薄真是个不错的东西。从2007年上饭否,就渐渐爱上了这个互联网上的新生事物。我觉得,微薄绝对是继聊天室,bbs,im等之后的具有革命意义的互联网产品。
可惜,2009年中国互联网风云巨变,饭否等一大批国内微薄网站相继倒闭。之后,因为种种原因,我再没使用过微薄。

之后偶遇奶瓶腿,顿时茅塞顿开,转战推特。在我看来,国内微薄纯属垃圾。微薄之所以流行,是因为便捷的发布方式,随时,随地;畅通的交流渠道,可以和在世界上任何人进行交流;自由的表达途径,不受任何人干扰。而国内的微薄,后面两点是绝对做不到的。

我不愿意在一个封闭的,不自由的,收到监控的聊天环境下聊天。那样的聊天还有什么意思?虽然我写的东西几乎无关zz,可是我依然感觉到被束缚。我喜欢开心的时候大叫,生气的时候骂骂娘,无论我写什么,都没有人来横加干涉。其实这和我当初从新浪博客里搬出来的初衷是一样。Twitter是个很好的微薄。虽然被墙,但是由于它的开放api,可以在不访问官网的情况下看推和发推。国内有很多基于此的应用,包括桌面客户端,浏览器插件,web客户端等。当然,web客户端应该是最方便的,因为不需要下载,而且能在手机上使用。比较不错的Web客户端有推特中文圈和奶瓶腿。网上有很多关于如何架设的文章,可以搜索一下。

现在,除了谷歌阅读器,我又多了一个了解信息的渠道。twitter的信息简短精炼,真实可靠。这是一个完全民主的环境,人与人之间靠信息沟通,自由发表任何看法。作为一个低调的人,我常常看那些中文微薄牛人在那砍大山,乐此不彼。希望大家都能加入到twitter的大家庭来,一起锐推。我的推特是 @didiao,希望大家follow,呵呵!

Ps:由于突然断网,这篇文章是在我的M608c手机上完成(安装了一个wap插件),还算比较顺利。小小佩服下自己修手机的能力,我的M608c居然就这样复活了,哈哈!