在开发一个新浪微博客Swing户端的过程中希望能展现不规则的窗体界面,原来JDK 6 update 10提供了创建指定形状窗体的特性,简单易用,记于此处。(2010.05.31最后更新)
Java从JDK 6 update 10开 始将内建支持构建指定形状的窗体,类com.sun.awt.AWTUtilities中的方法setWindowShape会根据不同的Shape实现 去构造相应形状的窗体。AWTUtilities类是放在SUN的包中,在使用该方法时应该通过反射去进行调用,如下代码所示,
Class
<?>
clazz
=
Class.forName(
"
com.sun.awt.AWTUtilities
"
);
Method method
=
clazz.getMethod(
"
setWindowShape
"
, Window.
class
, Shape.
class
);
1. 创建正常窗体
先创建一个简单的界面,它使用BorderLayout,在其中安放5个JButton,如下代码所示,
public
class
ShapedFrame
extends
JFrame {
private
static
final
long
serialVersionUID
=
-
2291343874280454383L
;
private
JButton centerButton
=
new
JButton(
"
Center
"
);
public
ShapedFrame() {
super
(
"
Shaped Frame
"
);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initUI();
}
private
void
initUI() {
Container container
=
getContentPane();
container.setLayout(
new
BorderLayout());
container.add(
new
JButton(
"
TOP
"
), BorderLayout.PAGE_START);
container.add(
new
JButton(
"
RIGHT
"
), BorderLayout.LINE_END);
container.add(
new
JButton(
"
BOTTOM
"
), BorderLayout.PAGE_END);
container.add(
new
JButton(
"
LEFT
"
), BorderLayout.LINE_START);
container.add(centerButton, BorderLayout.CENTER);
}
public
static
void
main(String[] args) {
SwingUtilities.invokeLater(
new
Runnable() {
@Override
public
void
run() {
ShapedFrame frame
=
new
ShapedFrame();
frame.setSize(
new
Dimension(
400
,
300
));
frame.setUndecorated(
true
);
setAtCenter(frame);
frame.setVisible(
true
);
}
});
}
//
将Window置于屏幕正中
private
static
void
setAtCenter(Window window) {
Dimension screenSize
=
Toolkit.getDefaultToolkit().getScreenSize();
window.setLocation((screenSize.width
-
window.getWidth())
/
2
,
(screenSize.height
-
window.getHeight())
/
2
);
}
}
执行上述程序的效果如下图所示,
2. 创建不规则窗体
基于上述程序创建不规则窗体,使整个窗体正好缺失掉RIGHT JButton所在的区域,如下代码所示,
public
class
ShapedFrame
extends
JFrame {
private
static
final
long
serialVersionUID
=
-
2291343874280454383L
;
private
static
Method method
=
null
;
static
{
try
{
Class
<?>
clazz
=
Class.forName(
"
com.sun.awt.AWTUtilities
"
);
method
=
clazz.getMethod(
"
setWindowShape
"
, Window.
class
, Shape.
class
);
}
catch
(Exception e) {
e.printStackTrace();
}
}
private
JButton centerButton
=
new
JButton(
"
Center
"
);
public
ShapedFrame() {
super
(
"
Shaped Frame
"
);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initUI();
addComponentListener(componentListener);
}
private
void
initUI() {
Container container
=
getContentPane();
container.setLayout(
new
BorderLayout());
container.add(
new
JButton(
"
TOP
"
), BorderLayout.PAGE_START);
container.add(
new
JButton(
"
RIGHT
"
), BorderLayout.LINE_END);
container.add(
new
JButton(
"
BOTTOM
"
), BorderLayout.PAGE_END);
container.add(
new
JButton(
"
LEFT
"
), BorderLayout.LINE_START);
container.add(centerButton, BorderLayout.CENTER);
}
private
ComponentListener componentListener
=
new
ComponentAdapter() {
@Override
public
void
componentResized(ComponentEvent evt) { // 当UI组件(JFrame)的尺寸发生改变时,调用该方法
Rectangle frameRect
=
getBounds();
Rectangle spaceRect
=
centerButton.getBounds();
Point o1
=
new
Point(
0
,
0
);
Point o2
=
new
Point(frameRect.width,
0
);
Point o3
=
new
Point(frameRect.width, frameRect.height);
Point o4
=
new
Point(
0
, frameRect.height);
Point i1
=
new
Point(spaceRect.x
+
spaceRect.width, spaceRect.y);
Point i2
=
new
Point(frameRect.width, spaceRect.y);
Point i3
=
new
Point(frameRect.width, spaceRect.y
+
spaceRect.height);
Point i4
=
new
Point(spaceRect.x
+
spaceRect.width, spaceRect.y
+
spaceRect.height);
int
[] xpoints
=
new
int
[] { o1.x, o2.x, i2.x, i1.x, i4.x, i3.x, o3.x, o4.x };
int
[] ypoints
=
new
int
[] { o1.y, o2.y, i2.y, i1.y, i4.y, i3.y, o3.y, o4.y };
int
npoints
=
8
// 构建一个六边形,将RIGHT JButton所处的位置空缺出来
Shape shape
=
new
Polygon(xpoints, ypoints, npoints);
setWindowShape(ShapedFrame.
this
, shape);
}
};
//
设置Window的形状
private
static
void
setWindowShape(Window window, Shape shape) {
try
{
method.invoke(
null
, window, shape);
}
catch
(Exception e) {
e.printStackTrace();
}
}
public
static
void
main(String[] args) {
SwingUtilities.invokeLater(
new
Runnable() {
@Override
public
void
run() {
ShapedFrame frame
=
new
ShapedFrame();
frame.setSize(
new
Dimension(
400
,
300
));
frame.setUndecorated(
true
);
setAtCenter(frame);
frame.setVisible(
true
);
}
});
}
//
将Window置于屏幕正中
private
static
void
setAtCenter(Window window) {
Dimension screenSize
=
Toolkit.getDefaultToolkit().getScreenSize();
window.setLocation((screenSize.width
-
window.getWidth())
/
2
,
(screenSize.height
-
window.getHeight())
/
2
);
}
}
执行上述程序后,会有如下图所示的效果,