TWeaver Quick-Start

  • 官网quick-start
  • 运行图见官方,或者自己运行一下
  • Alt + Shift + R,在Eclipse中重命名文件

第一个例子

  • TWaver绘制网元的一般过程如下:
  • 1).new一个容器对象TDataBox、一个画布对象TNetwork;
  • 2).把TNetwork放置在面板中,并布局设置大小;
  • 3).new若干图元(Node、Link等)并add到Box容器中;
  • 下面创建了一个“两点一线”的简单图形:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import twaver.Link;
import twaver.Node;
import twaver.TDataBox;
import twaver.TWaverUtil;
import twaver.network.TNetwork;
public class FirstDemo extends JFrame{
  private TDataBox box = new TDataBox("First Data Box");//创建DataBox容器
  private TNetwork network = new TNetwork(box);//创建可视化视图组件,会显示上面的工具栏
  // network.setToolbarByName(""); //这句话可以把工具栏去掉
  private JPanel networkPanel = new JPanel(new BorderLayout());
  public FirstDemo() {
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    getContentPane().add(networkPanel,BorderLayout.CENTER);
    networkPanel.add(network, BorderLayout.CENTER);
    doSample();
  }
  public static void main(String[] args) {
    FirstDemo frame = new FirstDemo();
    frame.setSize(600,400);
    frame.setTitle("TWaver Tutorial");
    TWaverUtil.centerWindow(frame);
    frame.setVisible(true);
  }
  private void doSample() {
    Node from = new Node("from");
    from.setName("I Am from");
    from.setLocation(50,50); //不加坐标会挤到左上角
    box.addElement(from);
    // 加两个Node
    Node to = new Node("to");
    to.setName("I Am to");
    to.setLocation(500,260);
    box.addElement(to);
    // 加一条线
    Link link = new Link(from, to);
    link.setName("Telephone Line");
    box.addElement(link);
  }
}

例子程序

  • 首先,我们创建一个窗体,然后放入一个分隔条。下面我们开始动手。我们用函数doSample中封装各种TWaver初始化动作
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import twaver.*;
import twaver.network.*;
import twaver.network.ui.*;
import twaver.table.*;
import twaver.tree.*;
public class Tutorial extends JFrame {
    private TDataBox box = new TDataBox("Simple Data Box");
    private TNetwork network;
    private TTree tree;
    private JPanel networkPane = new JPanel(new BorderLayout());
    private JPanel treePane = new JPanel(new BorderLayout());
    private JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane, networkPane);
    public Tutorial() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        getContentPane().add(split, BorderLayout.CENTER);
        split.setDividerLocation(200); //不加的话,左边的框显示不出来
        doSample();
    }
    public static void main(String[] args) {
        Tutorial frame = new Tutorial();
        frame.setSize(500, 300);
        frame.setTitle("TWaver Tutorial");
        TWaverUtil.centerWindow(frame);
        frame.setVisible(true);
    }
    private void doSample() {
        try {
            step1();
            step2();
            step3();
            step4();
            step5();
            step6();
            step7();
            step8();
            step9();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    private void step1() {
    }
    private void step2() {
    }
    private void step3() {
    }
    private void step4() {
    }
    private void step5() {
    }
    private void step6() {
    }
    private void step7() {
    }
    private void step8() {
    }
    private void step9() {
    }
}

step1 创建简单拓扑图

  • 要让拓扑图正常工作,首先需要创建一个DataBox来装载数据。然后创建拓扑图组件与之相连。接下来,把拓扑图放入窗体中。最后,创建两个节点一个连线,放入DataBox
    private void step1() {
        network = new TNetwork(box);
        networkPane.add(network, BorderLayout.CENTER);
        Node nodeA = new Node("A");
        nodeA.setName("I'm node A!");
        nodeA.setLocation(50, 50);
        box.addElement(nodeA);
        Node nodeB = new Node("B");
        nodeB.setName("I'm node B!");
        nodeB.setLocation(200, 200);
        box.addElement(nodeB);
        Link link = new Link("link", nodeA, nodeB);
        link.setName("Telephone Line");
    }

step2 创建树组件

  • 这节介绍如何创建一个树组件,用来显示拓扑图中数据的层次结构,也就是其包含关系。一般的应用程序都会用树和拓扑图协同工作,综合显示数据的外观和层次结构。
  • 首先要创建一个tree组件,然后与前面的DataBox实例进行连接。这样,拓扑图和树就共享了一套DataBox中的数据。然后,将树放在窗口分隔条的左侧。这样,树创建就完成了,前面创建的对象会直接显示在树上面。为了生动起见,我们又创建两个Dummy对象,把数据进行了一些分层,使得tree层次更加生动容易理解。
    private void step2() {
        Dummy nodeDummy = new Dummy("node dummy");
        nodeDummy.setName("All Nodes");
        nodeDummy.addChild(box.getElementByID("A"));
        nodeDummy.addChild(box.getElementByID("B"));
        box.addElement(nodeDummy);
        Dummy linkDummy = new Dummy("link dummy");
        linkDummy.setName("All Links");
        linkDummy.addChild(box.getElementByID("link"));
        box.addElement(linkDummy); // 只是用来分类,不加这两个Dummy会把Node和Link放到一块
        tree = new TTree(box);
        JScrollPane scroll = new JScrollPane(tree);
        treePane.add(scroll, BorderLayout.CENTER); // 这里要套一个scrollpane,nodepane没套是因为TNetwork已经有了
    }

step3 显示设备面板

  • 电信网管系统中,经常要显示电信设备的面板图或者机架图,便于直接监控设备的运行状况。本节介绍如何创建设备面板,并呈现在拓扑图中。我们会用到API和XML两种方式创建数据,供读者参考。
用API创建设备面板
  • 要用API创建设备面板,我们首先需要做一些工作:
  • 创建一个新的Chassis对象,并将其放入节点A(也就是作为节点A的孩子);
  • 创建一个机架对象,放入Chassis对象(作为Chassis对象的孩子);
  • 创建一些端口对象,放入机架中(作为机架的孩子);
  • 以下我们给出了相关代码。按照前面的思路new这些对象,然后放入DataBox中即可。我们创建16个以太网口的交换机,放置在面板的适当位置。这些代码稍微多一点,但是逻辑都极其简单,我们将其放入函数step3
    private void step3() {
        Node node = (Node) box.getElementByID("A");
        Chassis chassis = new Chassis("Chassis A");
        node.addChild(chassis);
        box.addElement(chassis);
        //1.在chassis上添加机架
        Rack rack = new Rack("Rack A");
        rack.setName("Rack");
        rack.setLocation(50, 50);
        rack.setImage("/demo/resource/tutorial/rack.png");
        chassis.addChild(rack);
        box.addElement(rack);
        //2.在机架上添加端口
        String imgPort1 = "/demo/resource/tutorial/port1.png";
        String imgPort2 = "/demo/resource/tutorial/port2.png";
        for (int module = 0; module < 4; module++) {
            Dummy dummy = new Dummy("PortDummy" + module);
            dummy.setName("module" + module);
            rack.addChild(dummy);
            box.addElement(dummy);
            for (int index = 0; index < 4; index++) {
                Port port = new Port(module + ":" + index);
                int x, y;
                if (module % 2 == 0) {
                    x = 210 + index * 24;
                } else {
                    x = 319 + index * 24;
                }
                if (module < 2) {
                    y = 16;
                    port.setImage(imgPort1);
                } else {
                    y = 37;
                    port.setImage(imgPort2);
                }
                x += rack.getLocation().x;
                y += rack.getLocation().y;
                port.setLocation(new Point(x, y));
                dummy.addChild(port);
                box.addElement(port);
            }
        }
    }
  • 我们在拓扑图上用鼠标双击节点A,拓扑图会自动进入我们上面创建的机架图;双击拓扑图的空白区域,可以返回上层拓扑图。节点A作为设备节点,Chassis对象代表一个机架图,Rack代表物理机架,而这些端口对象则代表了设备上的具体以太网端口
用XML创建机架图
  • 上一节介绍了使用API编程的方式用代码来创建机架图。由于每个设备的外观、结构千差万别,如果正在开发一套综合网管系统,需要管理上百种不同厂商的设备,则这个工作就显得非常啰嗦,代码量很大,也不容易维护。这时,可以考虑用XML的方式来简化代码。这节我们同样做上一节所做的工作,只是换成了XML的方式。
  • 首先我们准备设备面板的模版文件,也就是XML文件。我们可以通过TWaver产品Demo提供的编辑器进行编辑,然后导出。为了简化,我们直接给出和上节面板相同数据的XML文件,如下
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.1" class="java.beans.XMLDecoder">
<!-- rack -->
<object class="twaver.Rack" id="rack">
<void property="Image">
<string>/image/twaverRack.png</string></void>
<void property="location">
<object class="java.awt.Point">
<int>100</int>
<int>100</int>
</object>
</void>
</object>
<!-- ports -->
<!-- console port -->
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverConsolePort.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>259</int><int>145</int>
</object>
</void>
</object>
<!-- fiber port -->
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverFiberPort.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>582</int><int>132</int>
</object>
</void>
</object>
<!-- module 1-->
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>310</int><int>116</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>334</int><int>116</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>358</int><int>116</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>382</int><int>116</int>
</object>
</void>
</object>
<!-- module 2-->
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>419</int><int>116</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>443</int><int>116</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>467</int><int>116</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort1.png</string>
</void>
<void property="parent">
<object idref="rack"/></void>
<void property="location">
<object class="java.awt.Point">
<int>491</int><int>116</int>
</object>
</void>
</object>
<!-- module 3-->
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>310</int><int>137</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>334</int><int>137</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>358</int><int>137</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>382</int><int>137</int>
</object>
</void>
</object>
<!-- module 4-->
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>419</int><int>137</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>443</int><int>137</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>467</int><int>137</int>
</object>
</void>
</object>
<object class="twaver.Port">
<void property="Image">
<string>/image/twaverPort2.png</string>
</void>
<void property="parent">
<object idref="rack"/>
</void>
<void property="location">
<object class="java.awt.Point">
<int>491</int><int>137</int>
</object>
</void>
</object>
</java>
  • 然后,我们把它保存在文件equipment1_template.xml中。最后,通过以下代码进行加载
private void step3() {
  //add chassis to node A.
  Node node = (Node) box.getElementByID("A");
  Chassis chassis = new Chassis("Chassis A");
  chassis.setDataSource("/equipment1_template.xml");
  node.addChild(chassis);
  box.addElement(chassis);
}
  • 上述代码还是创建一个Chassis对象,但是把XML模版文件名直接作为属性,设置给Chassis对象即可。具体机架图上的数据不再需要用代码创建。直接运行上述代码,可以看到和上一节一模一样的效果。可见,适当的采用XML方式,可以大幅的减少代码工作量;同时,这个XML也便于修改、维护、存储、交换。
  • 注意:上述代码运行时,在双击节点A之前,机架图数据实际并未加载进DataBox中;当鼠标第一次双击节点A时,TWaver检查Chassis状态是否数据已经加载,如果未加载则从XML中进行读取解析加载,否则直接显示机架图内容。这也是TWaver另外一个重要特性:延迟加载机制。关于延迟加载方面的细节,请看后续章节介绍。
  • 可见,通过XML可以获得如下一些好处:
  • 1 过XML和延迟加载机制,可以加速程序启动速度。想象一下,如果有1000个节点,每个节点都有一套复杂的机架图,则完全通过API来加载,程序启动将非常缓慢,也没有必要在程序启动就创建所有的数据。通过延迟加载,首先显示必须显示的节点数据,当双击查看下层面板细节时,再通过XML获取细节数据。这样可以大幅优化程序的效率。
  • 2 化代码:把相对固定的数据放入XML作为数据模版,可以大幅减少代码的编写数量,便于维护、存储、修改、交换。
  • 3 低内存消耗:通过XML实现”按需加载”的机制,只创建需要的数据,可以节省内存消耗,降低数据的创建数量。
  • 4 据共享:通过定义数据模版,可以实现数据在前后台、多程序间的共享。

step4 设置右键菜单

  • 右键菜单是一个非常常用的交互方法,通过对数据进行选择、右键菜单,可以快速调出上下文有关的操作选项,为软件使用者提供直观的交互方法。TWaver中,我们使用一个叫做弹出菜单生成器(PopupMenuGenerator)的接口,来制作各种不同的右键菜单。更多关于使用右键菜单的例子,请见后续章节。这里仅给出一个简单的例子,让读者了解弹出菜单是如何制作出来的。
  • 菜单生成器是一个接口,被设置在拓扑图或其他图形组件上。一旦设置,当鼠标右键点击图形组件时,TWaver就会回调这个接口获得右键菜单。TWaver会将当前的一些操作场景传入,例如被点击的图形组件、鼠标事件等等。我们要做的,就是根据这些信息,动态的生成需要的右键菜单,返回即可。具体的菜单显示等细节,TWaver会帮我们完成。
    private void step4() {
        //Create a popup menu generator
        PopupMenuGenerator popupMenuGenerator = new PopupMenuGenerator() {
            /** * Add the identifier of each of the selected objects to the menu. * In this example, the items added to the menu do nothing. * In a real application, you would probably associate an * implementation of the Swing Action interface with each menu item. */
            public JPopupMenu generate(TView tview, MouseEvent mouseEvent){
                //Create an empty pop-up menu.
                JPopupMenu popMenu = new JPopupMenu();
                JMenuItem item;
                //If the selectedObjects collection is empty, no objects are selected.
                if (tview.getDataBox().getSelectionModel().isEmpty()) {
                    popMenu.add("Nothing selected");
                } else {
                    //Access the selected objects from the selection model.
                    Iterator it = tview.getDataBox().getSelectionModel().selection();
                    while (it.hasNext()) {
                        Element element = (Element) it.next();
                        popMenu.add(element.getName());
                    }
                }
                //If menu is empty, return null.
                if (popMenu.getComponentCount() == 0) {
                    return null;
                } else {
                    return popMenu;
                }
            }
        };
        //Set the pop-up menu generator for network components
        network.setPopupMenuGenerator(popupMenuGenerator);
    }

step5 添加鼠标和键盘动作

  • 拓扑图是在Java Swing组件的扩展上扩展出来的,和其他Swing组件一样,在Network上添加鼠标、键盘事件是很容易的。唯一需要注意的是,拓扑图并非一个简单JComponent,它由工具条、滚动窗口、画布等部分组成。所以,实际上我们一般添加动作都是针对于画布的,而不是Network本身。所以,要使用network.getCanvas()方法先获得画布对象,然后就可以像其他Swing组件那样添加各种监听器了。
  • 为了演示,我们在例子中添加一个双击动作,弹出消息框显示被双击的数据对象。这段代码被封装在函数step5中
    private void step5() {
        network.getCanvas().addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                //获取双击的网元对象
                    Element element = network.getElementPhysicalAt(e.getPoint());
                    String message;
                    if (element == null) {
                        message = "You clicked nothing.";
                    } else {
                        message = "You clicked '" + element.getName() + "'";
                    }
                    JOptionPane.showMessageDialog(network, message);
                }
            }
        });
    }
  • 运行程序如下图。双击空白区和双击对象,都会弹出消息。
  • 此外,为了方便开发者监听鼠标事件,TWaver添加了经过封装的鼠标监听方法:
  • TNetwork.addElementDoubleClickedActionListener:添加Element双击事件监听器。
  • TNetwork.addBackgroundDoubleClickedActionListener:添加空白区域双击事件监听器。
  • TNetwork.addElementClickedActionListener:添加Element单击事件监听器。
  • 通过这些高度封装的方法,监听鼠标事件就更加方便了。

step6 处理数据选择

  • 这一节将介绍如下内容:
  • 控制选择;
  • 监听选择变化;
  • 移动拓扑图以便选中数据处于可见位置;
  • 由于选择容器是DataBox的一个组成部分,所以所有共享同一个DataBox的图形组件也共享同一套数据选择状态。也就是说,一个对象被选择,是在数据层决定的,它在所有与DataBox相连的图形组件上都会体现出来。如果对选择变化进行监听,则从DataBox的选择容器进行加装监听器。每次选择发生变化,事件会被发送到所有监听器。我们可以在监听器中写代码执行各种任务。
  • 为了展示这个功能,我们创建一个监听器,当用户从tree选择一个数据后,拓扑图也会显示选中数据,并且如果这个选中的数据不在可见区域内,会自动滚动画布以保证数据处于可见视野内。
    private void step6() {
        //create a selection listener.
        DataBoxSelectionListener listener = new DataBoxSelectionListener() {
            public void selectionChanged(DataBoxSelectionEvent e) {
                //get the last selected element and make it visible.
                Element element = e.getBoxSelectionModel().lastElement();
                if (element != null) {
                    network.ensureVisible(element);
                }
            }
        };
        box.getSelectionModel().addDataBoxSelectionListener (listener);
    }
    private void step7() {
    }

step7 添加告警

  • 这一节介绍如何在数据上使用告警。TWaver提供了综合、全面、强大的告警支持,以简化电信管理软件的开发复杂度。TWaver提供了许多关于告警方面的图形渲染属性,用于控制告警的呈现。当告警发生后,对应的数据就会以相应的方式进行绘制和渲染,以便用直观、易于理解的方式提醒用户。
  • 每一个Element对象都有一个告警状态表Alarm State。这是一个告警信息表,记录了所有发生在Element上面的告警信息。要为数据添加告警,首先要获得告警状态表,然后在其中添加告警信息即可。数据会在拓扑图、树等图形组件上做出相应的显示变化。
  • 另外,还可以使用DataBox提供的告警传播机制。TWaver默认提供了一个功能完善的告警传播器,可以将告警沿着父对象的路径进行传播。也可以编写符合自己业务规则的告警传播器,设置在DataBox上使用。
  • 这里,我们对前面创建的数据添加一些告警,代码被封装在step7函数中。
    //还没看明白
    private void step7() {
        //create and set a summing propagator to the data source,
        //here will make the box propagate alarms to its parent.
        box.setAlarmPropagator(new SummingAlarmPropagator());
        //get a port in the equipment rack.
        Port nodeA = (Port) box.getElementByID("0:0");
        AlarmState alarmState = nodeA.getAlarmState();
        //add an acknowledged alarm with critical severity.
        alarmState.acknowledgeAlarm(AlarmSeverity.CRITICAL);
        //add and new alarm with major severity.
        alarmState.addNewAlarm(AlarmSeverity.MAJOR);
        //get another port.
        Port nodeB = (Port) box.getElementByID("3:3");
        alarmState = nodeB.getAlarmState();
        //add 10 new alarms with critical minor.
        alarmState.increaseNewAlarm(AlarmSeverity.MINOR, 10);
    }

step8 添加装饰图标

  • TWaver支持在各种数据对象上附着显示一些动态图标,用来表示一些动态的网络事件信息。例如,一个设备出了告警之外,还有一些其他并不像告警那么严重的时间信息,这些信息也需要用一种非常直观、醒目的方式显示出来提示用户。这种情况下,可以使用Attachment附件机制。装饰图标就是一种附件,它用一个小图标来表示某些事件的发生,并显示在对应的宿主对象边缘,用于显示一些网络上发生的动态事件和信息。
  • TWaver默认提供了一些预定义的装饰图标,可以直接使用。这些都被IconAttachmentHolder类进行统一管理。扩展新的装饰图标也很简单。我们通过代码进行演示如何操作。首先,我们需要一个小图标: icon,然后我们定义一个新的装饰图标并进行注册,然后让它显示在某一个Element上面。装饰图标从IconAttachment进行继承,我们重载构造函数,指定我们的图标即可。新的装饰图标需要是一个顶级类,我们推荐用public static来定义,或者放入单独的一个文件中TUIManager.registerAttachment方法进行注册,这样在运行过程中,就可以用element.addAttachment方法显示装饰图标了。
    //define a new LayoutedIconAttachment.
    //It must define as public static class.
    public static class MyIconAttachment extends IconAttachment{
        public MyIconAttachment(String name, ElementUI ui) {
            super(name, ui, TWaverUtil.getImageIcon("myIcon.png"));
        }
    }
    private void step8() {
        String iconName="document";
        TUIManager.registerAttachment(iconName, MyIconAttachment.class);
        //put a "document" icon on element B.
        Element element = box.getElementByID("A");
        element.addAttachment(iconName);
    }

step9 添加显示特效

  • TWaver提供了丰富的显示特效,尤其在拓扑图上面。例如,我们可以在连线上显示流动的特殊动画效果。我们通过对应的API函数就可以实现这种效果,非常简单。
  • 单击中间的Link会显示加粗
    private void step9() {
        //get the link element.
        Link element = (Link)box.getElementByID("link");
        //make the link animating flowing
        element.putLinkFlowing(true);
        //set the link flowing color
        element.putLinkFlowingColor(Color.black);
        //set the link outline color
        element.putLinkOutlineColor(Color.black);
        //set the link body color.
        element.putLinkColor(Color.white);
        //set the link lable font
        element.putLabelFont(new Font("Impact", 1, 20));
        //set the link lable color
        element.putLabelColor(Color.MAGENTA);
    }

总的代码

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import twaver.*;
import twaver.network.*;
import twaver.network.ui.*;
import twaver.table.*;
import twaver.tree.*;
public class Tutorial extends JFrame {
    private TDataBox box = new TDataBox("Simple Data Box");
    private TNetwork network;
    private TTree tree;
    private JPanel networkPane = new JPanel(new BorderLayout());
    private JPanel treePane = new JPanel(new BorderLayout());
    private JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane, networkPane);
    public Tutorial() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        getContentPane().add(split, BorderLayout.CENTER);
        split.setDividerLocation(200); // 不加的话,左边的框显示不出来
        doSample();
    }
    public static void main(String[] args) {
        Tutorial frame = new Tutorial();
        frame.setSize(500, 300);
        frame.setTitle("TWaver Tutorial");
        TWaverUtil.centerWindow(frame);
        frame.setVisible(true);
    }
    private void doSample() {
        try {
            step1();
// step2();
// step3();
// step4();
// step5();
// step6();
// step7();
// step8();
// step9();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    private void step1() {
        network = new TNetwork(box);
// network.setToolbarByName(""); //这句话可以把工具栏去掉
        networkPane.add(network, BorderLayout.CENTER);
        Node nodeA = new Node("A");
        nodeA.setName("I'm node A!");
        nodeA.setLocation(50, 50);
        box.addElement(nodeA);
        Node nodeB = new Node("B");
        nodeB.setName("I'm node B!");
        nodeB.setLocation(200, 200);
        box.addElement(nodeB);
        Link link = new Link("link", nodeA, nodeB);
        link.setName("Telephone Line");
        box.addElement(link);
    }
    private void step2() {
        Dummy nodeDummy = new Dummy("node dummy");
        nodeDummy.setName("All Nodes");
        nodeDummy.addChild(box.getElementByID("A"));
        nodeDummy.addChild(box.getElementByID("B"));
        box.addElement(nodeDummy);
        Dummy linkDummy = new Dummy("link dummy");
        linkDummy.setName("All Links");
        linkDummy.addChild(box.getElementByID("link"));
        box.addElement(linkDummy); // 只是用来分类,不加这两个Dummy会把Node和Link放到一块
        tree = new TTree(box);
        JScrollPane scroll = new JScrollPane(tree);
        treePane.add(scroll, BorderLayout.CENTER); // 这里要套一个scrollpane,nodepane没套是因为TNetwork已经有了
    }
    private void step3() {
        // add chassis to node A.
        Node node = (Node) box.getElementByID("A");
        Chassis chassis = new Chassis("Chassis A");
        chassis.setDataSource("/equipment1_template.xml");
        node.addChild(chassis);
        box.addElement(chassis);
    }
    private void step4() {
        //Create a popup menu generator
        PopupMenuGenerator popupMenuGenerator = new PopupMenuGenerator() {
            /** * Add the identifier of each of the selected objects to the menu. * In this example, the items added to the menu do nothing. * In a real application, you would probably associate an * implementation of the Swing Action interface with each menu item. */
            public JPopupMenu generate(TView tview, MouseEvent mouseEvent){
                //Create an empty pop-up menu.
                JPopupMenu popMenu = new JPopupMenu();
                JMenuItem item;
                //If the selectedObjects collection is empty, no objects are selected.
                if (tview.getDataBox().getSelectionModel().isEmpty()) {
                    popMenu.add("Nothing selected");
                } else {
                    //Access the selected objects from the selection model.
                    Iterator it = tview.getDataBox().getSelectionModel().selection();
                    while (it.hasNext()) {
                        Element element = (Element) it.next();
                        popMenu.add(element.getName());
                    }
                }
                //If menu is empty, return null.
                if (popMenu.getComponentCount() == 0) {
                    return null;
                } else {
                    return popMenu;
                }
            }
        };
        //Set the pop-up menu generator for network components
        network.setPopupMenuGenerator(popupMenuGenerator);
    }
    private void step5() {
        network.getCanvas().addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                //获取双击的网元对象
                    Element element = network.getElementPhysicalAt(e.getPoint());
                    String message;
                    if (element == null) {
                        message = "You clicked nothing.";
                    } else {
                        message = "You clicked '" + element.getName() + "'";
                    }
                    JOptionPane.showMessageDialog(network, message);
                }
            }
        });
    }
    private void step6() {
        //create a selection listener.
        DataBoxSelectionListener listener = new DataBoxSelectionListener() {
            public void selectionChanged(DataBoxSelectionEvent e) {
                //get the last selected element and make it visible.
                Element element = e.getBoxSelectionModel().lastElement();
                if (element != null) {
                    network.ensureVisible(element);
                }
            }
        };
        box.getSelectionModel().addDataBoxSelectionListener (listener);
    }
    private void step7() {
        //create and set a summing propagator to the data source,
        //here will make the box propagate alarms to its parent.
        box.setAlarmPropagator(new SummingAlarmPropagator());
        //get a port in the equipment rack.
        Port nodeA = (Port) box.getElementByID("0:0");
        AlarmState alarmState = nodeA.getAlarmState();
        //add an acknowledged alarm with critical severity.
        alarmState.acknowledgeAlarm(AlarmSeverity.CRITICAL);
        //add and new alarm with major severity.
        alarmState.addNewAlarm(AlarmSeverity.MAJOR);
        //get another port.
        Port nodeB = (Port) box.getElementByID("3:3");
        alarmState = nodeB.getAlarmState();
        //add 10 new alarms with critical minor.
        alarmState.increaseNewAlarm(AlarmSeverity.MINOR, 10);
    }
    //define a new LayoutedIconAttachment.
    //It must define as public static class.
    public static class MyIconAttachment extends IconAttachment{
        public MyIconAttachment(String name, ElementUI ui) {
            super(name, ui, TWaverUtil.getImageIcon("myIcon.png"));
        }
    }
    private void step8() {
        String iconName="document";
        TUIManager.registerAttachment(iconName, MyIconAttachment.class);
        //put a "document" icon on element B.
        Element element = box.getElementByID("A");
        element.addAttachment(iconName);
    }
    private void step9() {
        //get the link element.
        Link element = (Link)box.getElementByID("link");
        //make the link animating flowing
        element.putLinkFlowing(true);
        //set the link flowing color
        element.putLinkFlowingColor(Color.black);
        //set the link outline color
        element.putLinkOutlineColor(Color.black);
        //set the link body color.
        element.putLinkColor(Color.white);
        //set the link lable font
        element.putLabelFont(new Font("Impact", 1, 20));
        //set the link lable color
        element.putLabelColor(Color.MAGENTA);
    }
}

你可能感兴趣的:(TWeaver Quick-Start)