TWaver - 專注UI技術(shù)

          http://twaver.servasoft.com/
          posts - 171, comments - 191, trackbacks - 0, articles - 2
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          UI定制總結(jié)

          Posted on 2012-08-01 09:52 TWaver 閱讀(959) 評論(0)  編輯  收藏
          TWaver本身提供的豐富的設(shè)置選項,可以幫助我們快速實(shí)現(xiàn)各種絢麗的效果,但是在某些情況下,我們需要在網(wǎng)元上繪制一些圖形來表示某種狀態(tài)或業(yè)務(wù)信息,沒問題,只需要一點(diǎn)點(diǎn)2D知識可以很容易實(shí)現(xiàn)這樣的需求。
          假設(shè)一種需求(僅僅是假設(shè)):監(jiān)控交換機(jī)各個端口的傳輸速度,并用柱狀圖動態(tài)顯示。效果圖如下:
          大家可能奇怪,怎么放了三個一樣的網(wǎng)元呢?答案是:我使用了三種方式來實(shí)現(xiàn)這個效果!可能還有別的方式可以實(shí)現(xiàn),所謂條條大路通羅馬是也!這也是TWaver的強(qiáng)大之處, 為我們留下了一扇門,門后就是神奇的"納尼亞王國",本文的目的就是把這扇門的鑰匙交給你。

          我們從最簡單的說起,TWaver提供了BarChart表示柱狀圖,我們可以把BarChart通過ComponentAttachment掛到Node上,這是最簡單的方式,之所以說它簡單,因?yàn)槲覀儾恍枰褂?D繪制( 其實(shí)2D也不難),僅僅需要監(jiān)聽Node的屬性變化然后更新BarChart即可。

          ComponentAttachment上允許添加任何JComponent組件(JPanel,JButton,JLabel,JCheckbox,etc.),BarChart是JComponent的子類,自然也可以被添加。ComponentAttachment是個抽象類,需要定制一個PortRateAttachment繼承ComponentAttachment

          注冊Attachment
          1 TUIManager.registerAttachment("PortRateAttachment",PortRateAttachment.class);

          1 node1.addAttachment("PortRateAttachment");
          2 node1.putAttachmentPosition(TWaverConst.POSITION_RIGHT);
          3 node1.putAttachmentXOffset(-20);

           1 public class PortRateAttachment extends ComponentAttachment {
           2     Node p1=new Node();
           3     Node p2=new Node();
           4     Node p3=new Node();
           5     private BarChart barChart=new BarChart();
           6     public PortRateAttachment(String name, ElementUI ui) {
           7         super(name, ui);
           8         TDataBox box=new TDataBox();
           9         barChart.setDataBox(box);
          10         barChart.setShadowOffset(0);//取消陰影
          11         barChart.setUpperLimit(100);//刻度最大值
          12         barChart.setLowerLimit(0);//刻度最小值
          13         barChart.setYScaleLineVisible(false);//Y軸刻度線不可見
          14         barChart.setXAxisVisible(false);//X軸不可見
          15         barChart.setYAxisVisible(false);//Y軸不可見
          16         barChart.setBundleSize(3);//將三個Node放在一塊顯示
          17         barChart.setOpaque(false);//背景透明
          18         barChart.setXGap(0);//X軸Margin為0
          19         barChart.setYGap(0);//Y軸Margin為0
          20         barChart.setValueTextVisible(false);//ChartValue不可見
          21         barChart.getLegendPane().setVisible(false);//隱藏LegendPane
          22 
          23         //初始化三個Node
          24         p1.putChartValue(0);
          25         p1.putChartColor(PortRateConst.COLORS[0]);
          26         box.addElement(p1);
          27 
          28         p2.putChartValue(0);
          29         p2.putChartColor(PortRateConst.COLORS[1]);
          30         box.addElement(p2);
          31 
          32         p3.putChartValue(0);
          33         p3.putChartColor(PortRateConst.COLORS[2]);
          34         box.addElement(p3);
          35 
          36         this.setComponent(barChart);//將BarChart掛載在Attachment上
          37         this.setBorderVisible(true);//顯示Border
          38         this.setBorderColor(Color.gray);//Border顏色
          39         this.setSize(new Dimension(50,50));//設(shè)置Attachment大小
          40         this.setPosition(this.element.getAttachmentPosition());//設(shè)置Attachment的位置,提前存入Node的ClientProperty
          41         this.setXOffset(this.element.getAttachmentXOffset());//設(shè)置Attachment的X軸偏移量,提前存入Node的ClientProperty
          42     }
          43 
          44     /*
          45      * 監(jiān)控Node Property變化并更新到BarChart上
          46      * @see twaver.network.ui.ComponentAttachment#elementPropertyChange(java.beans.PropertyChangeEvent)
          47      */
          48     @Override
          49     public void elementPropertyChange(PropertyChangeEvent evt) {
          50         super.elementPropertyChange(evt);
          51         if(evt.getNewValue()!=null){
          52             if("UP:p1".equals(evt.getPropertyName())){
          53                 p1.putChartValue(Double.parseDouble(evt.getNewValue().toString().substring(3))*100);
          54             }else if("UP:p2".equals(evt.getPropertyName())){
          55                 p2.putChartValue(Double.parseDouble(evt.getNewValue().toString().substring(3))*100);
          56             }else if("UP:p3".equals(evt.getPropertyName())){
          57                 p3.putChartValue(Double.parseDouble(evt.getNewValue().toString().substring(3))*100);
          58             }
          59         }
          60 
          61     }
          62 }

          在Attachment中添加一個BarChart,并用三個Node表示chart的三個組,在elementPropertyChange中監(jiān)控Node屬性變化并同步更新到這三個Node上即可。
          所有的代碼已經(jīng)加上注釋,就不過多解釋了。
          TWaver還提供了一種IconAttachment,允許我們將一個Icon作為附件掛載在Node上,我們可以在Icon上畫任何內(nèi)容,所以這也是一種思路(參考了TWaver官方demo,InstrumentDemo,為避免版權(quán)糾紛,特此說明 :-D )。我們定制一個PortRateIconAttachment從IconComponentAttachment繼承。

           1 public class PortRateIconAttachment extends IconAttachment {
           2     public final static double WIDTH = 40;
           3     public final static double HEIGHT = 50;
           4 
           5     public PortRateIconAttachment(String name, ElementUI elementUI) {
           6         super(name, elementUI,new PortRateIcon(elementUI.getElement()));
           7     }
           8 
           9 }
          10 class PortRateIcon implements javax.swing.Icon{
          11     private Element element;
          12     public PortRateIcon(Element element){
          13         this.element=element;
          14     }
          15     @Override
          16     public void paintIcon(Component c, Graphics g, int x, int y) {
          17         Graphics2D g2d = (Graphics2D)g;
          18         //計算出柱狀圖中組數(shù)和組寬
          19         final int count = PortRateConst.KEYS.length;
          20         final double width = PortRateIconAttachment.WIDTH / count;
          21         //計算坐標(biāo)和尺寸,繪制三個矩形代表三個組
          22         for(int i=0; i<count; i++){
          23             double proportion=0;
          24             if(element.getUserProperty(PortRateConst.KEYS[i])!=null)
          25                 proportion =Double.parseDouble(element.getUserProperty(PortRateConst.KEYS[i]).toString().substring(3));
          26             g2d.setColor(PortRateConst.COLORS[i]);
          27             g2d.fillRect((int)(x + i * width),
          28                     (int)(y + PortRateIconAttachment.HEIGHT * (1- proportion)),
          29                     (int)width,(int)(PortRateIconAttachment.HEIGHT * proportion));
          30         }
          31         //繪制邊框
          32         g2d.setColor(Color.GRAY);
          33         g2d.setStroke(TWaverConst.BASIC_STROKE);
          34         g2d.drawRect(x, y-1, (int)PortRateIconAttachment.WIDTH, (int)PortRateIconAttachment.HEIGHT);
          35     }
          36 
          37     @Override
          38     public int getIconWidth() {
          39         return (int) PortRateIconAttachment.WIDTH;
          40     }
          41 
          42     @Override
          43     public int getIconHeight() {
          44         return (int) PortRateIconAttachment.HEIGHT;
          45     }
          46 
          47 }

          在PortRateIconAttachment中沒有任何繪制,僅僅與一個PortRateIcon綁定,繪制工作交給PortRateIcon執(zhí)行,每當(dāng)PortRateIconAttachment監(jiān)聽到Node屬性變化時就會重繪Icon

          在paintIcon方法中,我們最終繪制出了我們需要的動態(tài)柱狀圖。

          除了Attachment,重寫NodeUI也是一個不錯的選擇。看我們的第三種方法

          我們寫了一個SwitchNode繼承自Node,重寫getUIClassID方法,實(shí)際上就是為此Node指定了UI類

          PortNodeUI 
           1 public class PortNodeUI extends NodeUI {
           2     private Rectangle2D rect=null;
           3     public PortNodeUI(TNetwork network, Node node) {
           4         super(network, node);
           5     }
           6     @Override
           7     public void paintBody(Graphics2D g2d){
           8         super.paintBody(g2d);
           9         final int count = PortRateConst.KEYS.length;
          10         //計算出柱狀圖中組數(shù)和組寬
          11         final double width = 40 / count;
          12         double x=element.getX()+element.getWidth()-20;
          13         double y=element.getY()+20;
          14         //繪制組
          15         for(int i=0; i<count; i++){
          16             double proportion=0;
          17             if(element.getUserProperty(PortRateConst.KEYS[i])!=null)
          18                 proportion =Double.parseDouble(element.getUserProperty(PortRateConst.KEYS[i]).toString().substring(3));
          19             g2d.setColor(PortRateConst.COLORS[i]);
          20             g2d.fillRect((int)(x + i * width),
          21                         (int)(y + 50 * (1- proportion)),
          22                         (int)width, (int)(PortRateIconAttachment.HEIGHT * proportion));
          23         }
          24         //繪制邊框
          25         g2d.setColor(Color.GRAY);
          26         g2d.setStroke(TWaverConst.BASIC_STROKE);
          27         g2d.drawRect((int)x, (int)y, (int)PortRateIconAttachment.WIDTH, (int)PortRateIconAttachment.HEIGHT);
          28     }
          29 }

          注意paintBody方法,幾乎跟前面的paintIcon是一致的。
          注意右側(cè)的PropertySheet,我們也為其實(shí)現(xiàn)了一個Renderer繪制進(jìn)度條,實(shí)際上,通過Renderer,我們可以在PropertySheet繪制任何圖形或組件。
          通過 ElementAttribute指定Renderer

          1 ElementAttribute&nbsp;att=new&nbsp;ElementAttribute();
          2 att.setRendererClass(PortRateRenderer.class.getName());

          Renderer類

           1 public class PortRateRenderer extends JComponent implements TableCellRenderer {
           2     private Color foreColor;
           3     private double proportion;
           4     @Override
           5     public Component getTableCellRendererComponent(JTable table, Object value,
           6             boolean isSelected, boolean hasFocus, int row, int column) {
           7         if(value!=null){
           8             String strValue=(String)value;
           9             for(int i=0; i<PortRateConst.KEYS.length; i++){
          10                 String key = PortRateConst.KEYS[i];
          11                 if(strValue.startsWith(key)){
          12                     proportion = Double.parseDouble(strValue.substring(key.length() + 1));
          13                     foreColor = PortRateConst.COLORS[i];
          14                 }
          15             }
          16         }
          17         return this;
          18     }
          19     public void paintComponent(Graphics g){
          20         Graphics2D g2d=(Graphics2D)g;
          21         g2d.setColor(new Color(127,92,128));
          22         g2d.drawRect(1, 1, this.getWidth()-2, this.getHeight()-2);
          23         g2d.setColor(new Color(240,240,240));
          24         g2d.fillRect(2, 2, this.getWidth()-3, this.getHeight()-3);
          25         g2d.setColor(foreColor);
          26         g2d.fillRect(2, 2, (int)(this.getWidth() * proportion), this.getHeight()-3);
          27     }
          28 
          29 }

          在getTableCellRendererComponent中,我們根據(jù)傳進(jìn)Renderer的Value,設(shè)置進(jìn)度條的值和前景色,在paintComponent中就可以使用了。在paintComponent里,首先畫一個矩形當(dāng)作進(jìn)度條背景,然后覆蓋一個矩形當(dāng)作進(jìn)度,繪制好邊框以后一個進(jìn)度條就完成了!
          最近論壇上有人提出要實(shí)現(xiàn)帶圓角Title的Group,貼子地址:http://twaver.servasoft.com/forum/viewtopic.php?f=4&t=3091。 帖子里的實(shí)現(xiàn)過程是這樣的:Group的Label其實(shí)是一個LabelAttachment,為Group重新定制了一個LabelAttachment,在LabelAttachment繪制出圓角效果,然后將Group的LabelPosition設(shè)置為左上角即可。

          圓角繪制的原理是將一個圓角矩形和普通矩形通過Area組合,然后用漸變色填充,具體的代碼大家可以去帖子里下載。

          這個專題終于可以告一段落了,熟悉TWaver架構(gòu)以后,再加上一些2d知識,我們可以發(fā)揮自己的想象力繪制各種令人驚嘆的效果。希望本文能起到拋磚引玉的作用。最后附上文中demo的源代碼見原文最下方

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 井陉县| 土默特左旗| 义马市| 西安市| 玉门市| 宁武县| 拉萨市| 洪洞县| 射阳县| 诸暨市| 大丰市| 平顶山市| 察雅县| 云浮市| 威远县| 德安县| 常宁市| 沭阳县| 石景山区| 房产| 兴宁市| 大洼县| 临泽县| 深圳市| 本溪市| 藁城市| 永丰县| 高陵县| 怀远县| 黄浦区| 射洪县| 澜沧| 安仁县| 新平| 河曲县| 绥化市| 新巴尔虎右旗| 吉木萨尔县| 辽宁省| 枣强县| 灌阳县|