<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    dyerac  
    dyerac In Java
    公告

    日歷
    <2013年6月>
    2627282930311
    2345678
    9101112131415
    16171819202122
    23242526272829
    30123456
    統(tǒng)計(jì)
    • 隨筆 - 36
    • 文章 - 10
    • 評(píng)論 - 94
    • 引用 - 0

    導(dǎo)航

    常用鏈接

    留言簿(5)

    隨筆分類(49)

    隨筆檔案(36)

    文章分類(11)

    文章檔案(10)

    相冊

    dyerac

    搜索

    •  

    積分與排名

    • 積分 - 79220
    • 排名 - 705

    最新隨筆

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

     

    先把以前寫的轉(zhuǎn)過來,呵呵



    圖形界面開發(fā)對于Java來說并非它的長項(xiàng),開發(fā)者經(jīng)常會(huì)碰到各種各樣的限制,比如,如何打造一款任意形狀的窗口如何可以透過窗口顯示它覆蓋下的內(nèi)容

    考慮到Java并沒有被設(shè)計(jì)成支持以上的功能,所以,你能得到的永遠(yuǎn)是方方正正的窗口,毫無新意,當(dāng)然,我們可以通過JNI調(diào)用本地代碼來完成,但是這就失去了java可移植性的意義,那么,用純粹的java代碼如何實(shí)現(xiàn)以上兩種功能呢?

    下文提供了一個(gè)實(shí)現(xiàn)的參考

    預(yù)備知識(shí)
    1.java.awt.Robot,這個(gè)類是一個(gè)功能非常強(qiáng)大的類,通過它我們可以控制鼠標(biāo)和鍵盤的響應(yīng),不過這里,我們只需要用到它的一個(gè)功能--截屏,也就是得到當(dāng)前屏幕的快照(screenshot)
    2.我們可以通過調(diào)用一個(gè)swing組件的paintComponent(Graphics g)方法用特定的Graphics為其定制特殊的外觀

    首先聲明的一點(diǎn)是,本文中的實(shí)現(xiàn)方法只是一個(gè)欺騙的手法,因?yàn)橐雽?shí)現(xiàn)前文中的功能,我們幾乎的重寫一套Swing出來,這里,簡便的做法是,我們通過robot類來獲得當(dāng)前屏幕的快照,然后貼在我們需要的窗口上,這樣,不就實(shí)現(xiàn)了透明的功能了嗎?順便提一下,幾年前日本發(fā)明的隱形衣也是依靠這種機(jī)制,這種衣服在身后附帶一套攝像機(jī),然后即時(shí)的將拍下的內(nèi)容顯示在衣服的正面,因此,當(dāng)別人看過來時(shí),仿佛就通過人和衣服看到了身后的場景^_^

    另外,還要感謝Joshua Chris leniz的Swing Hack一書,以上充滿創(chuàng)新的方法正來自他的書中

    好咯,讓我們具體看一下細(xì)節(jié)的處理:
    第一,我們要得到當(dāng)前屏幕的快照,保存到一個(gè)Image對象[color=Red]background[/color]中:
    ? public void updateBackground() {
    ??try {
    ???Robot rbt = new Robot();
    ???Toolkit tk = Toolkit.getDefaultToolkit();
    ???Dimension dim = tk.getScreenSize();
    ???[color=Red]background [/color]= rbt.createScreenCapture(new Rectangle(0, 0, (int) dim
    ?????.getWidth(), (int) dim.getHeight()));
    ??} catch (Exception ex) {
    ?? }
    ?}

    第二,我們需要讓窗口顯示這個(gè)圖像,也就是說,讓窗口的背景圖像是這副圖像,以達(dá)到透明的欺騙效果:

    public void paintComponent(Graphics g) {
    ??Point pos = this.getLocationOnScreen();
    ??Point offset = new Point(-pos.x, -pos.y);
    ??g.drawImage([color=Red]background[/color], offset.x, offset.y, null);
    ?}

    在swing hack一書中,作者也給出了他的實(shí)現(xiàn),然而,運(yùn)行結(jié)果表明該實(shí)現(xiàn)存在很大的問題:窗口經(jīng)常無法即時(shí)更新,往往背景變了,窗口里顯示的卻還是以前的背景。仔細(xì)研究了他的代碼,我發(fā)現(xiàn)了問題的根結(jié),同時(shí)也是這種實(shí)現(xiàn)技術(shù)的關(guān)鍵要素--如何讓窗口在正確的時(shí)機(jī)里更新顯示,下面,我們會(huì)討論這一點(diǎn)

    第三,更新窗口外觀
    前兩步的操作,只能得到一副當(dāng)前屏幕的快照,一旦背景變化了,或者窗口移動(dòng)了,變化大小了,那么我們制作的窗口將永遠(yuǎn)無法和和屏幕背景聯(lián)合成整體,也就失去了透明的效果;同時(shí),我們也不可能每時(shí)每刻都調(diào)用
    updateBackground() 方法獲得最新的背景,可行的方法是,通過對事件的監(jiān)聽來選擇適當(dāng)?shù)臅r(shí)間來更新外觀

    我們應(yīng)該可以達(dá)到這三點(diǎn)共識(shí)
    1。窗口移動(dòng)或改變大小時(shí),背景圖像一般是不會(huì)發(fā)生變化的,我們不需要得到新的屏幕快照,只用將以前得到的背景中適當(dāng)?shù)牟糠仲N到窗口上,調(diào)用repaint()方法就足已
    2。要獲得最新的屏幕快照,必須先將窗口隱藏起來,調(diào)用updateBackground() 得到圖像后再把窗口顯示,我們可以用refresh方法來表示
    ?refresh(){
    ??? frame.hide();
    ??? updateBackground() ;
    ?? frame.show();
    }
    3。如果背景改變了,那么一定是別的windows程序獲得了或失去了事件焦點(diǎn),也就是說我們關(guān)注的窗口將觸發(fā)焦點(diǎn)得失事件,這個(gè)時(shí)候需要調(diào)用refresh() 得到最新的屏幕快照


    看到這里,你或許認(rèn)為已經(jīng)沒有技術(shù)難點(diǎn)了,然而,此時(shí)才是我們[color=Red]最需要關(guān)注的地方[/color]:
    參看第三點(diǎn),我們需要在窗口得失焦點(diǎn)時(shí)調(diào)用refresh() 方法;參看第一點(diǎn),我們調(diào)用refresh() 方法時(shí)需要先將窗口隱藏,然后再顯示。于是問題來了,在隱藏和顯示窗口時(shí),同樣會(huì)觸發(fā)得失焦點(diǎn)事件,得失焦點(diǎn)事件又將觸發(fā)新的隱藏和顯示窗口事件(為了得到新的屏幕快照),這就使程序陷入了死循環(huán)中,我們必須加以控制,使得第二次觸發(fā)焦點(diǎn)得失事件時(shí)不調(diào)用refresh()方法

    作者的辦法是加一個(gè)線程來控制,通過判斷時(shí)間間隔長短來決定是否調(diào)用refresh()方法,可是,這個(gè)條件是程序非常的不穩(wěn)定,因?yàn)橥{(diào)用時(shí)間會(huì)根據(jù)系統(tǒng)繁忙度而改變,使得需要更新時(shí)不能更新,不需要更新的時(shí)候反而更新了
    因此,我決定采取新的解決方案,能不能隱藏/顯示窗口時(shí)不觸發(fā)得失焦點(diǎn)事件呢?
    解決方法很簡單,我拋開了傳統(tǒng)的setVisible()或者show(),hide()方法,而是使用setLocation()方法,因?yàn)檎{(diào)用setLocation()方法時(shí)窗口不會(huì)失去焦點(diǎn),同時(shí),只要用類似setLocation(-2000,-2000)方法也同樣可以輕松的讓窗口在屏幕中消失
    下面是我的全部代碼:

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.Robot;
    import java.awt.Toolkit;
    import java.awt.event.ComponentEvent;
    import java.awt.event.ComponentListener;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowFocusListener;

    import javax.swing.JButton;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.UIManager;

    import org.jvnet.substance.SubstanceLookAndFeel;
    import org.jvnet.substance.theme.SubstanceLightAquaTheme;

    import ch.randelshofer.quaqua.QuaquaLookAndFeel;

    public class TestEvent extends JComponent implements ComponentListener,
    ??WindowFocusListener {
    ?private JFrame frame;

    ?private Boolean isHiding = false, isShowing = false, start = false;

    ?private Image background;

    ?private Point p;
    ????????????????????
    ??????????????????? [color=Red]//獲得當(dāng)前屏幕快照[/color]
    ?public void updateBackground() {
    ??try {
    ???Robot rbt = new Robot();
    ???Toolkit tk = Toolkit.getDefaultToolkit();
    ???Dimension dim = tk.getScreenSize();
    ???background = rbt.createScreenCapture(new Rectangle(0, 0, (int) dim
    ?????.getWidth(), (int) dim.getHeight()));
    ??} catch (Exception ex) {
    ???// p(ex.toString());
    ???// 此方法沒有申明過 ,因?yàn)闊o法得知上下文 。因?yàn)椴挥绊憟?zhí)行效果 ,先注釋掉它 ex.printStackTrace();
    ??}

    ?}

    ?????????????????? [color=Red]? //將窗口掉離出屏幕以獲得純粹的背景圖象[/color]
    ?public void refresh() {
    ??if (start == true) {
    ???this.updateBackground();
    ???frame.setLocation(p);
    ???if (p.x < 0 || p.y < 0)
    ????frame.setLocation(0, 0);
    ???this.repaint();
    ??}
    ?}

    ?public void componentHidden(ComponentEvent e) {
    ??// TODO Auto-generated method stub
    ??System.out.println("Hidden");
    ?}

    ???????????????????? [color=Red] //窗口移動(dòng)時(shí)[/color]
    ?public void componentMoved(ComponentEvent e) {
    ??// TODO Auto-generated method stub
    ??System.out.println("moved");
    ??this.repaint();
    ?}

    ??????????????????? [color=Red] //窗口改變大小時(shí)[/color]
    ?public void componentResized(ComponentEvent e) {
    ??// TODO Auto-generated method stub
    ??System.out.println("resized");
    ??this.repaint();
    ?}

    ?public void componentShown(ComponentEvent e) {
    ??// TODO Auto-generated method stub
    ??System.out.println("shown");
    ?}

    ??????????????????? [color=Red] //窗口得到焦點(diǎn)后,用refresh()方法更新界面[/color]
    ?public void windowGainedFocus(WindowEvent e) {
    ??// TODO Auto-generated method stub
    ??System.out.println("gainedFocus");
    ??refresh();
    ??start = false;
    ?}

    ??????????????????? [color=Red] //窗口失去焦點(diǎn)后,將其移出屏幕[/color]
    ?public void windowLostFocus(WindowEvent e) {
    ??// TODO Auto-generated method stub
    ??System.out.println("lostFocus");
    ??if (frame.isShowing() == true) {
    ???System.out.println("visible");
    ??} else {
    ???System.out.println("invisible");
    ??}
    ??start = true;
    ??p = frame.getLocation();
    ??frame.setLocation(-2000, -2000);
    ?}

    ?public TestEvent(JFrame frame) {
    ??super();
    ??this.frame = frame;
    ??updateBackground();
    ??this.setSize(200, 120);
    ??this.setVisible(true);
    ??frame.addComponentListener(this);
    ??frame.addWindowFocusListener(this);

    ??// TODO Auto-generated constructor stub
    ?}

    ??????????????????? //繪制外觀,注意,其中 pos,offset 是為了將特定部分的圖象貼到窗口上
    ?public void paintComponent(Graphics g) {
    ??Point pos = this.getLocationOnScreen();
    ??Point offset = new Point(-pos.x, -pos.y);
    ??g.drawImage(background, offset.x, offset.y, null);
    ?}

    ?/**
    ? * @param args
    ? */
    ?public static void main(String[] args) {
    ??// TODO Auto-generated method stub
    ??try {
    ???// UIManager.setLookAndFeel("org.fife.plaf.Office2003.Office2003LookAndFeel");
    ???// UIManager.setLookAndFeel("org.fife.plaf.OfficeXP.OfficeXPLookAndFeel");
    ???// UIManager.setLookAndFeel("org.fife.plaf.OfficeXP.OfficeXPLookAndFeel");
    ???UIManager.setLookAndFeel(new SubstanceLookAndFeel());
    ???//UIManager.setLookAndFeel(new SmoothLookAndFeel());
    ???//UIManager.setLookAndFeel(new QuaquaLookAndFeel());
    ???UIManager.put("swing.boldMetal", false);
    ???if (System.getProperty("substancelaf.useDecorations") == null) {
    ????JFrame.setDefaultLookAndFeelDecorated(true);
    ????//JDialog.setDefaultLookAndFeelDecorated(true);
    ???}
    ???System.setProperty("sun.awt.noerasebackground", "true");
    ???SubstanceLookAndFeel.setCurrentTheme(new SubstanceLightAquaTheme());

    ???// UIManager.setLookAndFeel("org.fife.plaf.VisualStudio2005.VisualStudio2005LookAndFeel");
    ??} catch (Exception e) {
    ???System.err.println("Oops!? Something went wrong!");
    ??}

    ??JFrame frame = new JFrame("Transparent Window");
    ??TestEvent t = new TestEvent(frame);
    ??t.setLayout(new BorderLayout());
    ??JButton button = new JButton("This is a button");
    ??t.add("North", button);
    ??JLabel label = new JLabel("This is a label");
    ??t.add("South", label);
    ??frame.getContentPane().add("Center", t);
    ??frame.pack();
    ??frame.setSize(150, 100);
    ??frame.show();
    ??frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ??// t.start=true;
    ?}

    }


    當(dāng)然,以上代碼還存在許多不足,比如在移動(dòng)窗口時(shí)性能會(huì)有影響,應(yīng)該可以通過線程來控制其更新的頻率來提升效率,希望大家能一起研究一下,改好了記得通知我哦

    ps:你也許還會(huì)說,e?怎么沒講任意形狀窗口如何打造?
    ?????? 呵呵,其實(shí)只要把窗口按上述方法設(shè)置成透明,再去掉邊框,再換上自己的邊框,不就完成了馬?
    ???? 相信聰明的各位一定很容易就辦到咯

    另外,我還在下面附帶了作者的大論,想了解更多的同學(xué)也可以去看看

    http://www.matrix.org.cn/resource/article/44/44186_Swing.html

    posted on 2006-04-03 18:15 dyerac in java... 閱讀(8962) 評(píng)論(13)  編輯  收藏 所屬分類: 原創(chuàng)文章JavaSE
    評(píng)論:
    • # re: 用java打造任意形狀窗口和透明窗口  nake Posted @ 2006-04-03 20:32
      不錯(cuò)
        回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  fanse Posted @ 2006-04-05 00:19
      好文章,我要充電了

      歡迎訪問 http://www.shuangzixing.net 雙子星Java開源技術(shù)門戶  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  jazzy Posted @ 2006-04-06 16:21
      呵呵,用SWT實(shí)現(xiàn)就很簡單啦  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  -_=~~ Posted @ 2006-08-07 11:54
      不錯(cuò)不錯(cuò),多謝

      swt....作者不是要跨平臺(tái)么..hoho  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  Tony[匿名] Posted @ 2006-12-04 23:19
      很感謝您發(fā)表自己的感想

      其實(shí)這是沒用的小技巧
      試想:使用者不可能不去移動(dòng)這個(gè)視窗,一移動(dòng),就露馬腳了

      很久以前我用過這個(gè)技巧
      卻在內(nèi)部RD就被否決掉

      原因就在:無法預(yù)測試用者的操作方式  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  dyerac in java... Posted @ 2006-12-05 12:38
      @Tony[匿名]
      不啊,移動(dòng)起來是沒有問題的
      只是在隱藏后再顯示時(shí)會(huì)出現(xiàn)一個(gè)瞬移的現(xiàn)象,但是基本上用戶是注意不到的  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  pc Posted @ 2007-09-20 11:47
      看到你的src里有一行
      //UIManager.setLookAndFeel(new QuaquaLookAndFeel());
      這個(gè)是windows下的L&F嗎?
      能不能給我發(fā)一份?hongmocai at 126.com
      Thank you.  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  ki_bum Posted @ 2008-02-24 17:56
      偶..最近..也在看Hack..
      但..L&F..MS講的有點(diǎn)少...
      呵~~~
      只有一個(gè)...小問題...
      如果...是雙屏顯示器(3屏..4屏~~~)
      在非主屏上...
      程序..就會(huì)認(rèn)為是windowLostFocus
      就會(huì)顯示L&F的background(==!)  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  evilz Posted @ 2009-02-13 14:28
      哈哈,這個(gè)東西我曾經(jīng)也實(shí)現(xiàn)過。樓上某位說不能移動(dòng),這個(gè)很好解決,自寫窗體事件,它只要一動(dòng),馬上重新截屏重新繪制窗體。  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  hello Posted @ 2009-05-13 21:10
      題目說的太大了。。你只是做了“透明”效果。。但可沒有做到使窗體呈任意形狀。。。我就沖這個(gè)任意形狀來的。。。結(jié)果。。。。。。  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  dyerac Posted @ 2009-05-14 14:36
      @hello
      仔細(xì)看完再說咯:
      ------
      ps:你也許還會(huì)說,e?怎么沒講任意形狀窗口如何打造?
      呵呵,其實(shí)只要把窗口按上述方法設(shè)置成透明,再去掉邊框,再換上自己的邊框,不就完成了馬?
      相信聰明的各位一定很容易就辦到咯  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  第一次 Posted @ 2009-06-21 01:21
      我很少留言的,這次如果不說聲謝謝我都過意不去了!  回復(fù)  更多評(píng)論   

    • # re: 用java打造任意形狀窗口和透明窗口  月下幽杳 Posted @ 2013-06-05 12:35
      根本沒必要搞這么復(fù)雜,
      this.setUndecorated(true);
      AWTUtilities.setWindowOpaque(this, false);
      然后調(diào)用一個(gè)JLabel來顯示圖片(png部分透明圖片),然后作為底層容器,可以實(shí)現(xiàn)任意窗口  回復(fù)  更多評(píng)論   

     
    Copyright © dyerac in java... Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 直接进入免费看黄的网站| 免费的一级片网站| 国产麻豆视频免费观看| xvideos永久免费入口| 日韩亚洲国产综合高清| 亚洲色图在线播放| 国产亚洲人成网站在线观看不卡 | 亚洲国产精华液网站w| 日韩高清在线高清免费| 嘿嘿嘿视频免费网站在线观看| 三年片免费观看大全国语| 特级一级毛片免费看| 亚洲国产精品精华液| 久久精品国产亚洲αv忘忧草| 亚洲第一精品福利| 亚洲αv久久久噜噜噜噜噜| 亚洲综合区小说区激情区| 四虎永久免费观看| 国产精品嫩草影院免费| 天天拍拍天天爽免费视频| 色se01短视频永久免费| 亚洲高清免费在线观看| aⅴ在线免费观看| 天天影视色香欲综合免费| 97免费人妻在线视频| 鲁大师在线影院免费观看 | 国产亚洲色视频在线| 久久久久无码专区亚洲av| 亚洲日韩人妻第一页| 亚洲情侣偷拍精品| 综合亚洲伊人午夜网| 亚洲午夜国产精品无码| 亚洲综合伊人久久大杳蕉| 国产aⅴ无码专区亚洲av麻豆| 亚洲日韩在线观看免费视频| 亚洲色偷偷综合亚洲AV伊人| 久久亚洲国产精品123区| 国产亚洲AV无码AV男人的天堂| 亚洲精品美女久久777777| 亚洲AV无码专区国产乱码4SE | 青青草原1769久久免费播放|