TWaver - 专注UI技术

http://twaver.servasoft.com/
posts - 171, comments - 191, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

 linkUML图大家都看过,可能大家也比较熟悉,有时候也希望能通过UML图形的方式展示一些网管业务逻辑,比如以下逻辑

下面通过一系列的功能点讲解,教大家如何使用TWaver实现UML效果,最终效果图如下

Step1, 如何实现UML图形的节点,效果如下:

功能点介绍
Step1.1 如何实现文字换行居中
TWaver中网元的Label默认就已经提供了对于html的支持,所以可以通过如下代码实现文字换行居中效果

1node.putLabelPosition(TWaverConst.POSITION_CENTER);
2node.setDisplayName("<html><center>网络资源<br>(Resource)</center></html>");

Step1.2 如何让网元显示成UML流程节点形状
这个主要有两个功能点
a:平时开发过程中,一般的网元都显示成图标的形式以代表业务逻辑,其实TWaver默认提供了一组CustomDraw的图形,可以将网元显示成不同的形状,如下图所示:

通过设置CustomDraw的属性就可以达到矩形的效果
Step1.3 如何在节点下面绘制几条分割线,这个功能很好的体现了TWaver中MVC的架构,对Swing熟悉一些的开发人员都知道,像JButton,JTextField等Swing组件都会有一些对应的UI类,比如ButtonUI,TextFieldUI进行绘制,开发人员可以很方便的通过LookAndFeel切换UI进行换肤操作。TWaver中网元渲染原理类似,像Node,Link都有对应的UI,NodeUI、LinkUI进行渲染,通过很方便的重载这些UI实现效果定制,比如TWaveDemo中的Custom Link Demo和Instrument Demo,如下图所示

UMLNode的实现也类似,首先定义了一个UMLNode类,在里面设置了一些列的CustomDraw属性(参考Step1.2),然后继承ResizableNodeUI实现了一个UMLNodeUI,在里面绘制了几条分割线,代码如下

 1public class UmlNode extends ResizableNode {
 2
 3    public UmlNode() {
 4        super();
 5        initNode();
 6    }

 7
 8    public UmlNode(Object id) {
 9        super(id);
10        initNode();
11    }

12
13    private void initNode() {
14        this.putCustomDraw(true);
15        this.putCustomDrawGradient(true);
16        this.putCustomDrawGradientFactory(TWaverConst.GRADIENT_LINE_N);
17        this.putCustomDrawFillColor(new Color(255200100150));
18        this.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE);
19        this.putCustomDrawOutlineColor(new Color(2000200));
20
21        this.putLabelPosition(TWaverConst.POSITION_CENTER);
22        this.putLabelFont(TUIManager.getDefaultPlainFont());
23        this.setSize(22060);
24    }

25
26    //重载UI
27    public String getUIClassID() {
28        return UmlNodeUI.class.getName();
29    }

30
31}

32
33public class UmlNodeUI extends ResizableNodeUI {
34
35    public UmlNodeUI(TNetwork network, ResizableNode node) {
36        super(network, node);
37    }

38
39    //想怎么画就怎么画
40    protected void paintCustomDraw(Graphics2D g2d) {
41        super.paintCustomDraw(g2d);
42        Rectangle bounds = this.getUIBounds();
43
44        g2d.drawLine(bounds.x+2, bounds.y+bounds.height-6, bounds.x+bounds.width-2, bounds.y+bounds.height-6);
45        g2d.drawLine(bounds.x+2, bounds.y+bounds.height-12, bounds.x+bounds.width-2, bounds.y+bounds.height-12);
46    }

47}

通过以上处理,就可以达到UML节点的效果了

Step2,如何实现UML的折线子环效果
TWaver中的Link默认有自环环效果,效果如下

但这个显然不是我们想要的,因为它默认只有圆形效果,这个时候我们就想到了另外一种Link,ShapeLink,顾名思义,这个Link是由一个Shape形状来表示的,那么我们能不能通过ShapeLink来实现折线子环的效果呢,答案是肯定的,只需要小小的定制即可,代码如下

 1public class LoopLink extends ShapeLink {
 2
 3    public LoopLink(Node node) {
 4        super();
 5        initLink();
 6    }

 7
 8    public LoopLink(Object id, Node node) {
 9        super(id);
10        this.setFrom(node);
11        this.setTo(node);
12        initLink();
13    }

14
15    private double wExtend = 0.5;
16    private double hExtend = 0.5;
17
18    private void initLink() {
19        this.putLinkFromPosition(TWaverConst.POSITION_RIGHT);
20        this.putLinkToPosition(TWaverConst.POSITION_BOTTOM);
21        this.setLinkType(TWaverConst.LINK_TYPE_YSPLIT);
22        this.putLinkOutlineWidth(0);
23        this.putLinkWidth(1);
24        this.putRenderColor(Color.BLUE);
25        this.putLinkToArrow(true);
26        this.putLinkToArrowStyle(TWaverConst.ARROW_DELTA_GREAT);
27        this.putLinkToArrowOutlineColor(Color.RED);
28        this.putLinkToArrowColor(Color.WHITE);
29
30        Node node = this.getFrom();
31               //注意此处,因为默认ShapeLink上的点是不会跟随Node移动的,所以为了实现跟随效果,这里通过监听Node的属性变化进行了更新处理
32        node.addPropertyChangeListener(new PropertyChangeListener() {
33            public void propertyChange(PropertyChangeEvent evt) {
34                if (TWaverConst.PROPERTYNAME_LOCATION.equals(evt.getPropertyName())) {
35                    validatePoints();
36                }

37            }

38        }
);
39        validatePoints();
40    }

41
42    private void validatePoints() {
43        this.clear();
44        Node node = this.getFrom();
45        Rectangle bounds = node.getBounds();
46        Point2D p1 = new Point2D.Double(bounds.getCenterX() + bounds.getWidth() / 2, bounds.getCenterY());
47        this.addPoint(p1);
48        Point2D p2 = new Point2D.Double(bounds.getCenterX() + bounds.getWidth() / 2 + bounds.getWidth() * wExtend, bounds.getCenterY());
49        this.addPoint(p2);
50        Point2D p3 = new Point2D.Double(bounds.getCenterX() + bounds.getWidth() / 2 + bounds.getWidth() * wExtend, bounds.getCenterY() + bounds.getHeight() / 2
51                + bounds.getHeight() * hExtend);
52        this.addPoint(p3);
53        Point2D p4 = new Point2D.Double(bounds.getCenterX(), bounds.getCenterY() + bounds.getHeight() / 2 + bounds.getHeight() * hExtend);
54        this.addPoint(p4);
55    }

56
57}

通过这样就可以达到折线自环的效果了,效果图如下

Step3 如何实现Link折线效果和From/To端文字标注
Step 3.1 如何实现Link折线效果,其实这个很简单,不过可能大多数人都会忽略TWaver默认提供的这个功能,通过设置不同的LinkType,Link可以显示成各种样式,如下图所示

通过如下代码即可达到UML图中的连线效果

 1private void initLink() {
 2        this.setLinkType(TWaverConst.LINK_TYPE_YSPLIT);
 3        this.putLinkOutlineWidth(0);
 4        this.putLinkWidth(1);
 5        this.putRenderColor(Color.BLUE);
 6        this.putLinkToArrow(true);
 7        this.putLinkToArrowStyle(TWaverConst.ARROW_DELTA_GREAT);
 8        this.putLinkToArrowOutlineColor(Color.RED);
 9        this.putLinkToArrowColor(Color.WHITE);
10    }

Step3.2 如何在Link的From/To端进行标注
效果如下

实现原理:这个借助了TWaver中Attachment的概念,顾名思义,Attachment即附件,它的主要功能就是附加一些信息到网元上,Attachment有很多种,简单点的可以显示一串文字,复杂点的可以显示一些组件在界面上,想TWaverDemo的AttachmentDemo,如下图所示

文字标注也可以通过这种方式进行处理,TWaver内部对于Link的From和To两个位置都有对应的定义

1TWaverConst.POSITION_LINK_FROM_ANCHOR
2TWaverConst.POSITION_LINK_TO_ANCHOR
既然有了这个实现起来就很简单了,我们只需要自定义一个Label的Attachment,然后将其放到From或To的Postion既可以了,见如下代码
 1public class LinkLabelAttachment extends ComponentAttachment {
 2
 3    public final static String LINKFROMLABEL = "linklabelattachment.linkfromlabel";
 4
 5    public LinkLabelAttachment(String name, ElementUI ui) {
 6        super(name, ui);
 7        initLabel();
 8    }

 9
10    public LinkLabelAttachment(String name, ElementUI ui, boolean minimized, boolean shrinked) {
11        super(name, ui, minimized, shrinked);
12        initLabel();
13    }

14
15    private JLabel label = new JLabel() {
16        {
17            this.setHorizontalAlignment(SwingConstants.CENTER);
18            this.setDoubleBuffered(false);
19        }

20    }
;
21
22    private void initLabel() {
23        label.setFont(LinkLabelDemo.USECUSTOMERFONT);
24        label.setForeground(LinkLabelDemo.LABELCOLOR);
25
26        setLabelText();
27        this.setPosition(TWaverConst.POSITION_LINK_FROM_ANCHOR);
28        this.setComponent(label);
29    }

30
31    private void setLabelText() {
32        Object obj = element.getClientProperty(LINKFROMLABEL);
33        if (obj != null{
34            label.setText(obj.toString());
35        }

36        else {
37            label.setText("");
38        }

39        //可以调整此参数设置文字的偏移
40        this.setXOffset(30);
41        this.setWidth(label.getPreferredSize().width + 2);
42        this.setHeight(label.getPreferredSize().height + 2);
43    }

44
45    public void elementPropertyChange(PropertyChangeEvent evt) {
46        super.elementPropertyChange(evt);
47        if (LINKFROMLABEL.equals(TWaverUtil.getPropertyName(evt))) {
48            setLabelText();
49        }

50    }

51
52}

Link添加以上Attachment以后就会自动出现在Link的from端
至于另外一端的标签,我们可以通过TWaver内置的一个Attachment,即Message来实现,代码如下

 1public void setToLabel(String label) {
 2        this.putMessageContent(label);
 3        if (!this.containsAttachment(TWaverConst.ATTACHMENT_MESSAGE)) {
 4            this.addAttachment(TWaverConst.ATTACHMENT_MESSAGE);
 5            this.putMessageStyle(TWaverConst.MESSAGE_COMPONENT_LABEL);
 6            this.putMessageBorderVisible(false);
 7            this.putMessageOpaque(false);
 8            this.putMessagePosition(TWaverConst.POSITION_LINK_TO_ANCHOR);
 9            this.putMessageShadowVisible(false);
10            this.putMessageFont(LinkLabelDemo.USECUSTOMERFONT);
11            this.putMessageForeground(LinkLabelDemo.LABELCOLOR);
12            JLabel label2 = new JLabel();
13            label2.setText(this.getMessageContent());
14            label2.setFont(LinkLabelDemo.USECUSTOMERFONT);
15            //可以设置以下参数设置Message的偏移
16            this.putMessageXOffset(30);
17        }

18    }

通过以上代码就可以实现在Link两端添加标签的效果了

源码请到此处下载:twaver.servasoft.com


评论

# re: 一步一步教你使用TWaver实现UML图—网元篇  回复  更多评论   

2011-08-18 21:38 by nomad2
请问,UML中的序列图,例如:http://www.blogjava.net/pengpenglin/archive/2008/03/25/188498.html 应该如何实现呢?谢谢

只有注册用户登录后才能发表评论。


网站导航: