一序言
关于Java做不好桌面的争论已经由来已久虽然Swing和JavaD已经有超过十年的历史也有JIDEJGoodiesTWaver等不少开源Swing组件但是用Java做桌面程序仍然不是一件轻松的事本《Java也惊艳》系列文章就是想通过一些简单生动的例子和大家一起认识Java探索Swing其实你只需要多一点创意多一点耐心你的Java程序也可以惊艳!本文就带您一起进入Java的水晶之恋
二立体水晶效果
受苹果公司的影响现在立体水晶风格的界面非常流行Java也可以吗?我们不妨先尝试一下用Java绘制一个立体水晶风格的按钮到底有多难一个立体的水晶按钮应当有一个图标一个圆角矩形区域边框以及一些立体反光效果如下图
简单思路如下先画矩形区域然后画图标然后设置clip并画高亮反光区域最后画外部边框
具体实现比较简单主要代码如下
Colorcolor=TWaverUtilgetRandomColor();
RoundRectangleDbody=newRoundRectangleDFloat(xysizesizesize/size/);
//drawbody
gdsetColor(color);
GradientPaintpaint=newGradientPaint(x
y
colordarker()
x
y+size
colorbrighter()brighter());
gdsetPaint(paint);
gdfill(body);
//drawimage
gdsetClip(body);
Imageimage=TWaverUtilgetImage(/glass/+i+png);
gddrawImage(image
x+(sizeimagegetWidth(null))/
y+(sizeimagegetHeight(null))/
null);
gdsetClip(null);
//drawhighlight
ShapehighlightArea=createHighlightShape(xysizebody);
gdsetColor(newColor());
gdfill(highlightArea);
//drawoutline
gdsetColor(colordarkGray);
gddraw(body);
其中对高亮区域的计算可以用一个圆心在左上方的大圆形和矩形进行剪切
privatestaticShapecreateHighlightShape(intcenterXintcenterYintsizeShapebody){
doublemyRadius=size*;
doublex=centerXsize*;
doubley=centerYsize*;
EllipseDDoublecircle=newEllipseDDouble(xymyRadiusmyRadius);
Areaarea=newArea(circle);
areaintersect(newArea(body));
returnarea;
}
运行程序效果如下
三更多变化
根据上面例子稍作形状变换可以画出立体水晶球的按钮
Colorcolor=TWaverUtilgetRandomColor();
EllipseDDoublecircle=newEllipseDDouble(centerXradiuscenterYradiusradius*radius*);
//drawbody
gdsetColor(color);
GradientPaintpaint=newGradientPaint(centerXcenterYcolorcenterXcenterY+radius*colorbrighter()brighter());
gdsetPaint(paint);
gdfill(circle);
//drawimage
gdsetClip(circle);
Imageimage=TWaverUtilgetImage(/glass/+i+png);
gddrawImage(image
centerXimagegetWidth(null)/
centerYimagegetHeight(null)/
null);
gdsetClip(null);
//drawhighlight
ShapehighlightArea=createHighlightShape(centerXcenterYradius);
gdsetColor(newColor());
gdfill(highlightArea);
唯一略有不同的部分是水晶球的高亮区域要用两个圆形拼切
privatestaticShapecreateHighlightShape(intcenterXintcenterYintradius){
doublemyRadius=radius*;
doublex=centerXmyRadius;
doubley=centerYmyRadiusmyRadius/;
doubley=centerYmyRadiusmyRadius/*;
EllipseDDoublecircle=newEllipseDDouble(xymyRadius*myRadius*);
EllipseDDoublecircle=newEllipseDDouble(xymyRadius*myRadius*);
Areaarea=newArea(circle);
areaintersect(newArea(circle));
returnarea;
}
运行效果如下
如果再来点儿循环随机大小随机位置随机颜色就可以做出绚丽的吹肥皂泡的效果
四融入Swing组件
以上例子仅使用了JavaD进行绘图在实际使用中需要将这些效果应用的Swing组件中例如按钮等一个简单的方式是将以上图形效果在内存中生成内存图片并封装到一个ImageIcon中然后将ImageIcon图标作为JButton的图标进行显示
publicstaticImagecreateImageIcon(Imagephantomintsize){
BufferedImagebi=newBufferedImage(sizesizeBufferedImageTYPE_INT_ARGB);
GraphicsDgd=bicreateGraphics();
gdsetRenderingHint(RenderingHintsKEY_ANTIALIASINGRenderingHintsVALUE_ANTIALIAS_ON);
intcenter=size/;
intradius=center;
//此处进行画图
gddispose();
returnbi;
}
然后用这些Icon创建一些按钮并显示
publicstaticvoidmain(String[]args)throwsException{
JFrameframe=newJFrame();
framegetContentPane()setLayout(newFlowLayout());
framegetContentPane()add(newJButton(按钮newImageIcon(createImageIcon(null))));
framegetContentPane()add(newJButton(按钮newImageIcon(createImageIcon(null))));
framegetContentPane()add(newJButton(按钮newImageIcon(createImageIcon(null))));
framegetContentPane()add(newJButton(使用JavaD创建的立体水晶风格的按钮newImageIcon(createImageIcon(null))));
framesetSize();
framesetTitle(Java也惊艳);
framesetDefaultCloseOperation(JFrameEXIT_ON_CLOSE);
TWaverUtilcenterWindow(frame);
framesetVisible(true);
}
效果如下图
本例子没有使用Look And Feel你也可以使用JGoodies来美化一下效果肯定更好
五总结
可以看出画出这类立体水晶效果并不难只需仔细观察这些效果的光学细节并用JavaD的API来实现即可这些例子稍作改进就可以用来绘制JButton等Swing组件并用在实际项目中或者也可以应用这些技巧来做一些复杂图形界面如在TWaver中做出的网络拓扑图效果
本文知识要点
■ 渐变填充这个使用GradientPaint就行了
■ 使用Clip类似蒙版/剪切的JavaD技术看看Graphics的setClip函数就明白了
■ Area的使用主要是Area的相交合并等几个常见图形处理手法详细请看javaawtgeomArea类
■ 生成内存图片主要是BufferedImage类的使用
如果大家感兴趣可以尝试用上述JavaD技巧实现下图效果
六参考资料
l
~hall/java/l