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

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

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

    TWaver - 專注UI技術

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

    用Swing定制流動的Link樣式

    Posted on 2012-07-27 16:52 TWaver 閱讀(1280) 評論(1)  編輯  收藏
    想想Java2D中給我們提供的線的樣式著實很少,除了直線,虛線,好像就沒有其他的什么樣式了,如果細心的童鞋還會發現,TWaver中倒是提供了一種比較特殊的連線,波浪曲折式的連線。

    這種波浪曲折的連線如果讓我們自己來實現也是有多種實現的方式,還記得之前幾篇文章中定制過的LinkUI么,也是各式各樣的方式,比如:

    五彩斑斕的Link



    流動點式的Link


    今天給大家介紹的是箭頭流動式的Link,何為箭頭流動,我們就先來看看效果圖:

    這是一個從from節點流向to節點的連線,連線是以一個一個箭頭組建而成,這樣的連線方式看上去比傳統的那種流動漂亮多了,也有不少客戶提及到這種樣式。本篇我將詳細給大家講解一下實現的細節。

    首先需要定制一個ArrowLink繼承于Link,在ArrowLink中需要給它定義幾個變量,例如:線的寬度、顏色、每段箭頭的長度、需要填充的流動箭頭的數量、透明度、是否是從from流向to以及偏移(用于顯示流動)等等。 不說這么多了,直接看代碼:

     1 public class ArrowLink extends Link {
     2 
     3     public ArrowLink() {
     4         super();
     5         init();
     6     }
     7 
     8     public ArrowLink(Object id) {
     9         super(id);
    10         init();
    11     }
    12 
    13     public ArrowLink(Node from, Node to) {
    14         super(from, to);
    15         init();
    16     }
    17 
    18     public ArrowLink(Object id, Node from, Node to) {
    19         super(id, from, to);
    20         init();
    21     }
    22 
    23     private void init() {
    24         this.putLinkColor(new Color(0, 0, 0, 0));
    25         this.putLinkOutlineWidth(0);
    26         this.setLinkType(TWaverConst.LINK_TYPE_PARALLEL);
    27         this.putLinkAntialias(true);
    28         this.putClientProperty("lineWidth", 3.0f);
    29         this.putClientProperty("lineColor", Color.blue);
    30         this.putClientProperty("offset", 0.0);
    31         this.putClientProperty("segmentLength", 8.0);
    32         this.putClientProperty("fillSegmentCount", 5);
    33         this.putClientProperty("defaultAlpha", 0.2);
    34         this.putClientProperty("from", true);
    35     }
    36 
    37     public String getUIClassID() {
    38            return ArrowLinkUI.class.getName();
    39         }
    40 
    41 }

    定制完連線之后,最主要的是需要重畫LinkUI,自定義ArrowLinkUI類繼承于LinkUI并重載paintBody方法,paintBody中我們需要畫出一個一個的箭頭,箭頭實現起來其實還是比較簡單的,我們能獲取Link的長度并且知道Link上每段的長度,就可以計算出需要繪制箭頭的數量。

    1 int count = (int)(length/segmentLength);

    根據箭頭的數量可以獲取到需要繪制箭頭的每個點的位置:

    1 List points = TWaverUtil.divideShape(this.path, count);

    獲取到這個位置之后,我們就可以以這個點為中心點,分別計算出箭頭的其他兩個點的位置:

    1 Point2D p0 = new Point.Double();
    2 transform.transform(point, p0);
    3 Point2D p1 =  new Point.Double();
    4 transform.transform(new Point.Double(point.getX() + segmentLength/2 * sign, point.getY() - segmentLength/2), p1);
    5 Point2D p2 =  new Point.Double();
    6 transform.transform(new Point.Double(point.getX() + segmentLength/2 * sign, point.getY() + segmentLength/2), p2);

    這樣一個箭頭就可以繪制出來了

    其他的箭頭也可以以同樣方式循環繪制出來,需要注意的是箭頭是需要隨著node的位置旋轉的,因此我們需要計算出箭頭旋轉的角度和旋轉點的位置:

    1 AffineTransform transform = new AffineTransform();
    2 transform.translate(point.getX(), point.getY());
    3 transform.rotate(angle);
    4 transform.translate(-point.getX(), -point.getY());

    最后還有流動的效果,這里我們設置了一個offset的參數,可以表示流動的偏移量,根據偏移量以及填充的流動箭頭的數量來確定當前這個箭頭的透明度:

    1 double alpha = (Double)this.element.getClientProperty("defaultAlpha");
    2 if(offset * count >= i && offset * count - fillSegmentCount <= i){
    3     alpha = 1 - (offset * count - i)/fillSegmentCount * 0.5;
    4 }

    完整繪制箭頭的代碼如下:

     1 public class ArrowLinkUI extends LinkUI {
     2 
     3     public ArrowLinkUI(TNetwork network, Link link) {
     4         super(network, link);
     5     }
     6 
     7     public void paintBody(Graphics2D g2d) {
     8         super.paintBody(g2d);
     9         this.drawFlowing(g2d);
    10     }
    11 
    12     private void drawFlowing(Graphics2D g2d) {
    13         double length = TWaverUtil.getLength(this.path);
    14         if(length < =0 ){
    15             return;
    16         }
    17 
    18         double segmentLength = (Double)this.element.getClientProperty("segmentLength");
    19         int count = (int)(length/segmentLength);
    20         List points = TWaverUtil.divideShape(this.path, count);
    21         if(points.size() < 2){
    22             return;
    23         }
    24         int fillSegmentCount = (Integer)this.element.getClientProperty("fillSegmentCount");
    25         double offset = (Double)this.element.getClientProperty("offset");
    26         Color lineColor = (Color)this.element.getClientProperty("lineColor");
    27         boolean from = (Boolean)this.element.getClientProperty("from");
    28         boolean fromLeft = this.getFromPoint().x <= this.getToPoint().x;
    29 
    30         g2d.setStroke(new BasicStroke((Float)this.element.getClientProperty("lineWidth")));
    31         for(int i=0; i
    32             Point2D point = (Point2D)points.get(i);
    33             Point2D point1, point2;
    34             double angle = 0;
    35             if(i == points.size()-1){
    36                 point1 = (Point2D)points.get(i-1);
    37                 point2 = point;
    38             } else {
    39                 point1 = point;
    40                 point2 = (Point2D)points.get(i+1);
    41             }
    42             angle = getAngle(point1, point2);
    43             int sign = (fromLeft && from || !fromLeft && !from) ? -1 : 1;
    44             if(angle == -Math.PI/2){
    45                 sign = point2.getY() > point1.getY() ? 1 : -1;
    46             }else if(angle == Math.PI/2){
    47                 sign = point2.getY() > point1.getY() ? -1 : 1;
    48             }
    49             double alpha = (Double)this.element.getClientProperty("defaultAlpha");
    50             if(offset * count >= i && offset * count - fillSegmentCount < = i){
    51                 alpha = 1 - (offset * count - i)/fillSegmentCount * 0.5;
    52             }
    53             g2d.setColor(new Color(lineColor.getRed(), lineColor.getGreen(), lineColor.getBlue(), (int)(255 * alpha)));
    54 
    55             AffineTransform transform = new AffineTransform();
    56             transform.translate(point.getX(), point.getY());
    57             transform.rotate(angle);
    58             transform.translate(-point.getX(), -point.getY());
    59 
    60             Point2D p0 = new Point.Double();
    61             transform.transform(point, p0);
    62             Point2D p1 =  new Point.Double();
    63             transform.transform(new Point.Double(point.getX() + segmentLength/2 * sign, point.getY() - segmentLength/2), p1);
    64             Point2D p2 =  new Point.Double();
    65             transform.transform(new Point.Double(point.getX() + segmentLength/2 * sign, point.getY() + segmentLength/2), p2);
    66             GeneralPath path = new GeneralPath();
    67             path.moveTo(p1.getX(), p1.getY());
    68             path.lineTo(p0.getX(), p0.getY());
    69             path.lineTo(p2.getX(), p2.getY());
    70             g2d.draw(path);
    71         }
    72     }
    73 
    74     private static double getAngle(Point2D p1, Point2D p2) {
    75         if(p1.getX() == p2.getX()){
    76             if(p2.getY() == p1.getY()){
    77                 return 0;
    78             }
    79             else if(p2.getY() > p1.getY()){
    80                 return Math.PI/2;
    81             }
    82             else{
    83                 return -Math.PI/2;
    84             }
    85         }
    86         return Math.atan((p2.getY() - p1.getY()) / (p2.getX() - p1.getX()));
    87     }
    88 }

    有了這種流動式的箭頭,我們就可以繪制出更多豐富多彩的界面,最后給出一個完整的例子供大伙學習參考:
    注:附件中還給出了另一種Link的實現效果。 見原文最下方

    評論

    # re: 用Swing定制流動的Link樣式[未登錄]  回復  更多評論   

    2015-05-28 22:16 by Neo
    如何設置Link的寬度呢?我的這個Link是連接兩個Group的。

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


    網站導航:
     
    主站蜘蛛池模板: 久久水蜜桃亚洲AV无码精品| 182tv免费视频在线观看| 亚洲成A∨人片天堂网无码| 曰批全过程免费视频在线观看无码| 亚洲成年人在线观看| 在线免费视频一区| 青柠影视在线观看免费高清 | 国产亚洲精品免费| 久久综合图区亚洲综合图区| 成年人免费网站在线观看| 亚洲五月午夜免费在线视频| 亚洲天堂一区二区三区| 亚洲国产日韩成人综合天堂| 我的小后妈韩剧在线看免费高清版 | 久久久精品午夜免费不卡| 亚洲日韩久久综合中文字幕| 国产成人麻豆亚洲综合无码精品 | 日韩免费福利视频| 午夜免费福利片观看| 成a人片亚洲日本久久| 亚洲欧洲日产韩国在线| 久久影院亚洲一区| 青苹果乐园免费高清在线| 在线观看黄片免费入口不卡| 亚洲国产欧洲综合997久久| 亚洲日本在线看片| 亚洲日本中文字幕一区二区三区 | 免费国内精品久久久久影院| 91制片厂制作传媒免费版樱花| 黄色a三级免费看| 国产v亚洲v天堂a无| 亚洲国产精品自在线一区二区 | mm1313亚洲精品无码又大又粗| 亚洲一区免费视频| 久久久久久AV无码免费网站| 特级毛片爽www免费版| 亚洲国产午夜精品理论片在线播放 | 亚洲中文字幕在线乱码| 哒哒哒免费视频观看在线www | 国产亚洲精品拍拍拍拍拍| 国产一级高清视频免费看|