TWaver提供了一些布局算法帮助我们快速为网元设置位置,很多情况下已经够用了,但是对于一些复杂的布局还需要我们自己做一些处理,看下面这个例子:
运行截图:
这个时候直接使用TNetwork#doLayout就不好使了,因为doLayout会对network中所有网元使用同一种布局算法,但是截图中Group下多个子Group各有自己的布局方式,我的解决办法是,先对最外层的Group整个布局,然后递归遍历子Group,单独对他们进行布局。
代码实现:
TWaver中实现局部布局可以通过两种方式:
- 将要布局的Element加入到一个新的TNetwork中,然后用新的TNetwork布局
- TWaver默认只对选中的Element布局,所以可以将要布局的Element加入到SelectionModel中
在这个demo中,首先用第一种方式对最外层的Group进行布局:
//layoutNetwork是用来布局的临时network //生成Group时,已经将布局方式存入ClientProperty layoutDatabox.addElementWithDescendant(group1); layoutNetwork.doLayout((Integer)group1.getClientProperty("layout"),false);
然后递归遍历group,为子group布局
recursionChild(group1); ............................................ private void recursionChild(Group group){ for(int i=0;i<group.getChildren().size();i++){ Element element= (Element) group.getChildren().get(i); if(element instanceof Group){ Group childGroup=((Group)element); recursionChild(childGroup);//如果有子Group,会一直递归 //使用两种方式结合,将要布局的子group加入到layoutNetwork的SelectionModel layoutDatabox.getSelectionModel().clearSelection(); layoutDatabox.getSelectionModel().appendSelection(childGroup.getChildren()); layoutNetwork.doLayout((Integer) ((Group) element).getClientProperty("layout"), false); layoutDatabox.getSelectionModel().clearSelection(); } } }
最后附上全部代码
public class LayoutTest extends JPanel { TDataBox layoutDatabox=new TDataBox(); TNetwork layoutNetwork=new TNetwork(layoutDatabox); public LayoutTest(){ TNetwork network=new TNetwork(); ResizableNode gatewayNode=new ResizableNode(); gatewayNode.putCustomDraw(true); gatewayNode.putCustomDrawShapeFactory(TWaverConst.SHAPE_ROUND_RECTANGLE_HALF); gatewayNode.putCustomDrawGradient(false); gatewayNode.putCustomDrawFillColor(new Color(254, 254, 206)); gatewayNode.setSize(70, 30); gatewayNode.setName("Gateway"); gatewayNode.putLabelPosition(TWaverConst.POSITION_CENTER); Group group1=createGroup(4,TWaverConst.LAYOUT_TREE); Group group1_1=createGroup(12,TWaverConst.LAYOUT_CIRCULAR); Group group1_2=createGroup(5,TWaverConst.LAYOUT_EAST); Link group1_2Link=new Link((Node)group1.getChildren().get(0),(Node)group1_2.getChildren().get(0)); setLinkStyle(group1_2Link); group1.addChild(group1_2); group1.addChild(group1_2Link); Link group1_1Link=new Link((Node)group1.getChildren().get(0),(Node)group1_1.getChildren().get(0)); setLinkStyle(group1_1Link); group1.addChild(group1_1); group1.addChild(group1_1Link); //layoutNetwork是用来布局的临时network //生成Group时,已经将布局方式存入ClientProperty layoutDatabox.addElementWithDescendant(group1); layoutNetwork.doLayout((Integer)group1.getClientProperty("layout"),false); recursionChild(group1); TDataBox box=new TDataBox(); box.addElementWithDescendant(group1); box.addElement(gatewayNode); group1.putGroupOpaque(true); group1.putGroupFillColor(new Color(154,206,254)); network.setDataBox(box); this.setLayout(new GridLayout(1,3)); this.add(network); Layer layer=new Layer(); box.getLayerModel().addLayer(layer); box.getLayerModel().moveToTop(layer); Link link1=new Link(group1,gatewayNode); setLinkStyle(link1); link1.setLinkType(TWaverConst.LINK_TYPE_ORTHOGONAL); link1.setLayerID(layer.getID()); box.addElement(link1); } /** * 递归Group设置布局 * @param group */ private void recursionChild(Group group){ for(int i=0;i<group.getChildren().size();i++){ Element element= (Element) group.getChildren().get(i); if(element instanceof Group){ Group childGroup=((Group)element); recursionChild(childGroup);//如果有子Group,会一直递归 //使用两种方式结合,将要布局的子group加入到layoutNetwork的SelectionModel layoutDatabox.getSelectionModel().clearSelection(); layoutDatabox.getSelectionModel().appendSelection(childGroup.getChildren()); layoutNetwork.doLayout((Integer) ((Group) element).getClientProperty("layout"), false); layoutDatabox.getSelectionModel().clearSelection(); } } } /** * 产生测试Group及Node * @param childCount * @param layout * @return */ private Group createGroup(int childCount,int layout){ Group group=new Group(); group.setExpand(true); group.putClientProperty("layout",layout); ResizableNode router=new ResizableNode(); router.putCustomDraw(true); router.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE); router.putCustomDrawGradient(false); router.putCustomDrawFillColor(new Color(254, 254, 206)); router.setSize(60, 20); router.setName("Router"); router.putLabelPosition(TWaverConst.POSITION_CENTER); group.addChild(router); for(int i=0;i<childCount;i++){ Node childNode=new Node(); Link link=new Link(router,childNode); childNode.putCustomDraw(true); childNode.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE); childNode.putCustomDrawGradient(false); childNode.putCustomDrawFillColor(new Color(254,202,2)); childNode.setName("C"+i); childNode.putLabelPosition(TWaverConst.POSITION_CENTER); setLinkStyle(link); group.addChild(childNode); group.addChild(link); } return group; } /** * 设置link样式 * @param link */ public void setLinkStyle(Link link){ link.putLinkColor(Color.black); link.putLinkOutlineWidth(0); link.putLinkWidth(1); link.putLinkAntialias(true); link.putLinkToArrow(true); link.putLinkToArrowOutline(false); } public static void main(String[] args){ SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JFrame frame=new JFrame("布局"); frame.setSize(1000,700); frame.setContentPane(new LayoutTest()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } }
代码和思路都很简单,希望能抛砖引玉,大家有建议或好的想法也可以交流一下