Java创建透明与任意形状窗口
一: Java 2D图形基础知识
自从Java Swing发布以来,Java的图形能力得到了很大的提升,JDK6的高级版本开始支持创
建自定义形状的JFrame,结合Java 2D图形的相关API,可以实现任意形状JFrame的创建。当
前JAVA 2提供可以创建的基本形状如下:
当前Java提供的对2D图形的主要操作有裁剪和路径覆盖,适当的运用Java 2D与Swing的其
他相关API,可以创建出任意形状的JFrame。
二:API支持透明和自定义形状
从JDK6的release 10开始支持设置透明和自定义形状,支持的对象有Swing的JFrame, JDialog,
AWT的Frame.以及所以继承java.awt.Window的子类。
Windows的透明效果又分为两类,简单的透明效果和基于像素位的透明效果。简单透明效果使
用alpha来设置所有的象素位,值越小越透明,最小值是完全透明,最大值代表完全不透明
(opaque)windows, 基于像素为的透明效果需要通过以下API来启用:
AWTUtilities.setWindowOpaque (frame, false);
对于透明度和形状的设定都是通过Java的反射机制完成调用,在JDK的官方网站有一个很好的Demo里面有个AWTUtilitiesWrappe类是一个很好的示例.
三:一个可以改变自身形状与透明效果的JFrame
程序的主要功能是选择你想要的形状,然后点击【OK】按钮,应用程序的窗口随之改变
点击【Cancel】按钮将推出程序,移动鼠标到窗口上面,可以拖动窗口程序。
涉及到Swing组件有JFrame, JPanel, JButton, JComboBox
组件的位置放置使用了绝对定位的方式,需要调用setLayout(null)来声明绝对定位方式
程序启动的运行效果如下:
选择 Circle并点击【OK】按钮以后的效果如下:
选择 Area并点击【OK】按钮以后的效果如下:
主要的代码为JCustomFrame
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Shape; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import java.awt.geom.RoundRectangle2D; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.UIManager; public class JCustomFrame extends JFrame { /** * gloomy fish */ private static final long serialVersionUID = -523336873755438297L; private Shape shape; private float alpha = 1f; private Dimension arcSize = new Dimension(50, 50); protected static final int CIRCLE_TYPE = 1; protected static final int RECTANGEL_TYPE = 0; protected static final int AREA_TYPE = 2; public JCustomFrame() { setUndecorated(true); setVisible(true); setListenersForEffects(); } public JCustomFrame(int width, int height) { this(); setSize(width, height); } public JCustomFrame(Shape shape, int width, int height) { this(width, height); setShape(shape); } public void setShape(Shape shape) { this.shape = shape; } public JCustomFrame(float alpha, Shape shape, int width, int height) { this(shape, width, height); setAlpha(alpha); } public void setAlpha(float alpha) { this.alpha = alpha; } private void setListenersForEffects() { //It is important to upadate visual effect on form resize. addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent evt) { updateFrameEffects(); } }); } /** * This updates visual effects like SHAPE form and transparency. You have to * update also shape property or it paints old shape ( if you resize * frame without resize shape .. ) */ public void updateFrameEffects() { updateShape(); try { AWTUtilitiesWrapper.setWindowShape(this, shape); if (shape != null) { AWTUtilitiesWrapper.setWindowOpacity(this, alpha); } } catch (Exception ex) { Logger.getLogger(JCustomFrame.class.getName()).log(Level.SEVERE, null, ex); } } public void updateShape() { if(shape == null) { shape = new RoundRectangle2D.Double(0d, 0d, getWidth(), getHeight(), arcSize.width, arcSize.height); } } public void updateShape(int type) { if(type == RECTANGEL_TYPE) { shape = new RoundRectangle2D.Double(0d, 0d, getWidth(), getHeight(), arcSize.width, arcSize.height); } else if(type == CIRCLE_TYPE) { shape = new Ellipse2D.Double(0, 0,400, 400); } else if(type == AREA_TYPE) { Shape circle1 = new Ellipse2D.Double(0, 0,400, 400); Shape circle2 = new Ellipse2D.Double(200, 100,400, 400); Area area1 = new Area(circle1); Area area2 = new Area(circle2); area1.subtract(area2); shape = area1; } } public void center() { Toolkit tk = Toolkit.getDefaultToolkit(); Dimension screenSize = tk.getScreenSize(); int screenHeight = screenSize.height; int screenWidth = screenSize.width; this.setLocation((screenWidth - this.getWidth()) / 2, (screenHeight - this.getHeight()) / 2); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { // com.sun.java.swing.plaf.windows.WindowsLookAndFeel UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); } catch (Exception e) { } /*These are simple custom panel generated with vidual editor of Netbeans don't care about it, take a look only to ImagePanel inherit ( why?...) */ // Cool transparent Frame final JCustomFrame customFrame = new JCustomFrame(); customFrame.setLayout(new BorderLayout()); // create custom JPanel final JImagePanel panel = new JImagePanel(); java.net.URL image1 = this.getClass().getResource("ball.jpg"); try { panel.setImage(ImageIO.read(image1)); panel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("OK")) { System.out.println("Transfer now......"); customFrame.updateShape(panel.getSelectedIndex()); if(panel.getSelectedIndex() == CIRCLE_TYPE) { customFrame.setSize(400, 400); } else if(panel.getSelectedIndex() == AREA_TYPE) { customFrame.setSize(400, 399); // force layout Manager re-computation } else { customFrame.setSize(400, 300); } } else if(e.getActionCommand().equals("Cancel")) { System.out.println("System Exit......"); customFrame.setVisible(false); customFrame.dispose(); System.exit(0); } } }); } catch (IOException e) { e.printStackTrace(); } DragBarHandler dragHandle = new DragBarHandler(customFrame); customFrame.add(panel, BorderLayout.CENTER); customFrame.add(dragHandle, BorderLayout.NORTH); customFrame.setTitle("Ttranslucency JFrame"); customFrame.setSize(400, 300); customFrame.setAlpha(0.8f); customFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); customFrame.center(); } }); } }如果想要全部的源代码,留下E-Mail