Posted on 2010-11-24 09:49
TWaver 阅读(3555)
评论(1) 编辑 收藏
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(255, 200, 100, 150));
18 this.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE);
19 this.putCustomDrawOutlineColor(new Color(200, 0, 200));
20
21 this.putLabelPosition(TWaverConst.POSITION_CENTER);
22 this.putLabelFont(TUIManager.getDefaultPlainFont());
23 this.setSize(220, 60);
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