`
xiaozhonghua
  • 浏览: 253664 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Swing第三刀:做套ERP,要配得上我的登录界面!

阅读更多

在《Swing第一刀》和《Swing第二刀》中提到了一个我正在折腾的一个ERP界面小框架,不少童鞋表示灰常感兴趣,这里继续和大家分享一个新的小进展:一个全新的登录界面。也许可以改变一些你对Swing和UI设计的看法。

 

为啥又是登录界面

登录界面是一个软件系统中最简单的一个界面,也是最重要的一个界面。为什么?因为它是用户看到的第一个界面;因为它是用户每天都要看的界面。要想让用户爱上你的软件,一个美观、耐看、友好的登录界面是一个重要的前提。下功夫做一个好的登录界面,你的系统就成功了一半。这就是为什么很多美工初学者总是喜欢从模仿、创作登录界面开始。

 

不信咱仔细瞅瞅。瞧,这是你做的登录界面:

 

抓图来自网络,版权归作者所有

瞧,这是我的登录界面(来自本文案例):

 

美工设计效果图

程序实际运行图

 

哪个更讨人喜欢?你是凤姐,我是志玲姐;你是芙蓉姐姐,我是Lady Gaga姐,不大好比哦。嗯,正如你所说,是“各有所长”吧!不过,除非你有严重的自虐倾向,否则你的选择应当跟我一样。

 

估计有人已经在叫了:“你这是Swing做的?”“用JNI了?”“这透明圆角,这透明文字,这阴影…咋弄的?”“快扔源码!”“Flex做这个太容易了”“花里胡哨有P用?”…你看,程序员的“老毛病”又来了。

 

不错,这个界面是Swing做的;也没有JNI(从来也没整过JNI);代码也极其简单,就是窗户纸一捅就破;也谈不上多么高深技术;也无意和Flex、.NET之类的技术相比较。我只是想让大家更多的了解Java和Swing的能力,以及我们对待技术和UI的态度。如果急吼吼的看一下代码run一下demo “哦!”一下,继续扭头堆代码,那我就算是白费这劲了。

 

Swing变冷了,还是变热了

JavaEye上最近关于Swing的帖子络绎不绝,不少人惊呼:Swing似乎难道又要热了?面对这样的疑问,国内著名Java专家、《程序员》杂志特约撰稿人、美国密苏里州立大学计算机科学与技术学院客座教授、JavaEye创始人Robbin却表现的很坦然,他告诉我说“对于我们Swing程序员来说,这是很正常的事情。”在Robbin看来,这是再正常不过的现象了。“Swing本来就很强大, 而最近频频出现的热帖也不是因为Swing发展加快了,只是媒体关注变多了。我使用Swing已经30多年了,在我上大学读书开始就接触Swing,”Robbin说,“毫无疑问,我相信Swing会取得成功”。“美洲大陆已经存在上亿年了,只是哥伦布发现了它而已。所以,不必惊呼新大陆很美很新鲜,只能怪我们很傻很无知。”

 

(注:以上访谈纯属自编自导个人杜撰,如有雷同,纯属巧合。)

 

Swing做界面,是快刀还是钝刀

用Swing做一个上面的登录界面,需要多少时间?答绝不可能是几分钟。而要做到“技惊四座、一鸣惊人”,用“鬼斧神工”搬的精致来彻底讨好和吸引用户,就必须下足功夫。这往往不是程序员一个人在战斗!美工师、程序员、熟悉业务的系统工程师…需要一起雕章琢句、废寝忘食。然而,好的设计带来的回报也会远远超过你的想象。所以,讨论所谓**技术更“快”和更“慢”毫无意义,当初快如闪电的PB、Delphi如今也难觅踪迹。所以,程序的价值和回报不在于速度,更多的在于我们的态度:精雕细琢成大器,还是粗制滥造堆垃圾呢?

 

程序员:我们并不在意程序是否好看

真的吗?你真的这样看吗?真是很可怕的一件事情。当然,在Java领域里,只要一提到J2EE、企业应用,大家就会立刻想到业务、重构、集群、云计算、松耦合、SOA、线程池、EJB、JPA、Hibernate、Spring、JBPM、SSH、JBoss、Lucene、Seam数之不尽的buzzword和framework。很多程序员浸淫在各种框架之中乐此不疲、无法自拔,甚至从来没有写下过例如“public class MyClass extends *** implements ***”亲手create过一个自己的class,实在是挺可怕。软件说到底是拿来“用”的,不是用来“学”的。再多的框架和技术,最终还是要为用户服务,和用户交互就要有好的UI。UI无非就是User Interface,是一切between在用户和机器之间的东西。忽视UI技术和UI设计,确实对一个程序员的成长是不利的。

 

程序员:我们需要左脑还是右脑

美国的斯佩里和日本角田等人的研究表明,左脑支配右半身的神经和感觉,是理解语言的中枢,主要完成语言、逻辑、分析、代数的思考认识和行为,它是进行有条不紊的条理化思维,即逻辑思维,是程序员的典型活跃区域,也是我们的“国家级重点保护区”。喜欢踢足球的程序员们注意了:尽量不要头球;用也要尽量用右脑;用左脑最好戴个摩托头盔先,别把吃饭的家什整坏了。右脑支配左半身的神经和感觉,是没有语言中枢的哑脑,但有接受音乐的中枢,主要负责可视的、综合的、几何的、绘画的思考认识和行为,也就是负责鉴赏绘画、观赏自然风光、欣赏音乐,凭直觉观察事物,纵观全局,把握整体。右脑具有类别认识能力、图形认识、空间认识、绘画认识、形象认识能力,是形象思维。看上去右脑似乎也恰恰是咱们程序员的软肋。但这能很好的解释为什么程序员弹吉他蓬蓬作响却像弹棉花,拉二胡一身汗还是像驴叫,跟大妈吵架被骂的插不上嘴,这不能怨我们自己,原来是有生理原因的。

 

但是从事逻辑思维的程序员恰恰还需要有很强的创造力。而右脑在创造性工作中具有不可替代的作用。美国科学家在《思维的艺术》一书中,将创造过程分为四个阶段,即准备阶段、酝酿阶段、闪光阶段和验证阶段。这其中,直觉和顿悟是创造的泉源,但是它必须经过语言的描述和逻辑的检验才具有价值。左右脑的这种协同关系是创造力的真正基础和源泉。如果我们一味的抱怨右脑发育不良,甚至自认右脑天生脑残,那就只能一生一世做一个不折不扣的coder编码机器了。

 

勤奋和聪明,哪个更重要

这个话题有点大。作为程序员,不管缺了哪样,都是致命的,还不如早点放弃这条路的好。这论调似乎很没新意,如果非要选择一个的话,我选择勤奋。不聪明,哪怕做不了程序员还可以干其他的嘛,比如当个官员、干个城管、踢个足球啥的(仅限国足,男队)。但要是不勤奋,恐怕就一事无成了,想做贪官都难(不勤奋你以为就能贪的到啊)。勤奋又聪明,再加上那么一点点激情,你就厉害了!

 

细节是魔鬼:登录还是登陆?

这真是一个问题。Google一下看,很多人都在争论和分析是“登陆”还是“登录”,这似乎不仅仅是一个软件问题,而变成了一个语言学术研究问题。《北京晚报》还在2007年5月专门发表解青的署名文章《“登陆网站”还是“登录网站”》进行深入的分析。经过一系列复杂的公式推导逻辑运算,作者最终得出的结论是应当使用“登陆网站”。我们程序员语言能力一向很差,虽然“登陆网站”还说得过去,但是软件的login界面如果用“登陆”那我们就会感觉有点点怪了,总让人想起彪炳史册的伟大的“诺曼底”这个地方。毫无疑问,“登录”是更正确的选择。别说程序员不用这样较真,别说这个跟我程序员无关。如果哪个大型软件的login界面用“登陆”两个字,请你立刻鄙视它、嘲笑它、讽刺它、挖苦它、打击它、永远别买它、永远离开它,离啊离开它,离~开~它!不服气现在就重启系统看看Windows界面用的什么,去Google一下主流软件抓图用的是什么。如果你做的软件真的由此而不能卖出去,此事也与你无关吗?细节决定成败,细节就是魔鬼,这不是口号。你不提防它,它就吃掉你。

 

Swing与不规则窗体的“哥德巴赫猜想”

不管你信不信,“如何用Swing做不规则窗体”是近10年来Swing被最常问到的几个问题之一。Google上搜索“Swing 不规则 窗体”有将近10万个中文结果,而且从1999年就有人在致力于这一问题的解决方法,至今甚至已经出现多种不同“流派”的解决方案。

 

第一招:抓屏法

最早出现的比较靠谱的一个解决方法出现在《Swing Hacks》一书中。《Swing Hacks》一书是著名的图书出版商O’Reilly在2007年出版的Swing技巧图书,作者是Swing开发组成员Joshua Marinacci,他也是目前JavaFX开发组成员。在这本书的41章中介绍了一种制作透明窗体和不规则窗体的方法。由于当时的JDK功能所限,Java本身并未提供任何直接的API来制作半透明或不规则窗体,所以这一技巧是利用Robot来截取屏幕原有内容生成内存图片,然后将图片显示在Swing的窗体中作为背景,“欺骗”大家的眼睛误以为是窗口“透”过去了。这一招确实体现了程序员的聪明才智。

 

不过这一方法的缺陷是,当窗口被移动一下后就会露馅,所谓“透明”区域的抓图不知道位置变化,也不会随之改变。所以在该书的例子程序中,作者又将JFrame的setUndecorated设置为true去掉了标题栏,让你无法移动窗口;再启动了一个线程,每250毫秒就重新抓屏一次,更新Swing窗口的图片背景。不过由于Swing窗口显示出来后,它本身又遮挡了屏幕后面的物体,作者只好先frame.hide()把窗口隐藏一下,然后马上抓图,然后再frame.show恢复窗口显示。透明效果是勉强出来了,但是程序在那里有事没事的一直忽隐忽现,真是够怪异的,效率、实时性也都惨不忍睹。

 

以下是相关代码:

 

public void run( ) {
	try {
		while(true) {
			Thread.sleep(250);
			long now = new Date( ).getTime( );
			if(refreshRequested &&
				((now - lastupdate) > 1000)) {
				if(frame.isVisible( )) {
                    Point location = frame.getLocation( );
                    frame.hide( );
                    updateBackground( );
                    frame.show( );
				frame.setLocation(location);
                    refresh( );
				}
				lastupdate = now;
				refreshRequested = false;
				}
			}
		} catch (Exception ex) {
			p(ex.toString( ));
			ex.printStackTrace( );
		} 
	} 

  《Swing Hacks》中介绍的方法代码片段

 

第二招:AWTUtilities.setWindowShape法

随着Sun公司对JavaFX技术的猛醒和大力持续投入,JDK从6就开始从底层为JavaFX的未来做好准备,提供更多底层功能支撑。作为“酷”、“炫”的UI技术的先锋,窗口透明、不规则窗口自然是将来JavaFX不可缺少的元素和特性。所以,Sun在JDK6中提供了几个新的函数,用来支持窗口透明度、窗口任意形状:

 

 

void setWindowOpacity(Window window, float opacity)  //设置窗口透明度
void setWindowShape(Window window, Shape shape)   //设置窗口形状
 

 

这里有官方的具体介绍:

http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/

 

setWindowOpacity方法提供了官方的、彻底的方法来生成不规则形状窗体。不过依旧有以下几个问题:

 

  • AWTUtilities并非JDK公开类,将来可能会发生变化。当然除了编译时的一个不爽的警告外,也不用过度担心,即使将来API发生变化,相信Sun和Oracle也会妥善处理好。
  • 用Shape形状定义的窗口边缘粗糙,显示效果差。使用setWindowShape函数对窗口设定形状后,其窗口切割的边缘并未做抗锯齿(anti-alias)处理,也没有相应的函数或参数进行控制,导致显示效果粗糙。看看Sun自己做出来的例子:http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/9.jpg,一个简单的椭圆Shape,其边缘就已经粗糙不堪。更不用说更复杂的透明图片边缘了。本人经过好几天的反复尝试,发现其效果始终不甚理想(如图),无论对图片的透明边缘如何精细处理,甚至直接new Shape,都完全达不到美工设计出来的效果图。 
     
  • 透明PNG图片的边缘Shape不好获取。如果我们的窗体不是一个规则的、可定义的几何形状Shape,而是一个任意透明PNG图片,该如何获取图片的透明边缘Shape,进而设置window的不规则形状呢?这确实是一个难题。在网上有人专门讨论这一算法,基本上是读取PNG图片的每一个像素,获得像素透明边界点,对边界点进行不断的合并与逼近,最后形成一个最终Shape。TWaver的TWaverUtil工具类中就有一个getImageShape方法用来获得任意图片的边缘shape。经反复测试验证,就是采用了这种算法。不过这种算法的缺点很明显:边缘必须是连续的,甚至必须是“外凸”的;如果png图片中间有一个透明的“洞”,甚至边缘有一个凹陷透明区域,生成的Shape都无法准确反映出来。

 

第三招:终极解决之道

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

 

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

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

 

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

 

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

 

 

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);
    }
}
 

运行效果如下图:


窗口的拖拽移动

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

 

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。

 

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图片:

 


程序代码如下:

 

 

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。否则,鼠标点击你画的椭圆或桌面的图标,它如何知道是点击了窗体,还是操作了桌面?只能生成内存图片,在里面进行像素判断了。要挖掘再深入的秘密,我也不清楚了,自己继续探索吧!

 

代码和可执行文件

作为一个完整的小Swing UI框架的一部分,可以在本文下方下载整个zip包,执行其中的login.bat来运行登录窗体、ERP程序框架、屏幕下雪例子。源代码还在整理中,请大家耐心等待。关于整个框架的更多介绍,可以查看《Swing第一刀》和《Swing第二刀》。希望大家喜欢,并给我留言,也希望各位高手批评指正!

 

谢谢!


 

  • 大小: 2.7 KB
  • 大小: 32.7 KB
  • 大小: 20.9 KB
  • 大小: 252.2 KB
  • 大小: 9.8 KB
  • 大小: 24.7 KB
  • 大小: 853.8 KB
  • 大小: 19.2 KB
  • 大小: 31.6 KB
  • 大小: 254.8 KB
  • 大小: 35.1 KB
分享到:
评论
49 楼 Now7! 2010-08-30  
  根据官方导引http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/和http://www.docjar.com/docs/api/com/sun/awt/AWTUtilities.html,类AWTUtilities对于窗体透明性的支持有3个枚举常量,并且"The constants PERPIXEL_TRANSPARENT, TRANSLUCENT, PERPIXEL_TRANSLUCENT represent shaping, simple translucency, and per-pixel translucency respectively."。
  其实,类AWTUtilities只是想知道窗体Bounds范围所有点的alpha值。它提供了3种不同的设置方法:1是利用Shape设置点全透明(0.0f,如果在Shape边缘或Shape内)或全不透明(1.0f,在Shape外);2是设置点为同一个透明度(例如可以设置为0.8f);3是自己手动设置每一个点的alpha值(譬如官方导引中示例的是GradiantPaint)。如下所示。方法1演示了一个字母'T'的Shape。

  这3种方法不分好坏,取决于自己的使用目的。方法1比较适用于Shape比较整齐(因为没有anti-alias),譬如实现一个“品”字形的窗体,也比较适用于Shape很容易获得的情况,譬如一个字符串在特定Font下的显示。方法2适用于窗体透明性很统一的时候。方法3适用于自定义,例如使用一张png图片指出各个点的alpha值。但是应当注意,只要AWTUtilities.setWindowOpaque(frame, false),无论你设置任何子组件的Opaque与否,系统都会以Opaque==false处理,这样就会导致JComponent的背景不会被绘制。
  所以lz登录界面采用第3种方法是最好的。不过题外话说一句,即使使用方法1,如下办法也可以正确绘制图片的Shape。即逐行扫描每个点的alpha值,连在一起的不为0.0f的点可以画一个Rectangle,然后将所有的Rectangle合并成一个Area。避免了lz提到的算法的“边缘必须是连续的,甚至必须是‘外凸’的”的缺陷。另外,方法3中使用的图片,我在Photoshop做处理的时候,一个点的不透明度&填充<5%则在我的Java实验中被当成完全透明(alpha=0.0f),反之就有alpha>0.0f。下面一个例子使用了这样一个“回”字型的png,里面空白的不透明度是0%,外圈空白的不透明度是5%,虽然他们视觉上几乎辨别不出来区别,但是用鼠标点一点就知道了,

(不过贴到论坛上 怎么看不出来是透明了  )
  配套使用的Java代码:
import java.awt.Color;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import com.sun.awt.AWTUtilities;

public class TranslucentFrameDemo extends JFrame
{
	private static final long serialVersionUID = 3878450094604602368L;

	TranslucentFrameDemo()
	{
		setUndecorated(true);
		setSize(400, 400);
		AWTUtilities.setWindowOpaque(this, false);
		final JLabel label = new JLabel(new ImageIcon("d:\\clip.png"));
		label.setBackground(Color.BLACK); // actually won't work
		add(label);
	}

	public static void main(final String[] args)
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				new TranslucentFrameDemo().setVisible(true);
			}
		});
	}
}


  另外应当注意的是,不是所有的OS——例如linux的CentOS发行版——都支持AWTUtilities带来的窗体透明。应该在使用窗体透明的方面前加入检测代码,如官方示例中做的那样。
  关于实现原理,由于在不规则的窗体中使用"Alt+Space"快捷键依然有效,依然可以设置AlwaysOnTop(true)并且确实一直在顶端,并且其绘制过程中使用了sun.awt.windows.WWindowPeer和BufferedImage类(参考lz把窗体设为很大导致溢出),我倾向于认为这样的不规则窗体依然使用了OS的window作为对等的peer,只是JVM先把不规则窗体中的所有内容先绘制到BufferedImage上,再向OS的window绘制Image,这个过程和Swing正常状态下直接使用window的绘制上下文绘制Swing组件还是略有不同的。不过我对Windows的底层编程实在不熟悉,也仅局限于这样猜测。为什么Windows的window现在可以是不规则、透明的?为什么以前不能?底层的实现原理是什么?关于这点疑问很希望和大家交流相关资料或见解!:)
  再另外,半透明的Jcomponent绘制可以参考:
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;


public class TanslucentJButtonDemo extends JFrame
{
	TanslucentJButtonDemo()
	{
		setSize(300, 300);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLayout(null);
		getContentPane().setBackground(Color.YELLOW);
		MyButton b = new MyButton();
		b.setBounds(100,50,100,100);
		add(b);
	}
	public static void main(String[] args)
     {
	     SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				try {  
					    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {  
					        if ("Nimbus".equals(info.getName())) {  
					            UIManager.setLookAndFeel(info.getClassName());  
					            break;  
					        }  
					    }  
					} catch (Exception e) {  
					    // If Nimbus is not available, you can set the GUI to another look and feel.  
					}  
				new TanslucentJButtonDemo().setVisible(true);
			}
		});
     }
}

class MyButton extends JButton
{
	MyButton()
	{
		super("Push Me!");
		setOpaque(false);	// critical! Make this line a comment and guess what happens.
	}
	
	@Override
	public void paint(Graphics g)
	{
		Graphics2D g2 = (Graphics2D) g;
		Composite com = g2.getComposite();
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
	     super.paint(g2);
	     g2.setComposite(com);
	}
}

  选择在Jcomponent里面覆盖paint而不是在某个UIDelegate里覆盖,是因为这样可以无论什么LAF,都可以获得渲染后的半透明组件。

  感谢lz的尝试和工作!向老汪致敬! 
48 楼 luojihaidao 2010-07-16  
雪花报错:
[Exception in thread "main" java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0/code]

加上frame.setBounds(0, 0, 1, 1);后就好了。


期望第四刀。源码什么时候出出来呀。  以前做的是web,看了你的贴后感觉不错,想看看你代码的规划,风格。
47 楼 yedaya 2010-07-13  
xiaozhonghua 写道
yedaya 写道
“对窗体上的组件安装这一listener,就可以对窗口中任意元素进行拖拽,直接拖动窗体四处晃悠了。”
具体怎么装?能不能就那个红色的方框演示一下。
比较愚钝,请明示!!谢谢。

请参考FreeLoginUI.java中的132行:
logoLabel.addMouseListener(moveWindowListener);
        logoLabel.addMouseMotionListener(moveWindowListener);

哦,明白了,我没有添加第二个事件,出来了,谢谢。
46 楼 xiaozhonghua 2010-07-13  
yedaya 写道
“对窗体上的组件安装这一listener,就可以对窗口中任意元素进行拖拽,直接拖动窗体四处晃悠了。”
具体怎么装?能不能就那个红色的方框演示一下。
比较愚钝,请明示!!谢谢。

请参考FreeLoginUI.java中的132行:
logoLabel.addMouseListener(moveWindowListener);
        logoLabel.addMouseMotionListener(moveWindowListener);
45 楼 yedaya 2010-07-13  
“对窗体上的组件安装这一listener,就可以对窗口中任意元素进行拖拽,直接拖动窗体四处晃悠了。”
具体怎么装?能不能就那个红色的方框演示一下。
比较愚钝,请明示!!谢谢。
44 楼 wwccss 2010-07-13  
虽然我不用,但一定要支持一下。鄙视有些人从来不发表什么建设性的东西,就知道冷言冷语说风凉话。
43 楼 evabibi 2010-07-12  
xiaozhonghua 写道
flyfox1982 写道
xiangkun 写道


为什么我的这里运行出来是这样的呢?

Windows Xp下的.


应该与xp没有关系,估计的更新下jre

哎呦?奇怪了。能否说一下你的操作系统的具体版本?(cmd里面ver一下)还有java的版本(cmd里面java -version一下)
其他人也有类似问题么?

我这台式机上也是同样的问题,希望对你有帮助 : )

var

Microsoft Windows XP [版本 5.1.2600]


java -version 

java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) Client VM (build 11.3-b02, mixed mode, sharing)

42 楼 CodingMouse 2010-07-12  
之前我也做过Swing,当时用的substance皮肤,对资源占用大不说,内存还不能释放。但最小化窗口又好像正常。所以,像substance这样的LookAndFeel并不见得有多好,你楼主这样有一个整体的UI设计思路才是正道!感谢分享!
41 楼 usiboy 2010-07-09  
icanfly 写道
引用
“Swing本来就很强大, 而最近频频出现的热帖也不是因为Swing发展加快了,只是媒体关注变多了。我使用Swing已经30多年了,在我上大学读书开始就接触Swing,”Robbin说

这个比较绝。Java诞生才多少年,已经有人使用Swing 30年了 ,我汗,哈哈 

这个的确很强大,HOHO,可以和C++谈历史了
40 楼 jychenok 2010-07-09  
强烈建议楼主剔除twaver,这个东西太贵了...搞到框架里如果商用就有点麻烦了.....
公司肯定不会愿意花那额外的20W..
39 楼 xiaozhonghua 2010-07-09  
flyfox1982 写道
xiangkun 写道


为什么我的这里运行出来是这样的呢?

Windows Xp下的.


应该与xp没有关系,估计的更新下jre

哎呦?奇怪了。能否说一下你的操作系统的具体版本?(cmd里面ver一下)还有java的版本(cmd里面java -version一下)
其他人也有类似问题么?
38 楼 flyfox1982 2010-07-09  
xiangkun 写道


为什么我的这里运行出来是这样的呢?

Windows Xp下的.


应该与xp没有关系,估计的更新下jre
37 楼 ninja9turtle 2010-07-08  
ray_linn 写道
所有的魔法就在于使用Layered Windows呗:

1。 WinAPI里CreateWindows,调用EX_LAYRED,构成一个分层窗口。
2。 调用UpdateWindowsLayered,把bitmap帖到分层窗口上。

mac os上呢?
36 楼 fyook 2010-07-08  
最近也在学习swing,但是还没有达到美化的程度,基本的还没有学好,好好加油
35 楼 ald 2010-07-08  
LZ太NB了
34 楼 guduxing890 2010-07-08  
        顶!!!!!!! 我爱死Swing啦
33 楼 frenchleaf 2010-07-08  
浏览器纷争的时代,swing可以崛起,很有搞头,狂顶
32 楼 ycysth 2010-07-08  
Swing确实很强大,主要是相比其他的要繁琐一些。
31 楼 h0nk3r 2010-07-08  
提交作业

30 楼 hu437 2010-07-08  
楼主的文笔不是一般的好呀~~~~

相关推荐

    Swing第三刀:做套ERP,要配得上我的登录界面

    Swing第三刀:做套ERP,要配得上我的登录界面

    SWING大刀系列源码

    Swing第三刀:做套ERP,要配得上我的登录界面! http://joshuaxiao.iteye.com/blog/710428 Swing第四刀:代码尽散换芳华 http://joshuaxiao.iteye.com/blog/714669 Swing第五刀:走马观花看世博 ...

    Swing_大刀系列.pdf

    Swing大刀系列: 1.1 Swing是一把刀 ...1.3 Swing第三刀:做套ERP,要配得上我的登录界面! 1.4 Swing第四刀:代码尽散换芳华 1.5 Swing第五刀:走马观花看世博 1.6 Swing第六刀:老婆不能换,窗户框可以

    Swing登录界面

    在这个"Swing登录界面"项目中,我们可以学习到如何利用Swing构建一个简单但实用的用户登录界面。 1. **Swing组件使用**: - `JFrame`: 这是所有Swing应用的基础,它代表了一个窗口或框架。登录界面通常会在`JFrame`...

    Swing第三刀(转)

    Swing第*刀(转) 个人觉得不错,发来大家学习,不要分

    swing 模仿QQ登录界面

    本项目“Swing模仿QQ登录界面”旨在通过Swing库来构建一个与QQ登录界面类似的交互式窗口。 在Swing中,我们首先需要了解几个核心概念: 1. **JFrame**: JFrame是所有Swing应用的基础,它代表了窗口。在模仿QQ登录...

    Swing第二刀(转)

    Swing第*刀(转) 觉得很好,发给大家看看,不需要分

    swing界面美化包

    总的来说,Swing界面美化是Java GUI开发中的一项重要技能,通过合理利用Look-and-Feel机制和第三方库,开发者可以打造出独特且吸引人的用户界面,提升用户体验。在实际项目中,结合业务需求和个人审美,灵活运用这些...

    Swing做的高仿QQ登陆界面

    下面我们将详细探讨Swing在创建登录界面以及相关功能实现上的应用。 首先,Swing提供了丰富的组件库,包括JFrame(主窗口)、JLabel(文本标签)、JButton(按钮)、JTextField(文本输入框)和JPasswordField...

    Swing第四刀(转)

    Swing第*刀(转) 个人觉得不错,发来大家学习,不要分

    java swing 用户登录界面设计

    在这个特定的项目中,“java swing 用户登录界面设计”涉及到了如何利用Swing来创建一个用户登录界面,并通过连接数据库进行安全验证。 首先,我们需要理解Swing中的主要组件。如`JFrame`是窗口容器,`JLabel`用于...

    用swing mysql 写的一个QQ登录界面

    【Swing与MySQL结合实现QQ登录界面】 Swing是Java的一种图形用户界面(GUI)工具包,主要用于构建桌面应用程序。在本项目中,"用Swing MySQL写的一个QQ登录界面",意味着开发者使用Swing来创建了一个模拟QQ登录的窗口...

    无数据库的swing登录注册验证界面

    Swing是Java提供的一种图形用户界面(GUI)工具包,用于开发桌面应用程序。 在这样的应用中,用户界面通常包括输入字段,如用户名和密码文本框,以及登录和注册按钮。Swing组件如JFrame、JLabel、JTextField、...

    java swing漂亮界面 超酷 javaswing教程

    Java Swing 是Java平台上用于构建图形用户界面(GUI)的一个库,它是Java Foundation Classes (JFC)的一部分。在Swing中,你可以创建出丰富、交互性强的桌面应用,而且它的组件库提供了很多美观的外观和感觉。 ...

    java swing管理系统源码 程序 代码 图形界面(11套).zip

    Java Swing是Java编程语言中的一个图形用户界面(GUI)工具包,它是Java Foundation Classes (JFC)的一部分,用于构建桌面应用程序。本压缩包包含了11套完整的Java Swing管理系统源码,这些源码对于学习和理解Java GUI...

    Swing大刀系列

    ### Swing大刀系列知识点概述 #### 1. Swing的地位与争议 - **Swing的现状**: Swing作为一种桌面应用开发框架,在Web技术和RIA(富互联网应用)兴起后受到了冷落。很多人认为Swing已经过时或者即将被淘汰。 - **...

    QQ登录界面模仿[swing]

    QQ登录界面模仿[swing],下载后使用 554278334,ljheee登录

    Swing精美界面设计和动画制作教程+实例

    Swing精美界面设计和动画制作教程+实例Swing精美界面设计和动画制作教程+实例Swing精美界面设计和动画制作教程+实例Swing精美界面设计和动画制作教程+实例Swing精美界面设计和动画制作教程+实例Swing精美界面...

    java swing漂亮界面(超酷) javaswing教程

    Java Swing 是Java编程语言中用于构建桌面应用程序用户界面的一个库,它是Java Foundation Classes (JFC) 的一部分。Swing 提供了一系列组件,如按钮、文本框、菜单等,用于创建功能丰富的图形用户界面(GUI)。在...

Global site tag (gtag.js) - Google Analytics