沉默了近一个月,终于有时间写Blog了。这些日子除了忙于工作还抽时间看Flex,发现ActionScript的编程思路和SWT、Swing有很多相似之处,而且语法也和Java很相似。总之我对Flex极为看好。今后可能要穿插地写些Flex的Blog了:)
前写日子看留言,有人说VB、VC的界面设计都是将界面保存成一个资源文件,这样能完全做到界面与逻辑的分离。我从事UI设计以来,用过像JBuilder、NetBeans的GUI拖拽工具,但是实现方式均是生成Java代码而已,这样不但容易造成偶合,而且工具生成的代码往往冗长。从我的项目经验来看,UI部分大多数代码出现在组件的创建与布局这一环节,如果你使用Matisse将组件布局设置成GridBagLayout或GroupLayout,再随便拖拽两三个空间上去,观察下代码,很长。而且不了解GridBagLayout和GroupLayout的非专业UI设计人员很难读懂。
“将界面保存成一个资源文件”类似想法早就有了,一直想通过xml配置将组件生成而非hardcoding。下一篇的文章将作详细介绍。在此之前,先解决一个bug,关于自定义布局类FormLayout和CenterLayout。这两个布局的preferredLayoutSize方法实现如下:
public Dimension preferredLayoutSize(Container target) {
return target.getPreferredSize();
}
其实是不对的,如果这样的话当容器没有设置setPreferredSize的话,运行时会产生堆栈溢出错误。解释下缘由。
java.awt.Container的getPreferredSize方法定义如下
public Dimension getPreferredSize() {
return preferredSize();
}
追踪到preferredSize:
@Deprecated
public Dimension preferredSize() {
/* Avoid grabbing the lock if a reasonable cached size value
* is available.
*/
Dimension dim = prefSize;
if (dim == null || !(isPreferredSizeSet() || isValid())) {
synchronized (getTreeLock()) {
prefSize = (layoutMgr != null) ?
layoutMgr.preferredLayoutSize(this) :
super.preferredSize();
dim = prefSize;
}
}
if (dim != null){
return new Dimension(dim);
}
else{
return dim;
}
}
发现如果prefSize为空等原因的话,可能返回布局类的layoutMgr.preferredLayoutSize方法。所以说,如果在布局类的preferredLayoutSize实现中返回容器的getPreferredSize,那么很可能陷入函数调用的循环中,最终导致堆栈溢出程序终止。类似的还有minimumLayoutSize和maximumLayoutSize方法,修复的实现如下:
public Dimension preferredLayoutSize(Container target) {
target.getPreferredSize();
synchronized (target.getTreeLock()) {
return new Dimension(0, 0);
}
}
预计周末发表《通过xml配置文件定义及布局组件》