您的位置:首页 > 其它

Swing 不规则窗体的制作

2013-08-23 19:13 127 查看
终极解决之道
经过反复的研究探索,终于获得了一个完美的解决方法:不用shape、不用抓图、不用workaround,真正的、彻底的、完全的、随意的在桌面上任意绘图、涂鸦、撒野,真正的属于程序员的Freedom!下面就来一起揭开这层窗户纸吧!

在程序中依次设置以下几个参数:

设置窗口完全透明:AWTUtilities.setWindowOpaque(frame, false);
设置窗口无边缘:frame.setUndecorated(true);
设置窗口的ContentPane为要显示的Pane:frame.setContentPane(myPane);
在myPane中放置具体要显示的内容,也可以重载paint方法进行Java2D绘制。这些paint会直接发生在桌面背景上。
接下来,就是见证奇迹的时刻!



(不好意思,暴露我的桌面了)

通过上面方法,可以做一个任意大小、任意位置的window,在相应的桌面位置上随意显示Swing组件,或做任意Java2D画图。比如下面小例子可以在屏幕上直接画一个红色的立体矩形,而没有显示窗口:

Java代码


import com.sun.awt.AWTUtilities;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.setBounds(500, 500, 300, 300);
AWTUtilities.setWindowOpaque(frame, false);

JPanel pane = new JPanel() {

@Override
public void paint(Graphics g) {
super.paint(g);

g.setColor(Color.red);
g.fill3DRect(10, 10, 100, 100, true);
}
};

frame.setContentPane(pane);

frame.setVisible(true);
}
}


运行效果如下图:



窗口的拖拽移动

窗口不再规则,窗口标题栏不再出现,如何移动窗口?按照其他类似软件的习惯做法,应当允许用鼠标直接拖拽窗体任意位置进行窗口移动。做一个鼠标监听器对窗口中的元素进行拖动监听,对窗口进行相应拖动距离的移动:

Java代码


private MouseAdapter moveWindowListener = new MouseAdapter() {

private Point lastPoint = null;

@Override
public void mousePressed(MouseEvent e) {
lastPoint = e.getLocationOnScreen();
}

@Override
public void mouseDragged(MouseEvent e) {
Point point = e.getLocationOnScreen();
int offsetX = point.x - lastPoint.x;
int offsetY = point.y - lastPoint.y;
Rectangle bounds = FreeLoginUI.this.getBounds();
bounds.x += offsetX;
bounds.y += offsetY;
FreeLoginUI.this.setBounds(bounds);
lastPoint = point;
}
};


对窗体上的组件安装这一listener,就可以对窗口中任意元素进行拖拽,直接拖动窗体四处晃悠了。

图片的切割

要做好的界面,需要一个耐心、有创意的美工大力协助,例如图片的切割就很重要。下图展示了如何从效果图进行具体切割素材:



制作渐变背景Panel

仔细观察中间的输入区域部分,其背景是有渐变设计的。其制作方法也很简单:首先让美工帮助制作一个一个像素宽、整个panel高度的小图片作为素材;然后用这个图片创建纹理Paint;最后用这个纹理对真个panel进行fill。

Java代码


private JPanel inputPane = new JPanel() {

private String backgroundImageURL = FreeUtil.getImageURL("login_background.png");
private TexturePaint paint = FreeUtil.createTexturePaint(backgroundImageURL);

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(paint);
g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
}
};


肆虐你的桌面:六月飘雪!

既然窗户纸捅破了,在桌面上就随意折腾吧。这几天窗外酷热难耐,咱们就来个桌面飘雪,也许可以望梅止渴,带来丝丝清凉吧!

先准备一个雪花的png透明图片,然后在桌面上随机生成50个雪花坐标,每次paint让每个雪花的左右略微抖一下(snowX[i] += TWaverUtil.getRandomInt(5) - 3),垂直距离下坠5像素(snowY[i] += 5),再旋转个小角度。然后,用一个线程不停的repaint窗口。

雪花png图片:



程序代码如下:

Java代码


public class TestSnow {

public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
AWTUtilities.setWindowOpaque(frame, false);

final JPanel pane = new JPanel() {

private int[] snowX = null;
private int[] snowY = null;
private int[] angles = null;
private int count = 50;

@Override
public void paint(Graphics g) {
super.paint(g);
Rectangle bounds = frame.getBounds();
if (snowX == null) {

snowX = new int[count];
for (int i = 0; i < snowX.length; i++) {
snowX[i] = TWaverUtil.getRandomInt(bounds.width);
}
snowY = new int[count];
for (int i = 0; i < snowY.length; i++) {
snowY[i] = TWaverUtil.getRandomInt(bounds.height);
}
angles = new int[count];
for (int i = 0; i < snowY.length; i++) {
angles[i] = TWaverUtil.getRandomInt(360);
}
}

Graphics2D g2d = (Graphics2D) g;
Image image = TWaverUtil.getImage("/free/test/snow.png");
for (int i = 0; i < count; i++) {
snowX[i] += TWaverUtil.getRandomInt(5) - 3;
snowY[i] += 5;
angles[i] += i / 5;
snowY[i] = snowY[i] > bounds.height ? 0 : snowY[i];
angles[i] = angles[i] > 360 ? 0 : angles[i];
int x = snowX[i];
int y = snowY[i];
int angle = angles[i];
g2d.translate(x, y);
double angleValue = Math.toRadians(angle);
g2d.rotate(angleValue);
g2d.drawImage(image, 0, 0, null);
g2d.rotate(-angleValue);
g2d.translate(-x, -y);
}
}
};

frame.setContentPane(pane);
frame.setVisible(true);
Thread thread = new Thread() {

@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (Exception ex) {
ex.printStackTrace();
}
pane.repaint();
}
}
};

thread.start();
}
}


快快运行代码,让雪花飘起来吧!



如果愿意折腾,还可以修改代码中的:

private int count = 50,调整雪花的数量;
修改angles[i] += i / 5,调整雪花翻滚的速度;
修改snowY[i] += 5,调整雪花下坠的速度;
修改snowX[i] += TWaverUtil.getRandomInt(5) – 3,调整雪花左右摆动的速度;

别说你不知道怎么结束程序啊,不会Alt+F4的话,你这个程序员肯定不合格了。

秘密背后的秘密

当把透明窗口Frame设置特别大以后(例如10000*10000),你会发现不但界面变得极其缓慢,而且还会内存溢出。Sun的秘密不言自明了:还是使用了BufferedImage。否则,鼠标点击你画的椭圆或桌面的图标,它如何知道是点击了窗体,还是操作了桌面?只能生成内存图片,在里面进行像素判断了。要挖掘再深入的秘密,我也不清楚了,自己继续探索吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: