[Java] Swing set opaque

博客首页 » Java Swing set opaque

发布于 14 Mar 2015 14:53
标签 blog
http://blog.csdn.net/failure01/article/details/8227744

JscrollPane 设置透明
JScrollPane jsp = new JScrollPane();
jsp.setOpaque(false);
jsp.getViewport().setOpaque(false);

JList 设置透明
JList jl = new JList();
jl.setOpaque(false);
(JLabel)jl.getCellRenderer.setOpaque(false);

http://tieba.baidu.com/p/1908487364
关于如何让 Java 的窗体变成透明的、不规则的效果,其实一直有很多种方案,
而最经典的一种方式是这样的:
我们在窗体显示出来之前,先对窗体即将显示的区域进行截屏,
然后把截屏得到的图片给绘制到窗体的最底层面板上,来模拟一种“透明”的效果

这种方法其实被广泛应用着,
当然,它也有它的缺点,如果窗体的背景在不断变化,那么,很容易就穿帮
窗体在移动之后,也会穿帮,
但是如果你窗体的桌面背景是静态的,并且你也不需要移动它,
那这种方法非常适合你。

楼下放上代码:

方案一:

public class Test extends JFrame {

Image image;

public Test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setUndecorated(true);
setSize(400, 600);
setLocationRelativeTo(null);
try {
Robot robot = new Robot();
//对在窗体所在位置截屏
image = robot.createScreenCapture(getBounds());
} catch (AWTException e) {
e.printStackTrace();
}
BackPane pane = new BackPane();
pane.add(new JButton("ok"));
pane.add(new JButton("cancel"));
setContentPane(pane);
setVisible(true);
}

class BackPane extends JPanel {

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, null);
}
}

}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
new Test();
}
});
}

}

我对这个方案的建议是:如果这个方案已经足够满足需求,就尽量选择这个方案。

方案二:

从 Java 1.6_10 开始,有一种透明窗体的方案十分流行,
这就是:AWTUtilities
我们来看一下使用它他的代码:

class Test2 extends JFrame {

public Test2() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setUndecorated(true);
setSize(400, 600);
setLocationRelativeTo(null);
JPanel pane = new JPanel();
pane.add(new JButton("ok"));
pane.add(new JButton("cancel"));
setContentPane(pane);
AWTUtilities.setWindowOpaque(this, false);
setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
new Test2();
}
});
}
}

可以看出,代码简洁了很多,
一句 AWTUtilities.setWindowOpaque(this, false); 便能实现透明
并且,这是真正的透明窗体,不再会像方法一那样容易穿帮。

然而这种方法却存在很严重的问题:
1、AWTUtilities 不是 JDK 中提供 API 的类,而是一个内部使用类,
也就是说,它无法保证向下兼容,
而且在 Java 1.6_10 到 Java 1.7 之间,这个方法也不支持跨平台,很多平台下都会报错
2、效率极差,使用了这种效果后,会让你的整个程序变得很卡很卡,
而且有时侯还会出现异常的绘制,造成整个窗体失真。

因此,我对这个方案的建议是:不要使用。

方案三:

Java 7 中推出了一种官方的透明方案,只要一句简单的方法调用,便能透明:
我们只要把方法二中的一句话改掉就行:
AWTUtilities.setWindowOpaque(this, false);
改成:
setBackground(new Color(0,0,0,0));

也就是说,在 Java 7 中,你终于可以使用一种官方支持的透明方案了,
它可以跨平台,可以向下兼容,但是它依然存在问题。
因为它的底层实现其实和 AWTUtilities 是一样的,
效率的问题,依然没有解决,如果你一定要使用它,请保证你的程序不要太过复杂
而且要保证你的运行环境足够稳定。

因此,我对这个效果的评价是:华而不实、鸡肋。

——————————————————————————————————————

其实,我个人觉得,不规则的窗体、透明的窗体,只是一种华而不实的效果,
其实使用者很少会去注意这个细节,
然而如果你的程序效率很差,还会界面失真,则会很容易被别人注意到。
因此,如果你真的非常想要一个透明窗体的效果,那就尽量选择第一种方案吧。
在 Java 官方没有完全解决方案三的效率和失真问题之前,
还是忘记方案二和三那种华而不实的效果吧。

请问下,使用你的第一种方法,我在拖动鼠标的时候加上事件,
代码如下:this.addMouseListener(new MouseAdapter() {
@Overridepublic void mousePressed(MouseEvent e) {// 获取鼠标按下的位置point = e.getLocationOnScreen();}});
this.addMouseMotionListener(new MouseMotionListener() {
@Overridepublic void mouseMoved(MouseEvent e) {
}
@Overridepublic void mouseDragged(MouseEvent e) {Point currentPosition = e.getLocationOnScreen();image = robot.createScreenCapture(Test.this.getBounds());int offsetX = currentPosition.x - point.x;int offsetY = currentPosition.y - point.y;
Test.this.setLocation(Test.this.getLocation().x + offsetX,Test.this.getLocation().y + offsetY);point = currentPosition;pane.repaint();}});图片没有变是怎么回事?

收起回复28楼2013-10-13 09:08举报 |
个人企业举报
垃圾信息举报

windsun_ul: 第一种方法是最简单的处理,只有在第一次呈现时保证模拟的“透明”效果,一拖动就会露馅。希望拖动后依然“透明”的处理比较复杂,我没有在这个简单的例子中实现
2013-10-13 09:16回复

程序猿927: 回复 windsun_ul :对,确实是这样,从最通俗的角度理解应该就是程序在截屏所有的时间要比拖动后更新画面的时间久得多,所以导致在重绘的时候还是绘制原来的图片,是这样吧?拖动依然透明你是采用什么方式实现呢?
2013-10-13 12:41回复

windsun_ul: 回复 程序猿927 :,使用线程,很快的隐藏原窗体,对新区域截图,然后做为新底图,重绘后再把窗体显示出来,不过肯定会看到一些闪动
2013-10-13 13:46回复

程序猿927: 回复 windsun_ul :OK,谢谢!我等等试试。
2013-10-13 14:02回复

程序猿927: 回复 windsun_ul :按照你的思路可以将实现,而且我发现即使不用线程也可以实现,关键是在拖动的时候先将窗体隐藏,然后再显示出来。
2013-10-13 16:48回复


本页面的文字允许在知识共享 署名-相同方式共享 3.0协议和GNU自由文档许可证下修改和再使用,仅有一个特殊要求,请用链接方式注明文章引用出处及作者。请协助维护作者合法权益。


系列文章

文章列表

  • Java Swing set opaque

这篇文章对你有帮助吗,投个票吧?

rating: 0+x

留下你的评论

Add a New Comment