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

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

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

    隨筆 - 18  文章 - 96  trackbacks - 0
    <2007年9月>
    2627282930311
    2345678
    9101112131415
    16171819202122
    23242526272829
    30123456


    常用鏈接

    留言簿(4)

    隨筆檔案

    相冊

    我的兄弟們

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

         摘要: 很久沒有回來這里寫技術(shù)BLOG了,這里的氛圍還行,大家都對一個問題積極的思考(至少之前這里給我的感覺是這樣的),2年里面自己也忙著做些事情,沒有寫,最近有空也就寫寫,偶爾會去oschine.net看看新聞,然后就在那里看到了一個人提出的問題很有意思,就是怎么表達(dá)式求解,例如(1 + 2) / 3 - 1 * 2 + 5 / (3 + 2)這樣的字符串輸入,怎么樣解析之后輸出結(jié)果。說來也好笑,對于我...  閱讀全文
    posted @ 2011-11-09 10:36 ruislan 閱讀(1761) | 評論 (6)編輯 收藏
         摘要: 很久沒來了,不是一位朋友給我發(fā)郵件問我關(guān)于swing的問題,才想起,然后翻看了之前的代碼,發(fā)現(xiàn)當(dāng)年還實現(xiàn)了一個Vista風(fēng)格的按鈕沒有放出來,現(xiàn)在補上,也許現(xiàn)在人們的swing水平對我這代碼不屑一顧,不過還是依然拋磚引玉,給未知的人們一個啟發(fā)。還是老慣例,上效果圖: 正常情況下:(和vista一樣具有焦點的按鈕的顏色漸深漸淺的循環(huán)變化) 鼠標(biāo)在區(qū)域內(nèi)時: 鼠標(biāo)按下去: 然后是代...  閱讀全文
    posted @ 2009-09-12 12:54 ruislan 閱讀(2486) | 評論 (3)編輯 收藏
    認(rèn)為自己是達(dá)人的就不用看了。只是一點小技巧,不敢班門弄斧,做個總結(jié),為那些還不知道的解解惑,隨便告訴大家我還活著。

    最近客戶提了個小改動,客戶網(wǎng)站上圖片存放的目錄需要改動一下。例如在網(wǎng)上訪問是www.tkk7.com/images/*.*,在服務(wù)器上的目錄是D:/<webroot>/images/*.*,客戶想把這個images目錄下的資源全部移動到E:/data/里面去,但是在網(wǎng)上www.tkk7.com/images/*.*還是同樣可以訪問得到,我剛開始犯了形式主義的錯誤,老是想用程序解決,一會filter,一會servlet/action,后來我配置程序的時候突然看到了server.xml,于是我想到了選擇用映射的方式。正好,server.xml中的<Context>就是做這個事情的。于是乎我們在<Host></Host>中增加了一個<Context docBase="E:/data/images" path="/images">,OK,重啟之后,所有檢索www.tkk7.com/images路徑下的資源實際上都由E:/data/images下的資源提供了。

    posted @ 2008-02-15 16:41 ruislan 閱讀(1272) | 評論 (3)編輯 收藏
    在寫多線程程序的時候,你就像個經(jīng)理,手下有那么或多或少的職員,你負(fù)責(zé)協(xié)調(diào)職員之間的工作,如果你稍不留神,職員之間就陷入了相互等待的尷尬狀態(tài)。還好,大多數(shù)時候多線程都還在我們掌控之內(nèi),即便是遇到這樣的deadlock情況,我們也能夠去修正,但是有的時候生活就是那么不盡人意,特別是NIO這種你不能掌控的時候,且看下面的代碼:

    /**
     * @(#)DeadLock.java  v0.1.0  2007-12-13
     
    */
    package ruislan.rswing.test;

    import java.net.InetSocketAddress;
    import java.nio.channels.ClosedChannelException;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.util.concurrent.Executors;

    /**
     * NIO DeadLock
     * 
     * 
    @author ruislan <a href="mailto:z17520@126.com"/>
     * 
    @version 0.1.0
     
    */
    public class DeadLock {
        
    public static void main(String[] args) throws Exception {
            Service service 
    = new Service();
            Executors.newSingleThreadExecutor().execute(service);

            SocketChannel channel 
    = SocketChannel.open();
            channel.configureBlocking(
    false);
            channel.connect(
    new InetSocketAddress("http://www.tkk7.com"80));
            service.addChannel(channel);
        }

        
    static class Service implements Runnable {
            Selector selector;

            
    public Service() {
            }

            
    public void run() {
                
    try {
                    selector 
    = Selector.open();
                    
    while (true) {
                        selector.select();
                        System.out.println(selector.selectedKeys().size());
                    }
                } 
    catch (Exception e) {
                }
            }

            
    public void addChannel(SocketChannel channel) {
                
    try {
                    channel.register(selector, SelectionKey.OP_CONNECT
                            
    | SelectionKey.OP_READ);
                    System.out.println(
    "can reach here?when pigs fly!");
                } 
    catch (ClosedChannelException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    乍看之下,我們的代碼沒有問題,但是運行之后你會發(fā)現(xiàn),這句System.out.println("can reach here?when pigs fly!");永遠(yuǎn)無法執(zhí)行,也就是說register()方法被阻塞了!Oh god bless,讓我們看看JavaDoc是怎么說的:

    ...
    可在任意時間調(diào)用此方法。如果調(diào)用此方法的同時正在進(jìn)行另一個此方法或 configureBlocking 方法的調(diào)用,則在另一個操作完成前將首先阻塞該調(diào)用。然后此方法將在選擇器的鍵集上實現(xiàn)同步,因此如果調(diào)用此方法時并發(fā)地調(diào)用了涉及同一選擇器的另一個注冊或選擇操作,則可能阻塞此方法的調(diào)用。
    ...

    看這句“可在任意時間調(diào)用此方法。”,也就是說我們調(diào)用的時間沒有任何限制,而阻塞的情況只會出現(xiàn)在“如果調(diào)用此方法的同時正在進(jìn)行另一個此方法或 configureBlocking 方法的調(diào)用”的情況下,即便是阻塞了,我相信“正在進(jìn)行另一個此方法或configureBlocking”也不會花掉太多的時間,況且這里沒有上面這樣的情況出現(xiàn)。那register()是被誰擋住了?或者是BUG?

    我們來分析一下程序,程序有兩個線程主線程和Service線程,主線程啟動后啟動了Service線程,Service線程啟動Selector然后Service線程陷入select()的阻塞中,同時,主線程調(diào)用Service的addChannel()方法來添加一個SocketChannel,嗯,兩個線程之間唯一的聯(lián)系就是selector,看來要從selector尋找線索,很可惜,selector的實現(xiàn)沒有源代碼可查,不過可以肯定是channel的register()會調(diào)用selector的register(),雖然此時持有selector的Service線程被select()方法所阻塞,但是并不影響其他線程對其操作吧?那么,剩下的解釋就是Selector的select()方法和register()方法公用了一個鎖,select()方法阻塞住了,所以register()拿不到這個鎖了,那么這樣一來我們就只能保證讓select()或者register()不能同時調(diào)用或者register()調(diào)用的時候select()不持有這個鎖,也就是說我們要用Service線程自己來執(zhí)行addChannel()方法,所以改進(jìn)如下:

    /**
     * @(#)DeadLock.java  v0.1.0  2007-12-13
     
    */
    package ruislan.rswing.test;

    import java.net.InetSocketAddress;
    import java.nio.channels.ClosedChannelException;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.util.Queue;
    import java.util.concurrent.LinkedBlockingQueue;

    /**
     * NIO DeadLock
     * 
     * 
    @author ruislan <a href="mailto:z17520@126.com"/>
     * 
    @version 0.1.0
     
    */
    public class DeadLock {
        
    public static void main(String[] args) {
            Service service 
    = new Service();
            
    new Thread(service).start();
            
    for (int i = 0; i < 5; i++) {
                
    new Thread(new ChannelAdder(service)).start();
            }
        }

        
    static class ChannelAdder implements Runnable {
            
    private Service service;

            
    public ChannelAdder(Service service) {
                
    this.service = service;
            }

            @Override
            
    public void run() {
                
    try {
                    SocketChannel channel 
    = SocketChannel.open();
                    channel.configureBlocking(
    false);
                    channel.connect(
    new InetSocketAddress(
                            
    "http://www.tkk7.com"80));
                    service.addChannel(channel);
                } 
    catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        
    static class Service implements Runnable {
            
    private Selector selector;
            
    private Queue<SocketChannel> pendingRegisters;

            
    public Service() {
                pendingRegisters 
    = new LinkedBlockingQueue<SocketChannel>();
            }

            
    public void run() {
                
    try {
                    selector 
    = Selector.open();
                    
    while (true) {
                        selector.select();
                        System.out.println(selector.selectedKeys().size());
                        handlePendingRegisters();
                    }
                } 
    catch (Exception e) {
                }
            }

            
    public void handlePendingRegisters() {
                
    while (!pendingRegisters.isEmpty()) {
                    SocketChannel channel 
    = pendingRegisters.poll();
                    
    try {
                        channel.register(selector, SelectionKey.OP_CONNECT);
                        System.out.println(
    "can reach here?yeah!");
                    } 
    catch (ClosedChannelException e) {
                        e.printStackTrace();
                    }
                }
            }

            
    public void addChannel(SocketChannel channel) {
                pendingRegisters.offer(channel);
                selector.wakeup();
            }
        }
    }


    新的代碼,我們在Service的線程提供了一個待處理Channel隊列,然后在添加一個SocketChannel到隊列中時喚醒這個selector,取消阻塞,然后在Service的循環(huán)中處理這個pendingChannel,這樣就避免這個Deadlock的發(fā)生了。當(dāng)然我們亦可以在那個代碼上將select的超時時間設(shè)置非常的短,然后讓兩個線程去競爭,這樣做有太多的不可控性,不推薦了。

    posted @ 2007-12-13 18:31 ruislan 閱讀(1349) | 評論 (3)編輯 收藏
        UI作為用戶與電腦的交互界面,如何更好的服務(wù)于人,讓人們用起來方便、簡單、快捷一直是UI開發(fā)者應(yīng)該有的覺悟,作為開發(fā)人員的我們來說,不應(yīng)該只是把UI推給電腦平面設(shè)計人員,更不應(yīng)該一手包辦了(如果你不是一個人的話)。我們開發(fā)人員常常在開發(fā)UI的時候避重就輕,基本上都在強調(diào)code的美學(xué),模式的應(yīng)用而忽略了真實用戶的感受。我們常常得意于自己技術(shù)的美麗,而將一些比自己水平低的應(yīng)用嗤之以鼻。但是用戶卻從來不關(guān)心代碼是如何寫的,他們關(guān)心這個應(yīng)用是否對他們有用,順手乎?聰明乎?所以如果我們只是美麗于自己的設(shè)計,太關(guān)注軟件的本身而忽略了用戶的感受,就跟某些象牙塔里拿著錢做些無用的研究的人沒什么兩樣,或許有個美麗的名詞,為了科學(xué)。
        那么如何才能算是好的UI人性化的設(shè)計呢?這個得看針對的用戶主要是哪些。我們熟知的操作系統(tǒng)Windows XP,Windows Vista,Vista是微軟最新的操作系統(tǒng),包含了很多開發(fā)人員辛苦的結(jié)晶,但是在我身邊的很多人都不愿意裝它,也包括一些新聞的調(diào)查也說Vista不如當(dāng)年XP出世那般火爆,他們大多數(shù)不愿裝的都說了同樣的話,XP都還有很多不懂,怕Vista更搞不懂,說實話我用過Vista,就我這么一個算是業(yè)內(nèi)人士用起來當(dāng)然駕輕就熟,再加上我們都有勇于創(chuàng)新的精神,所以常常去用新的東西,而普通客戶就不這么想了,我問了幾個不懂電腦才安裝了Vista的用戶的感受,“開始菜單的‘開始’兩個字沒有了,我還以為換了位置”,“界面比XP漂亮啊,但是我的機器好像有點慢,是不是要設(shè)置個什么啊”……再來我們熟知的AJAX,我已經(jīng)接到過很多次不同的人給我的電話,說“為什么網(wǎng)頁打開的時候突然好卡了,以前不這樣啊?”,“網(wǎng)頁瀏覽不了,老說請稍候,數(shù)據(jù)加載中,等了很久,就是不出現(xiàn)”……面對這些電話或許我們會說,你們怎么那么笨啊,它卡是因為在下東西,在執(zhí)行JS,寫JS的人太垃圾,浪費了資源,不出現(xiàn)就刷新啊,不要瀏覽那個不專業(yè)的網(wǎng)站了,等等就OK了等等回答,其實很多時候我們可以避免用戶的問題出現(xiàn),例如你的AJAX的JS太大的時候,可以先提示用戶說,數(shù)據(jù)量較大,請稍后,如果長時間無反應(yīng),請按瀏覽器的刷新按鈕,或者嘗試按下F5鍵。
        我還見過許多軟件鼓吹自己的功能如何強大,如何厲害,多么的人性化,但是我打開他們的軟件,居然發(fā)現(xiàn)只能用鼠標(biāo)操作!!這是多么大的UI設(shè)計失敗!在舉一個例子,MSN和QQ兩個IM,如果你用MSN,在聯(lián)系人框里按上下的話,MSN會很聰明的明白你是要選擇上一位或者下一位聯(lián)系人,而QQ會很聰明的明白你是要拖動滑動條!@#$,還有很多軟件記憶力太差,不管我如何操作,它就是記不住,關(guān)閉軟件重新啟動后又回到了最初的模樣,還有的軟件自信心不足,一再問我“你確定嗎?”,“真的要這樣做嗎?”,“或許您不小心點了?”而我只是在點關(guān)閉這個娛樂性質(zhì)的軟件而已,而有些軟件又特膽肥,做了一個不可恢復(fù)的操作盡然連提示都沒有,還有的軟件文化太差,常常把一個按鈕或者圖標(biāo)該表達(dá)的含義弄得模棱兩可,以至于常常讓我們會錯意,做錯操作,或者把一些高風(fēng)險的操作放在常用操作的旁邊,很容易點錯,還有的把不常用的操作也放到常用操作區(qū),還不告訴用戶怎么去掉,這樣的例子不勝枚舉。
        出現(xiàn)這些問題的原因在于我們與用戶之間的思維方式有著很大的不同。例如在寫文章之前我才將老爸從我的電腦椅上請下來,請下來之前他正在看我吃飯前的網(wǎng)頁——“界面九宮格”,我說您能看得懂嘛,他說“不懂,不過這軟件的界面不都這樣嘛?再說了,一張紙就8個方位,加上中間正好九個,你的東西不擺這里擺哪里啊?”,我正要解釋一下這與軟件設(shè)計的關(guān)系,但是突然一想,是啊,有道理啊,要是我給他老人家再解釋一下可以放在上面和下面,那不就是3D的了。再比如我一直都很不屑一顧的網(wǎng)絡(luò)實名,但是當(dāng)它被我在很多人的機器里面消滅之后,很多人都打電話問我,怎么在地址欄里面輸入漢字,跳出搜索界面了,不是那個漢字的網(wǎng)站了,以前是有的,原來我只看到了它流氓的一面,忽略了普通用戶是根本記不住網(wǎng)址在哪里,甚至有些用戶不懂英文,你怎么讓他記得住全是英文的網(wǎng)址呢?不過過了幾天,他們都說不用了,有一個網(wǎng)站導(dǎo)航網(wǎng)址做了他們的主頁,他們平日想去的網(wǎng)站都在上面列著的,我后來才知道,就是被我以前同寢室的刪除了半天的hao123。所以我們必須充分考慮我們的應(yīng)用是針對哪些用戶,他們是哪一類人,習(xí)慣是什么,當(dāng)然還有就是UI設(shè)計的一些基本的東西,例如鼠標(biāo)能夠完成的動作,同樣鍵盤也能完成等等。

    posted @ 2007-11-11 13:36 ruislan 閱讀(1427) | 評論 (5)編輯 收藏
    Swing作為一個完整的UI解決方案,包含了一個GUI程序所擁有的方方面面,當(dāng)然包括作為普通程序也好,作為GUI程序也好,作為Web程序等等程序都共有的線程概念。

    Swing中的線程有三種:初始線程,事件線程,工作線程

    這三種線程基本上包括了讓一個GUI完美工作的方方面面,首先,初始線程被用來創(chuàng)建GUI組件、資源加載和啟動GUI組件,眾所周知,Swing是事件驅(qū)動的,所以當(dāng)UI出現(xiàn)了之后,初始線程就完成了它的使命,并將接力棒交給了事件線程,Event Dispatch Thread,這個時候所有組件的事件行為都交給了這個線程去處理,當(dāng)然我們自己也要需要用線程來運行許多任務(wù),優(yōu)秀的GUI程序是絕不能讓界面被卡死不動的,那會讓用戶崩潰,所以這個時候就需要工作線程了,也可以說是在背后運行的線程,這種線程是勞動階級,任勞任怨的執(zhí)行者長時間的工作。

    初始線程的寫法很簡單,這樣就可以了:
    SwingUtilities.invokeLater(new Runnable() {
        
    public void run() {
            initGUI();
            showGUI();
        }
    }

    但是Applet中,你可能需要調(diào)用SwingUtilities.invokeAndWait這個方法,要是init方法返回了,瀏覽器開始展現(xiàn)Applet,但是GUI的創(chuàng)建還在thread中,出錯也是可想而知的。
    至于invokeLater和invokeAndWait這兩個線程的簡單點的區(qū)別就是invokeLater是異步的,你不知道它什么時候會開始執(zhí)行,invokeAndWait則是同步的,它會等到動作執(zhí)行完成之后才返回。

    Event Dispatch Thread不是線程安全的,所以要用線程來與它打交道要注意了,同步問題總是讓人頭痛。

    在1.5之前應(yīng)該說工作線程都是由開發(fā)人員自己去定義的,但是現(xiàn)在Swing推薦了SwingWorker這個類,包括Swing最新的符合JSR標(biāo)準(zhǔn)的Swing AppFramework也使用了SwingWorker這個類來處理所有在GUI背后做的事情。

    了解了Swing中的線程定義,能夠讓我們更好的寫出優(yōu)美的基于Swing的GUI程序。

    posted @ 2007-11-04 12:40 ruislan 閱讀(1269) | 評論 (2)編輯 收藏
    很多人都說我們這行的人是偏執(zhí)狂,我也覺得我是有一點倔脾氣,就像看連續(xù)劇,從第一集開始一直到最后一集才會關(guān)上電腦,一旦一個研究開始,就一定要有一個結(jié)果或者令自己滿意的結(jié)果才結(jié)束,但是當(dāng)我看到這位“偏執(zhí)狂”之后,我覺得我只是稍微有一點偏執(zhí)而已。
    研究UI繪制的時候很容易陷入另外一個領(lǐng)域,圖像領(lǐng)域,或者是游戲領(lǐng)域,我不喜歡做游戲是因為我愛玩游戲,如果玩和工作綁在一起了的話,那么工作之后的休閑就也是工作了。
    好了,說了點廢話,下面是對FengGUI的介紹.
    FengGUI是一個建立在OpenGL上的GUI的API,F(xiàn)engGUI提供了很多標(biāo)準(zhǔn)的UI組件,像Button,TextField,Panel之類的,下面先看看截圖:

    GridLayout的截圖

    可分割的面板


    要說到最大的特色,莫過于FengGUI基于OpenGL,并且可以在組件里面直接使用OpenGL,可以輕松的集成jME(java Monkey Engine,一個非常棒的Java 3D游戲引擎),jogl(Java OpenGL API),lwjgl(輕量級Java游戲庫),jPCT(同樣非常棒的Java 3D游戲引擎),但是在跑它的demo時我也感受到了CPU 80% 工作率的壓力,所以就目前的我膚淺的了解,用它來做普通的GUI程序估計還為時有點早,但是如果是游戲中的組件的話確實是與上述引擎和API的非常好的補充。
    posted @ 2007-10-27 20:34 ruislan 閱讀(1707) | 評論 (2)編輯 收藏
        以前或許大家對一個UI組件是否透明沒有那么關(guān)心,但是自從Vista的毛玻璃出現(xiàn)后,UI透明就成了大家非常關(guān)注的一個話題,于是Java陣營開始了鋪天蓋地的討論如何實現(xiàn)透明的效果,但是很不幸的是無論組件如何透明和變換,但是能夠放置于屏幕任何位置的Window一族就是沒法透明和變形,原生代碼的問題還是交給原生代碼來解決吧。
        自己寫原生代碼是可怕的,特別是對我這種只知道Java的平凡程序員,所以我們得借助一個非常方便的跨平臺的調(diào)用OS function方便的Lib,JNA便是最佳選擇(那個誰,這里不是討論JRuby&JPython的)。
        so, all robots, transform!
        下面我們要做一個界面是圓角四邊形的,中間有一個滑動條來滑動調(diào)節(jié)透明度。先看看做好的截圖。
        
        注意圖中的JFrame邊角已經(jīng)變成了圓弧,滑動滑塊,JFrame開始透明,桌面的圖標(biāo)顯現(xiàn)出來,下面是代碼。
       
    /**
     * @(#)TransparentFrame.java  v0.1.0  2007-10-21
     
    */
    package ruislan.rswing.test;

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.geom.RoundRectangle2D;

    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JSlider;
    import javax.swing.border.LineBorder;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;

    import com.sun.jna.examples.WindowUtils;

    /**
     * Transparent JFrame use JNA
     * 
     * 
    @author ruislan <a href="mailto:z17520@126.com"/>
     * 
    @version 0.1.0
     
    */
    public class TransparentFrame {
        
    private JFrame frame;
        
    private JPanel container;
        
    private JSlider slider;
        
    private JPanel titleBar;
        
    private JLabel titleLabel;
        
    private JButton closeButton;

        
    public static void main(String[] args) {
            
    new TransparentFrame().launch();
        }

        
    private void launch() {
            createUI();
            launchUI();
        }

        
    protected void launchUI() {
            frame.setVisible(
    true);
        }

        
    protected void createUI() {
            System.setProperty(
    "sun.java2d.noddraw""true");
            frame 
    = new JFrame();
            frame.setSize(
    200150);
            frame.setAlwaysOnTop(
    true);
            frame.setUndecorated(
    true);

            container 
    = new JPanel();
            frame.setContentPane(container);
            container.setLayout(
    new BorderLayout());
            container.add(
    new JLabel("Ubunto vs Vista, I like both."),
                    BorderLayout.CENTER);
            container.setBorder(
    new LineBorder(Color.BLACK));

            titleBar 
    = new JPanel();
            titleBar.setLayout(
    new BorderLayout());
            titleLabel 
    = new JLabel("JNA is great!");
            titleBar.add(titleLabel, BorderLayout.CENTER);
            titleBar.setBorder(
    new LineBorder(Color.GRAY));
            closeButton 
    = new JButton("X");
            closeButton.setFocusPainted(
    false);
            closeButton.addActionListener(
    new ActionListener() {
                @Override
                
    public void actionPerformed(ActionEvent e) {
                    System.exit(
    0);
                }
            });
            titleBar.add(closeButton, BorderLayout.EAST);
            container.add(titleBar, BorderLayout.NORTH);

            slider 
    = new JSlider(0100);
            slider.setValue(
    100);
            slider.addChangeListener(
    new ChangeListener() {
                @Override
                
    public void stateChanged(ChangeEvent e) {
                    
    float value = slider.getValue();
                    WindowUtils.setWindowAlpha(frame, value 
    * 0.01f);
                }
            });
            container.add(slider, BorderLayout.SOUTH);
            RoundRectangle2D.Float mask 
    = new RoundRectangle2D.Float(00, frame
                    .getWidth(), frame.getHeight(), 
    2020);
            WindowUtils.setWindowMask(frame, mask);
            centerWindow(frame);
        }

        
    public static void centerWindow(Container window) {
            Dimension dim 
    = Toolkit.getDefaultToolkit().getScreenSize();
            
    int w = window.getSize().width;
            
    int h = window.getSize().height;
            
    int x = (dim.width - w) / 2;
            
    int y = (dim.height - h) / 2;
            window.setLocation(x, y);
        }
    }

        利用JNA來制作透明效果非常簡單,只需要調(diào)用WindowUtils.setWindowAlpha(window, alpha)就可以了。當(dāng)然這是JNA特別為UI寫的工具代碼。如果要改變形狀,用WindowUtils.setWindowMask(window, shape)或者WindowUtils.setWindowMask(window, icon)就可以了,但是要注意一點必須設(shè)置System.setProperty("sun.java2d.noddraw""true"),否則JNA會告訴你這個程序不支持透明。當(dāng)然要運行起來,還得需要兩個Jar,jna.jarexamples.jar ,都不是很大,只有200多K。
        雖然這篇文章只是介紹了一下JNA關(guān)于Swing的簡單用法,但是有了這個我最先到的便是可以做類似于Yahoo Widget和Google Widget之類的東西了,還可以做好看的fishEye,SideBar,JNA的JAR兩個合起來不過400K,卻能讓這么多復(fù)雜的事情簡單化,真是精湛的藝術(shù)啊,嗯。

    posted @ 2007-10-21 13:43 ruislan 閱讀(4385) | 評論 (12)編輯 收藏
    很久沒有上來更新了,因為一些原因。但是,我又回來了,套用MASK的話,小子們,想我嗎?

    回來了先報告一個Blogjava的BUG,就是用Opera9瀏覽器寫文章時不能用鼠標(biāo)點擊編輯區(qū),還好用TAB可以切換過來,然后就是用Google輸入法的話,標(biāo)點符號和數(shù)字輸入一次,編輯區(qū)會出來兩個,最后就是編輯完之后好像內(nèi)容也保存不了,所以我又換回FF來編輯了。

    回來了卻不知從何開始了,組件的改造也算拋磚引玉了(當(dāng)然如果你們喜歡,我還可以繼續(xù)改造),冰封的程序要繼續(xù)改造的話就要開一個工程了大家集體參與了,所以那就還是先從上次哪位仁兄提到的組件透明的問題,從那個開始吧!show time。

    posted @ 2007-10-20 16:30 ruislan 閱讀(433) | 評論 (1)編輯 收藏
    昨天我們改進(jìn)了選擇區(qū),今天我們來繼續(xù)為選擇區(qū)選定之后添加一個操作框
    下面是改進(jìn)后的截圖:

    正常的情況,右下角出現(xiàn)了一個操作框

    在三個(左、右、底)邊際的情況,我們重新計算了位置。

    三個按鈕還沒有功能,也不是圖片,但是我們離QQ的截屏程序又進(jìn)一步了,嗯!

    posted @ 2007-09-14 18:48 ruislan 閱讀(1160) | 評論 (10)編輯 收藏
    “千里冰封” 兄弟的截屏程序酷斃了,但是好像9月4日之后就沒有繼續(xù)更新了,我們來繼續(xù)為他的程序改進(jìn),順便也把我們這幾天都在講的2D繪制用進(jìn)來,我們的目標(biāo)是讓冰封的截屏程序成為截屏程序里的王!
    今天先改進(jìn)一下截圖時候的選框,還是先放上截圖的截圖(*o*):

    這是原來的圖片,下面是改進(jìn)后的

    和改進(jìn)的代碼部分:
    這部分代碼插入 Temp類的paintComponent方法中的    if (showTip) 這句的前面
        Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, 
    0.3F));
                g2d.setColor(Color.RED.brighter().brighter());
                
    int sX = Math.min(startX, endX);
                
    int sY = Math.min(endY, startY);
                g2d.fillRect(sX, sY, Math.abs(endX 
    - startX), Math.abs(endY
                        
    - startY));
                g2d.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, 1F));
                
    boolean drawCTip = endX - startX != 0 && endY - startY != 0;
                
    if (drawCTip) {
                    String cTip 
    = String.format("%dX%d", Math.abs(endX - startX),
                            Math.abs(endY 
    - startY));
                    
    int cTipH = 20;
                    Font cTipFont 
    = new Font("system", Font.BOLD, 16);
                    g2d.setFont(cTipFont);
                    
    int cTipW = SwingUtilities.computeStringWidth(
                            getFontMetrics(cTipFont), cTip);
                    g2d.setPaint(Color.BLACK);
                    
    int cStartY = sY - cTipH > 0 ? sY - cTipH : sY;
                    g2d.fillRect(sX, cStartY, cTipW, cTipH);
                    g2d.setPaint(Color.WHITE);
                    g2d.drawString(cTip, sX, cStartY 
    == sY ? sY + cTipH - 3
                            : sY 
    - 3);
                }
                g2d.dispose();

    怎么樣,比起QQ的截圖程序,我們又近一步了,嗯。

    posted @ 2007-09-13 13:28 ruislan 閱讀(1488) | 評論 (10)編輯 收藏
         摘要: 嗯,BeanSoft的話很有道理,令我敬佩,也許是昨天在下對那個“更好的”三個字感到一時憤慨,所以看到UI就自己擴(kuò)大了問題,想到迎合LookAndFeel上面去了,在此說句對不起了。你的回帖里面偏重于從整個組件的設(shè)計和重用性上,我的文章主要講的是如何將2D繪制和組件的繪制結(jié)合起來,看客如果既了解了如何繪制自己想要的組件,又能設(shè)計得體,重用性高的話也算是對我拋磚引玉的欣慰了。...  閱讀全文
    posted @ 2007-09-12 13:36 ruislan 閱讀(2440) | 評論 (11)編輯 收藏
    主站蜘蛛池模板: 亚洲精品无码99在线观看| 亚洲AV午夜成人影院老师机影院| 水蜜桃视频在线观看免费| 国产亚洲大尺度无码无码专线| 毛片无码免费无码播放| 亚洲国产精品日韩av不卡在线 | 亚欧免费视频一区二区三区| 亚洲人成网站色在线观看| 亚洲成av人片一区二区三区| 青青草原1769久久免费播放| 亚洲成av人在线观看网站| 亚洲国产无套无码av电影| 大学生一级特黄的免费大片视频| www.av在线免费观看| 亚洲一卡2卡3卡4卡国产网站| 亚洲精品视频在线看| 韩国免费一级成人毛片| 美女网站在线观看视频免费的| 亚洲不卡中文字幕| 国产成人亚洲精品91专区手机| 青青青免费国产在线视频小草| 中国内地毛片免费高清| 亚洲精品一卡2卡3卡四卡乱码| 亚洲av女电影网| 亚洲男人av香蕉爽爽爽爽| 嫩草影院免费观看| 亚洲国产精品免费视频| 好湿好大好紧好爽免费视频| 亚洲精品无码中文久久字幕| 18亚洲男同志videos网站| 国产成人精品久久亚洲高清不卡 | 四虎成人精品一区二区免费网站| 蜜桃成人无码区免费视频网站| 一级美国片免费看| 久久水蜜桃亚洲AV无码精品| 亚洲不卡中文字幕| 亚洲人成在线影院| 亚洲乱码日产一区三区| 亚洲欧洲中文日韩久久AV乱码| 日韩高清在线高清免费| 猫咪社区免费资源在线观看|