Java桌面技術(shù)

          Java Desktop Technology

          常用鏈接

          統(tǒng)計(jì)

          友情連接

          最新評(píng)論

          打造專業(yè)外觀-三

          在《打造專業(yè)外觀-二》中,留下了3個(gè)未實(shí)現(xiàn)的功能:窗口標(biāo)題和圖標(biāo),邊緣圓角,功能按鈕。在本篇中將實(shí)現(xiàn)這些功能來(lái)完結(jié)打造專業(yè)外觀-窗口部分的講解。

          一、窗口標(biāo)題。
          SWT窗口Shell有public void setText(String string),public void setImage(Image image) 方法用來(lái)設(shè)置標(biāo)題和圖標(biāo)。但是現(xiàn)在窗口的樣式已經(jīng)是SWT.NO_TRIM,不再有標(biāo)題欄了,因此標(biāo)題只能自己“畫(huà)”。在paintControl方法中添加如下代碼:
          else if (e.getSource() == northPanel) {
             String text = getText();
             if (text != null) {
              gc.setForeground(titleColor);
              gc.drawText(text, e.width / 2 - gc.stringExtent(text).x / 2,
                e.height / 2 - gc.stringExtent(text).y / 2, true);
             }
             Image image = getImage();
             if (text == null) {
              text = "";
             }
             if (image != null) {
              gc.drawImage(image, e.width / 2 - gc.stringExtent(text).x / 2
                - image.getBounds().width - 10, e.height / 2
                - image.getBounds().height / 2);
             }
            }
          標(biāo)題文字居中顯示,圖標(biāo)居標(biāo)題文字10像素。代碼中“e.width”獲取繪圖環(huán)境上下文的長(zhǎng)度,“gc.stringExtent(text).x”獲得標(biāo)題文字的長(zhǎng)度,“true”表示繪制的文字不需要背景,如果是false,會(huì)看到有明顯的灰色矩形作背景。繪制圖標(biāo)不難理解。當(dāng)然通常的標(biāo)題欄是九宮格的“上部”面板,所以要為northPanel添加繪制監(jiān)聽(tīng)器。northPanel.addPaintListener(this);

          二、邊緣圓角
          如果你不熟悉SWT的Region使用,請(qǐng)先研讀http://www.eclipse.org/swt/snippets/中的“create a non-rectangular shell from a transparent image”程序。
          該程序通過(guò)分析Image各個(gè)像素點(diǎn)的alpha值,來(lái)獲取Region的填充。你可以通過(guò)本地圖片實(shí)例化一個(gè)Image對(duì)象,支持透明的圖片格式有PNG和GIF兩種,美工都會(huì)知道這一點(diǎn),本程序中用到的southwest.png、southeast.png、northeast.png、northwest.png均符合,以圖片透明度來(lái)實(shí)現(xiàn)不規(guī)則窗體是常用的方法,這樣做的好處是只要更換圖片就可達(dá)到改變窗體形狀。但是有些應(yīng)用自身規(guī)定一種顏色為透明顏色,例如QQ,規(guī)定紫色為透明顏色,所以在它的實(shí)現(xiàn)中通過(guò)對(duì)圖片逐個(gè)像素點(diǎn)分析,發(fā)現(xiàn)RGB是紫色就認(rèn)為是透明。好,原理大致如此。下面來(lái)定義一個(gè)函數(shù)來(lái)完成次功能:
          private Region getImageTransparenceRegion(Image image, int offsetX,
             int offsetY) {
            Region region = new Region();
            final ImageData imageData = image.getImageData();
            if (imageData.alphaData != null) {
             Rectangle pixel = new Rectangle(0, 0, 1, 1);
             for (int y = 0; y < imageData.height; y++) {
              for (int x = 0; x < imageData.width; x++) {
               if (imageData.getAlpha(x, y) != 255) {
                pixel.x = imageData.x + x + offsetX;
                pixel.y = imageData.y + y + offsetY;
                region.add(pixel);
               }
              }
             }
            }
            return region;
           }
          該方法參考了Snippet21(http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet219.java?view=co),方法返回給定圖片透明部分構(gòu)造的Region。然后在controlResized末尾添加如下代碼:
          Region oldRegion = getRegion();
            if (oldRegion != null && !oldRegion.isDisposed()) {
             oldRegion.dispose();
            }
            Region newRegion = new Region();
            newRegion.add(0, 0, getSize().x, getSize().y);
            newRegion.subtract(getImageTransparenceRegion(northwestImage, 0, 0));
            newRegion.subtract(getImageTransparenceRegion(northeastImage,
              getSize().x - northeastImage.getBounds().width, 0));
            newRegion.subtract(getImageTransparenceRegion(southwestImage, 0,
              getSize().y - southwestImage.getBounds().y));
            newRegion.subtract(getImageTransparenceRegion(southeastImage,
              getSize().x - southeastImage.getBounds().width, getSize().y
                - southeastImage.getBounds().height));
            setRegion(newRegion);

          Shell實(shí)例通過(guò)setRegion(Region region)設(shè)置區(qū)域來(lái)實(shí)現(xiàn)不規(guī)則巨型窗體,但是前提是把樣式設(shè)置成SWT.NO_TRIM。
          由于窗體尺寸的變更相應(yīng)的區(qū)域也要跟著調(diào)整,所以要把邏輯寫(xiě)在controlResized方法中,而且每次改變過(guò)后要釋放Region資源并重新設(shè)置新的區(qū)域。上述在初始化Region對(duì)象后,“newRegion.add(0, 0, getSize().x, getSize().y);”方法將覆蓋窗口整個(gè)區(qū)域,隨后的subtract挖掉四個(gè)角落的透明部分。

          三、功能按鈕
          出于時(shí)間比較緊,只添加關(guān)閉按鈕,其他按鈕如最小化、最大化原理相同。
          通常按鈕有四種狀態(tài),分別是:正常態(tài)、鼠標(biāo)在上方、鼠標(biāo)按下、被禁用。這4態(tài)對(duì)應(yīng)4個(gè)圖標(biāo)。由于時(shí)間關(guān)系,只對(duì)需要注意的地方簡(jiǎn)單介紹。具體見(jiàn)完整代碼。
          無(wú)疑,4種狀態(tài)切換要添加鼠標(biāo)事件監(jiān)聽(tīng)器。關(guān)閉按鈕通過(guò)聲明private Composite closeButton;來(lái)實(shí)現(xiàn)。具體位置本程序?qū)崿F(xiàn)是右端與northeastPanel相鄰,左邊與northPanel相鄰。在鼠標(biāo)抬起時(shí),要檢查抬起點(diǎn)是否在該按鈕上,如果是才執(zhí)行關(guān)閉操作。見(jiàn)如下代碼
          if (e.x > 0 && e.x < closeButton.getSize().x && e.y > 0
               && e.y < closeButton.getSize().y){
          // 執(zhí)行關(guān)閉操作,否則鼠標(biāo)在關(guān)閉按鈕上方按下,但是不在其上松開(kāi),表明用戶放棄關(guān)閉行為。
          }
          重寫(xiě)dispose方法如下:
          @Override
           public void dispose() {
            try {
             northwestImage.dispose();
             northeastImage.dispose();
             northImage.dispose();
             southwestImage.dispose();
             southeastImage.dispose();
             southImage.dispose();
             westImage.dispose();
             eastImage.dispose();
             closeImage.dispose();
             closeOverImage.dispose();
             color1.dispose();
             color2.dispose();
             titleColor.dispose();
            } finally {
             super.dispose();
            }
           }
          首先是釋放所有SWT本地資源,然后是super.dispose();釋放窗口資源。

          運(yùn)行程序,界面效果如下


          至此,打造專業(yè)外觀-窗口部分的講述就結(jié)束了,在這3篇幅中,主要講述了九宮格的概念,九宮格法俗話說(shuō)就是“貼圖”,這個(gè)手法最常用也是最基礎(chǔ)的,你會(huì)發(fā)現(xiàn)界面美觀與否與圖片有很大關(guān)系,同時(shí)桌面編程人員需要頻繁與美工交互才能達(dá)到理想效果,如果沒(méi)有合格的美工,但憑技術(shù)很難實(shí)現(xiàn)漂亮的外觀,不過(guò)確實(shí)也存在只用多邊形與曲線繪制組件的高手,swing的L&F就是這么實(shí)現(xiàn)的,但是貼圖的好處是只要圖片替換,外觀也跟著替換,不用更改代碼。

          本程序只作為您設(shè)計(jì)的參考,欠缺還很多,并且沒(méi)有對(duì)代碼的健壯性、異常情況過(guò)多考慮,由于swt資源必須手工釋放,如dispose方法中那樣,其實(shí)那是最基本的,在實(shí)際環(huán)境下這么做還很有限,而且nullPoint異常也沒(méi)有過(guò)多考慮。這都需要你自己去實(shí)現(xiàn)。

          最終的完整程序這里下載

          posted on 2007-11-07 00:49 sun_java_studio@yahoo.com.cn(電玩) 閱讀(6459) 評(píng)論(6)  編輯  收藏 所屬分類(lèi): NetBeans 、GUI Design

          評(píng)論

          # re: 打造專業(yè)外觀-三[未登錄](méi) 2007-11-07 13:14 Thinker

          受用  回復(fù)  更多評(píng)論   

          # re: 打造專業(yè)外觀-三 2007-11-07 19:06 William Chen

          Hi 電玩,
          文章寫(xiě)的不錯(cuò),項(xiàng)目也做的非常漂亮。SWT都被你做成這個(gè)樣子,佩服。
          我對(duì)SWT并不太熟,稍有了解。其實(shí)對(duì)于swing,我也只是個(gè)人偏愛(ài),至于SWT總有它適合的地方。我的文章的目的主要是糾正人們對(duì)于Swing的誤解,希望人們不要對(duì)SWT過(guò)于迷信。所謂糾往必須過(guò)正嘛。
          實(shí)際上沒(méi)有正確與錯(cuò)誤的技術(shù),只有合適不合適的技術(shù)。
          以前覺(jué)得國(guó)內(nèi)都在搞Server Side Java,難得在這兒看到有這么多人對(duì)Java GUI感興趣,而且技術(shù)都相當(dāng)不錯(cuò)啊。
          最近Java應(yīng)用桌面開(kāi)發(fā)逐漸升溫,加上Sun對(duì)于桌面Java態(tài)度的改變,Java的開(kāi)源,這些都必將促進(jìn)Java桌面技術(shù)的復(fù)興。
          Java桌面技術(shù)前途還是比較光明的。  回復(fù)  更多評(píng)論   

          # re: 打造專業(yè)外觀-三[未登錄](méi) 2007-12-12 16:16 xiaoxiao

          高手們,能不能加上最小化和最大化按鈕。初學(xué)者  回復(fù)  更多評(píng)論   

          # 打造專業(yè)外觀-三 2008-05-22 15:51 swt

          謝謝啊,收下了??!  回復(fù)  更多評(píng)論   

          # re: 打造專業(yè)外觀-三 2008-05-24 14:12 一嘯長(zhǎng)天

          是啊....轉(zhuǎn)做WEB也是一種無(wú)柰之舉啊!  回復(fù)  更多評(píng)論   

          # re: 打造專業(yè)外觀-三 2008-05-24 15:19 sun_java_studio@yahoo.com.cn(電玩)

          @一嘯長(zhǎng)天
          Web是大趨勢(shì),但是不一定就是HTML,RIA的興起將會(huì)帶來(lái)一場(chǎng)革命,F(xiàn)lex、JavaFX和桌面程序開(kāi)發(fā)很像。  回復(fù)  更多評(píng)論   

          TWaver中文社區(qū)
          主站蜘蛛池模板: 泸水县| 禹州市| 泸西县| 新郑市| 夏津县| 读书| 齐河县| 华池县| 农安县| 宜章县| 兴文县| 景泰县| 唐山市| 关岭| 秀山| 沙湾县| 平泉县| 阿勒泰市| 泽州县| 永清县| 策勒县| 和平县| 利辛县| 会宁县| 泸州市| 安图县| 合水县| 佳木斯市| 来安县| 洛川县| 光山县| 石河子市| 庐江县| 祥云县| 饶阳县| 扬中市| 驻马店市| 名山县| 班玛县| 昌黎县| 巴马|