TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
一、序言
关于“java做不好桌面”的争论已经由来已久。虽然Swing和Java2D已经有超过十年的历史,也有JIDE、JGoodies、TWaver等不少开源Swing组件,但是用Java做桌面程序仍然不是一件轻松的事。本《Java也惊艳》系列文章,就是想通过一些简单生动的例子,和大家一起认识Java、探索Swing。其实你只需要多一点创意、多一点耐心,你的Java程序也可以“惊艳”!本文就带您一起进入Java的“水晶之恋”。
二、立体水晶效果
受苹果公司的影响,现在立体水晶风格的界面非常流行。Java也可以吗?我们不妨先尝试一下用Java绘制一个立体水晶风格的按钮到底有多难。一个立体的水晶按钮应当有一个图标、一个圆角矩形区域、边框以及一些立体反光效果,如下图:

简单思路如下:先画矩形区域,然后画图标,然后设置clip并画高亮反光区域,最后画外部边框。
具体实现比较简单,主要代码如下:
Color color =
TWaverUtil.getRandomColor();
RoundRectangle2D body = new RoundRectangle2D.Float(x, y, size, size, size / 3, size / 3
);
//draw body
g2d.setColor(color);
GradientPaint paint = new
GradientPaint(x,
y,
color.darker(),
x,
y +
size,
color.brighter().brighter());
g2d.setPaint(paint);
g2d.fill(body);
//draw image
g2d.setClip(body);
Image image = TWaverUtil.getImage("/glass/" + i + ".png"
);
g2d.drawImage(image,
x + (size - image.getWidth(null)) / 2
,
y + (size - image.getHeight(null)) / 2
,
null
);
g2d.setClip(null
);
//draw highlight.
Shape highlightArea =
createHighlightShape(x, y, size, body);
g2d.setColor(new Color(255, 255, 255, 150
));
g2d.fill(highlightArea);
//draw outline.
g2d.setColor(color.darkGray);
g2d.draw(body);
其中,对高亮区域的计算,可以用一个圆心在左上方的大圆形和矩形进行剪切:
private static Shape createHighlightShape(int centerX, int centerY, int
size, Shape body) {
double myRadius = size * 4
;
double x = centerX - size * 2.3
;
double y = centerY - size * 3.2
;
Ellipse2D.Double circle = new
Ellipse2D.Double(x, y, myRadius, myRadius);
Area area = new
Area(circle);
area.intersect(new
Area(body));
return
area;
}
运行程序效果如下:
三、更多变化 根据上面例子稍作形状变换,可以画出立体水晶球的按钮。
Color color =
TWaverUtil.getRandomColor();
Ellipse2D.Double circle = new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2
);
//draw body
g2d.setColor(color);
GradientPaint paint = new GradientPaint(centerX, centerY, color, centerX, centerY + radius * 2
, color.brighter().brighter());
g2d.setPaint(paint);
g2d.fill(circle);
//draw image
g2d.setClip(circle);
Image image = TWaverUtil.getImage("/glass/" + i + ".png"
);
g2d.drawImage(image,
centerX - image.getWidth(null) / 2
,
centerY - image.getHeight(null) / 2
,
null
);
g2d.setClip(null
);
//draw highlight.
Shape highlightArea =
createHighlightShape(centerX, centerY, radius);
g2d.setColor(new Color(255, 255, 255, 150
));
g2d.fill(highlightArea);
唯一略有不同的部分是,水晶球的高亮区域要用两个圆形拼切:
private static Shape createHighlightShape(int centerX, int centerY, int
radius) {
double myRadius = radius * 0.8
;
double x = centerX -
myRadius;
double y1 = centerY - myRadius - myRadius / 5
;
double y2 = centerY - myRadius - myRadius / 5 * 2
;
Ellipse2D.Double circle1 = new Ellipse2D.Double(x, y1, myRadius * 2, myRadius * 2
);
Ellipse2D.Double circle2 = new Ellipse2D.Double(x, y2, myRadius * 2, myRadius * 2
);
Area area = new
Area(circle1);
area.intersect(new
Area(circle2));
return
area;
}
运行效果如下:

如果再来点儿循环、随机大小、随机位置、随机颜色,就可以做出绚丽的“吹肥皂泡”的效果

四、融入Swing组件
以上例子仅使用了Java2D进行绘图。在实际使用中,需要将这些效果应用的Swing组件中,例如按钮等。一个简单的方式是:将以上图形效果在内存中生成内存图片并封装到一个ImageIcon中,然后将ImageIcon图标作为JButton的图标进行显示。
public static Image createImageIcon(Image phantom, int
size) {
BufferedImage bi = new
BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d =
bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int center = size / 2
;
int radius =
center;
//此处进行画图
g2d.dispose();
return
bi;
}
然后,用这些Icon创建一些按钮并显示:
public static void main(String[] args) throws
Exception {
JFrame frame = new
JFrame();
frame.getContentPane().setLayout(new
FlowLayout());
frame.getContentPane().add(new JButton("按钮1", new ImageIcon(createImageIcon(null, 60
))));
frame.getContentPane().add(new JButton("按钮2", new ImageIcon(createImageIcon(null, 60
))));
frame.getContentPane().add(new JButton("按钮3", new ImageIcon(createImageIcon(null, 60
))));
frame.getContentPane().add(new JButton("使用Java2D创建的立体水晶风格的按钮", new ImageIcon(createImageIcon(null, 30
))));
frame.setSize(500, 300
);
frame.setTitle("Java也惊艳"
);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TWaverUtil.centerWindow(frame);
frame.setVisible(true
);
}
效果如下图:
本例子没有使用Look And Feel。你也可以使用JGoodies来美化一下,效果肯定更好。
五、总结 可以看出,画出这类立体水晶效果并不难,只需仔细观察这些效果的光学细节,并用Java2D的API来实现即可。这些例子稍作改进,就可以用来绘制JButton等Swing组件,并用在实际项目中。或者,也可以应用这些技巧来做一些复杂图形界面,如在TWaver中做出的网络拓扑图效果:
本文知识要点:
n 渐变填充:这个使用GradientPaint就行了;
n 使用Clip:类似蒙版/剪切的Java2D技术。看看Graphics的setClip函数就明白了;
n Area的使用:主要是Area的相交、合并等几个常见图形处理手法。详细请看java.awt.geom.Area类;
n 生成内存图片:主要是BufferedImage类的使用;
如果大家感兴趣,可以尝试用上述Java2D技巧实现下图效果:

以上内容转载请注明 |
|