John Jiang

a cup of Java, cheers!
https://github.com/johnshajiang/blog

   :: 首页 ::  :: 联系 :: 聚合  :: 管理 ::
  131 随笔 :: 1 文章 :: 530 评论 :: 0 Trackbacks
构建不规则窗体
在开发一个新浪微博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(400300));
                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(00);
            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(400300));
                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);
    }
}

执行上述程序后,会有如下图所示的效果,


posted on 2011-05-31 20:46 John Jiang 阅读(1970) 评论(0)  编辑  收藏 所属分类: JavaSEJavaSwingGUI原创

只有注册用户登录后才能发表评论。


网站导航: