SWT行,AWT/Swing也行系列(1)-实现半透明及不规则窗体

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
对于Java来说,GUI开发一直都是项比较头疼的事情。从AWT的功能奇缺,到Swing的臃肿不堪,往如梦魇般困扰着Java开发人员。

于是,有一群人开始走向了邪路……

这群误入岐途的人(至少Sun是这么认为的……),走出了自己的一条路,名为SWT(Standard Widget Toolkit)的不归路(Sun,Sun|||)。

说起SWT冒着被诟病为邪恶所换取的,无外以下几点:

1.彻底摒弃了AWT/Swing,某种意义上甚至架空了JVM,比如其通过dispose()即时释放资源。(当然,大家也都知道这意味着什么)

2.功能几乎全用本地系统完成,所以其界面与本地程序界面也高度一致,一改Java GUI的沉闷,令人眼前一亮。

3.支持本地API调用,也就是说无论本地系统能实现什么,都可以通过SWT照样实现出来。

4.使用"用户线程"作为唯一线程,只有在这个线程中才能调用对构件或某些图形API的访问操作,减少图形操作时线程错误。但也允许间接的在非用户线程的进行图形构件的访问操作。

5.在Windows下运行速度有保证,明显超越AWT/Swing,且较稳定。

6.目前已有较丰富的组件库,有JFace等辅助项目,借助于IDE之利,开发GUI程序速度N快……

但是,只所以被称为邪道,也不是空穴来风,它的缺陷也是显而易见的,比如:

1.JNI调用耗费的时间是不能忽略的。JNI调用速度要比普通Java方法调用慢好几倍甚至几十倍。即便是在Java 6中,这种情况并没有改善。且Swing绝大部分是用Java平台模拟出的组件,这个过程都在一个系统平台内完成。而SWT是部分在本地系统完成,部分在Java平台完成,进行操作时要在这两个平台之间需要进行频繁的数据交互。SWT并没有从根本上解决效率问题。

2.Swing可以享受JVM的特殊待遇,进行特殊优化,比如inline,JIT代码,Swing事件队列对于事件的预处理(合并Paint事件,批处理Java 2D光栅指令等),这就像本地组件可以利用操作系统进行优化一样。而SWT由于采用本地操作,无法完成。

3.SWT只能自顶向下地构建GUI。因此,如果没有父容器,子控件也就不存在,父容器无法在以后任意改变。不如AWT/Swing灵活。

4.在目前来讲,SWT还是一个有限的图形环境(Sun,依旧是Sun)。到目前为止,它对于Java2D和Java3D的支持还不怎么好。

5.SWT在Windows下速度虽快,是占了Microsoft提供的大量API之利,在其他平台上则持平或较慢于AWT/Swing。

6.与AWT/Swing不同,SWT和JFace并不是Java技术的标准配置,需要在将JAR文件放到Java CLASSPATH中,并将DLL文件放到系统PATH中才能运行,较AWT/Swing更繁琐,如果某天Sun大神发威,和标准JRE兼容都可能成为问题。

两种论调势成水火,各不相下,似乎都要彻底压到另一方才可罢休。

其实我认为大可不必,使用何种技术,大体上只有开发人员才会关心,技术外的那些才是用户所关心的。开发人员间再怎么争辩,其实在外人眼里都是无意义的窝里斗罢了。

比如,SWT可以包含AWT/Swing,而在AWT/Swing下,要实现SWT的功能也是轻而易举的。

我举几个程序的例子。

AWT/Swing与SWT透明窗体实现的比较:

在SWT中,由于高度集成本地环境,能够完成很多AWT/Swing力所不能及,很Cool的工作,比如半透明的窗体,代码如下:
package  org.loon.framework.dll.test;

import  org.eclipse.swt.SWT;
import  org.eclipse.swt.graphics.Point;
import  org.eclipse.swt.internal.win32.OS;
import  org.eclipse.swt.internal.win32.TCHAR;
import  org.eclipse.swt.layout.FillLayout;
import  org.eclipse.swt.widgets.Display;
import  org.eclipse.swt.widgets.Shell;

/**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * 
@author chenpeng
 * @email:ceponline@yahoo.com.cn
 * 
@version 0.1
 
*/

public   class  SWTTransTest  {

    
/**
     * 
@param args
     
*/

    
public static void main(String[] args) {
        Display display 
= new Display();

        Shell shell 
= new Shell(display, SWT.CLOSE);
        shell.setSize(
new Point(400400));
        shell.setLayout(
new FillLayout());
        shell.setText(
"SWT半透明窗体实现");

        
// 打开shell
        shell.open();

        
// 设置窗体透明
        OS.SetWindowLong(shell.handle, OS.GWL_EXSTYLE, OS.GetWindowLong(
                shell.handle, OS.GWL_EXSTYLE) 
^ 0x80000);
        
// load User32.dll lib
        TCHAR lpLibFileName = new TCHAR(0"User32.dll"true);
        
int hInst = OS.LoadLibrary(lpLibFileName);
        
if (hInst != 0{
            
// 设定调用函数名称
            String name = "SetLayeredWindowAttributes�";
            
byte[] lpProcName = new byte[name.length()];
            
for (int i = 0; i < lpProcName.length; i++{
                lpProcName[i] 
= (byte) name.charAt(i);
            }

            
// 检索DLL输出函数地址
            int fun = OS.GetProcAddress(hInst, lpProcName);
            
// 当函数存在
            if (fun != 0{
                
// 150为透明度,在0-255之间
                OS.CallWindowProc(fun, shell.handle, 01502);
            }

            
// 释放lib
            OS.FreeLibrary(hInst);

            
while (!shell.isDisposed()) {
                
if (!display.readAndDispatch()) {
                    display.sleep();
                }


            }


        }


    }

}


效果如图:



嗯,很简单,很方便.

不过,似乎有个问题,这些反复出现的OS,不就是封装的Win32 API吗?那么,SWT由于依赖本地平台能够实现,那么Swing那种"画"出来的界面可以实现吗?答案是肯定的,事实上,没有一种界面不是系统"画"来的,只要能获得窗体的hWnd,也就是句柄,任何窗体的操作都是张飞吃豆芽-小菜一碟罢了.

下面,我用AWT/Swing完成同样的操作.

package  org.loon.framework.dll.test;


import  java.awt.Frame;
import  java.awt.event.WindowAdapter;
import  java.awt.event.WindowEvent;

import  javax.swing.JFrame;


import  org.loon.framework.dll.NativeLoader;

/**
 * <p>Title: LoonFramework</p>
 * <p>Description:AWT/SWing实现真窗体透明</p>
 * <p>Copyright: Copyright (c) 2007</p>
 * <p>Company: LoonFramework</p>
 * 
@author chenpeng  
 * @email:ceponline@yahoo.com.cn 
 * 
@version 0.1
 
*/

public   class  TransTest  {
    
public static void main(final String[] args) {
        
        
//助于SetLayeredWindowAttributes函数,
        
//在Windows下,AWT/SWing要实现不规则窗体、半透明窗体是非常容易的
        JFrame frame = new JFrame("透明窗体测试");
        
//Frame frame = new Frame("透明窗体测试");
        /*frame.addWindowListener(new WindowAdapter(){
        public void windowClosing(WindowEvent we){
            System.exit(0);
        }
        });
*/

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(
true);
        
//NativeLoader为制作好的本地API集合, 0.6f为透明度60%显示
        NativeLoader.getInstance().setTransparence(frame, 0.6f);
        frame.setSize(
400400);
        frame.setLocationRelativeTo(
null);

    }

}



效果图:



事实上,我们只要在 NativeLoader中通过当前object在jawt.dll中的运行时hWnd,(即AWT窗体的hWnd,因为Swing底层是AWT,两者一至),与SWT是没有任何区别的.

再比如在AWT/Swing中,似乎很难实现真正的不规则窗体,充其量只能做一些"伪不规则窗体",而SWT借助本地支持却能轻易实现.

AWT/Swing与SWT不规则窗体实现的比较:

比如SWT实现不规则窗体.

package  org.loon.framework.dll.test;

import  org.eclipse.swt.SWT;
import  org.eclipse.swt.graphics.Image;
import  org.eclipse.swt.graphics.ImageData;
import  org.eclipse.swt.graphics.Point;
import  org.eclipse.swt.graphics.Region;
import  org.eclipse.swt.widgets.Display;
import  org.eclipse.swt.widgets.Event;
import  org.eclipse.swt.widgets.Listener;
import  org.eclipse.swt.widgets.Shell;

/**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * 
@author chenpeng
 * @email:ceponline@yahoo.com.cn
 * 
@version 0.1
 
*/

public   class  SWTWindowFrm  {

    
private Shell shell;

    
private Display display = Display.getDefault();

    
private Image image = null;

    
private ImageData imageData = null;

    
public static void main(String[] args) {
        
try {
            SWTWindowFrm window 
= new SWTWindowFrm();
            window.open();
        }
 catch (Exception e) {
            e.printStackTrace();
        }

    }


    
public void open() {
        createUI();
        shell.open();
        shell.layout();
        
while (!shell.isDisposed()) {
            
if (!display.readAndDispatch())
                display.sleep();
        }

    }


    
protected void createUI() {
        shell 
= new Shell(display, SWT.NO_TRIM);
        shell.setSize(
500375);
        shell.setText(
"SWT实现不规则窗体");
        createShell();
        Listener listener 
= new Listener() {
            
int startX, startY;

            
public void handleEvent(Event e) {
                
// 注入鼠标事件
                if (e.type == SWT.MouseDown && e.button == 1{
                    startX 
= e.x;
                    startY 
= e.y;
                }

                
if (e.type == SWT.MouseMove && (e.stateMask & SWT.BUTTON1) != 0{
                    Point p 
= shell.toDisplay(e.x, e.y);
                    p.x 
-= startX;
                    p.y 
-= startY;
                    shell.setLocation(p);
                }

                
if (e.type == SWT.Paint) {
                    e.gc.drawImage(image, imageData.x, imageData.y);
                }

            }

        }
;

        shell.addListener(SWT.KeyDown, listener);
        shell.addListener(SWT.MouseDown, listener);
        shell.addListener(SWT.MouseMove, listener);
        shell.addListener(SWT.Paint, listener);

    }


    
protected void createShell() {

        String path 
= this.getClass().getResource("role.gif").getPath();
        image 
= new Image(display, new ImageData(path));
        Region region 
= new Region();
        imageData 
= image.getImageData();
        
// 将255(白色)定为透明区域,镂空
        if (imageData.alphaData != null{
            
for (int y = 0; y < imageData.height; y++{
                
for (int x = 0; x < imageData.width; x++{
                    
if (imageData.getAlpha(x, y) == 255{
                        region.add(imageData.x 
+ x, imageData.y + y, 11);
                    }

                }

            }

        }
 else {
            ImageData mask 
= imageData.getTransparencyMask();
            
for (int y = 0; y < mask.height; y++{
                
for (int x = 0; x < mask.width; x++{
                    
if (mask.getPixel(x, y) != 0{
                        region.add(imageData.x 
+ x, imageData.y + y, 11);
                    }

                }

            }

        }

        shell.setRegion(region);
        shell.setSize(imageData.x 
+ imageData.width, imageData.y
                
+ imageData.height);

    }


}


效果图如下:



但是,AWT/Swing做不到吗?我已经说过了,只要能得到句柄,就没有修改不了的窗体存在.而AWT/Swing显然是可以得到运行时本地句柄的.

下面来个AWT/Swing实现:

package  org.loon.framework.dll.test;

import  java.awt.Image;
import  java.awt.Point;

import  java.awt.Window;
import  java.awt.event.FocusEvent;
import  java.awt.event.FocusListener;
import  java.awt.event.MouseEvent;
import  java.awt.event.MouseMotionListener;
import  java.awt.image.BufferedImage;
import  java.io.File;
import  java.io.IOException;

import  javax.imageio.ImageIO;

import  org.loon.framework.dll.win32.UIWindow;

/**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * 
@author chenpeng
 * @email:ceponline@yahoo.com.cn
 * 
@version 0.1
 
*/

//  UIWindow为本人提供类,内部已设置255为镂空色
public   class  MyJWindow  extends  UIWindow  implements  MouseMotionListener,
        FocusListener 
{

    
private static final long serialVersionUID = 1L;

    Point mousePointer;

    
public MyJWindow(Image img) {
        
super(img);
        init();

    }


    
public void init() {

        addMouseMotionListener(
this);
        addFocusListener(
this);

    }


    
public void focusGained(FocusEvent aFocusEvent) {
        Point aPoint 
= getLocation();
        setLocation(
150000);

        setLocation(aPoint);
    }


    
public void focusLost(FocusEvent aFocusEvent) {
    }


    
public void mouseDragged(MouseEvent aMouseEvent) {
        Point aPoint 
= aMouseEvent.getPoint();
        
int x = getX() + aPoint.x - mousePointer.x;
        
int y = getY() + aPoint.y - mousePointer.y;
        setLocation(x, y);

    }


    
public void mouseMoved(MouseEvent aMouseEvent) {
        mousePointer 
= aMouseEvent.getPoint();
    }


    
public static void main(String[] args) {

        String path 
= MyJWindow.class.getResource("role.gif").getPath();
        BufferedImage backgroundImage 
= null;
        
try {
            backgroundImage 
= ImageIO.read(new File(path));
        }
 catch (IOException e) {
            e.printStackTrace();
        }

        Window window 
= new MyJWindow(backgroundImage);
        window.setBounds(
00, backgroundImage.getWidth(null), backgroundImage
                .getHeight(
null));
        window.setLocationRelativeTo(
null);
        window.setVisible(
true);
        window.validate();
    }

}


效果如下图:



两者有区别吗?

我们可以从此得知,不,可以说确信,在同样利用本地API时,SWT与AWT/Swing相比是没有太大优势的.而且Sun已经开始优化AWT对本地系统的支持,再不久的将来,SWT可能将没有任何优势可言了^^(我是亲Sun一派~)

其中org.loon.framework.dll包下载路径位于: loonframework-dll
SWT AWT/Swing系列 1 -实现半透明不规则窗体 阅读详情

相关推荐

JAVA图形化界面开发工具SWingswt的windowbuilder

JAVA图形化界面开发集成环境,含eclipse,Swing,windowbuilder

SWTSwing区别

笔者过去学习过Swing(也算是AWT的增强版吧), 现在开始学习一下 SWT, 还没有开始深入 JFace 和 RCP, 一步步来吧。 先学好基础的, 又不用着急做项目用。 本文讨论的内容仅限于我已知的 SWTSwing 范围, 希望能对有 Swing 经验的人快速了解 SWT 有所帮助。     第一个不同点就是 SWT 的类库结构不像 Swing, 没有单一的父组件。 SWT 中有好几个

Stroller 1万+

细说Java GUI:AWTSWTSwing

历史 Internet上有许多围绕这一争论的故事。你可能已经听说过它们中的大多数了,其中之一有助于让你理清头绪,让我们就从这里开始,Amy Fowler是Swing阵营的一个倡导者。 回到上个世纪90年代,曾几何时有3家庞大的Smalltalk公司——IBM、Parc-Place和 Digitalk。在90年代初期3家公司的市场份额大致相等,生活是美好的。Parc-Place采用仿窗口部件(emulated widgets)的设计(即Swing的设计),IB...

顺其自然~专栏 2229

java swing面板设置透明度_Java Swing-导致伪像的半透明组件

我目前正在为大学课程进小组项目,但遇到了一些绊脚石.我们已决定要实现的程序是一个具有中央服务器的对等聊天客户端,该服务器用于存储和共享用户名等.我被分配来做GUI.一位朋友开玩笑地建议我加入“火红的背景!”所以我决定这样做,但是要有一个用户选择的背景图像.照原样,只有一点点背景图像可见,所有组件都位于其上方,因此我决定尝试实现半透明.这是我的问题所在:从输入框向聊天窗口发送信息时,或者在导航好友...

weixin_39736007的博客 751

【UI编程】Java AWT/Swing/SWT/JavaFX杂谈

Java界面编程粗略介绍,解开Java是否合适做桌面重程序的心结。

曲折旅程,艰难人生 3403

java awt原理_JavaAWTSwingSWT三大GUI技术的原理与效率差别

看了一下对Java GUI讨论的帖子,因此写了一篇文章来阐述一下各类GUI技术的优劣。Java世界中,目前最知名的三大GUI库分别是:一、AWT(Abstract Window Toolkit)抽象窗口工具包库,包含于全部的Java SDK中二、Swing高级图形库,包含于Java2 SDK中三、来自IBM Eclipse开源项目的SWT(Standard Widget Toolkit)标准窗口部...

weixin_39648824的博客 706

java swtswing_Java GUI编程中AWT/swing/SWT的优缺点

http://www.cnblogs.com/dugang/archive/2010/10/22/1858478.htmlAWTAWT是Abstract Window Toolkit(抽象窗口工具包)的缩写,是SUN专门针对JavaGUI编程提供的最早的也是最初的开发工具包,用来建立和设置Java图形用户界面,这个工具包提供了一套与本地图形界面交互的接口。AWT 中的图形函数与操作系统所提供的图...

weixin_36328025的博客 823

JavaAWTSwingSWT三大GUI技术的原理与效率差异

MineHe原创看了一下对Java GUI讨论的帖子,所以写了一篇文章来阐述一下各种GUI技术的优劣。Java世界中,目前最知名的三大GUI库分别是:1AWT(Abstract Window Toolkit)抽象窗口工具包库,包含于所有的Java SDK中2、Swing高级图形库,包含于Java2 SDK中3、来自IBM Eclipse开源项目的SWT(Standard Widget Toolk

远方 3140

AWTSwingSWT的区别与比较(网摘)

      AWT       AWT 是Abstract Window ToolKit (抽象窗口工具包)的缩写,这个工具包提供了一套与本地图形界面进交互的接口。AWT 中的图形函数与操作系统所提供的图形函数之间有着一一对应的关系,我们把它称为peers。 也就是说,当我们利用 AWT 来构件图形用户界面的时候,我们实际上是在利用操作系统所提供的图形库。由于不同操作系统的图形库所提供的功能是...

zhangmingji的专栏 546

SwingAWTSWT的认识

1、 三者的概述: AWT(Abstract Window Toolkit) 是 API为Java 程序提供的建立图形用户界面GUI (Graphics User Interface)工具集,基于一个对等体实现的。AWT可用于Java的applet和applications中。它支持图形用户界面编程的功能包括: 用户界面组件;事件处理模型;图形和图像工具,包括形状、颜色和...

weixin_30748995的博客 258

浅谈SwingSWT比较

SwingSWT简介 Swing产生的主要原因就是AWT不能满足图形化用户界面发展的需要。AWT设计的初衷是支持开发小应用程序的简单用户界面。AWT缺少剪贴板、打印支持、键盘导航等特性;AWT功能较弱,它甚至不包括弹出式菜单或滚动窗格等基本元素。此外,AWT体系结构还存在着其他一些严重的缺陷。 随着图形化用户界面发展的需要,Swing出现了,Swing组件几乎都是轻量级组件,与AWT...

mxdxm8899的专栏 477
上一篇: 在SWT中使用ChartDirector
下一篇: 灭了珊瑚虫,OOXX了SOFF,下一个是谁?
cping1982
博客等级 码龄19年 2976粉丝 277原创
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值