2014-04-02 54 views
2

我正在致力于读取一些xml文件并根据这些xml文件中的信息创建图形图表的程序。如何在Java中创建Treelayout图形

我在制作图表时遇到困难。我想,我的图表看: http://pic.dhe.ibm.com/infocenter/elixent/v3r5/topic/com.ibm.ilog.elixir.doc/Content/Visualization/Documentation/Flex/Diagram4Flex/_media/TreeLayoutExample_default.png

所以,我希望它有一个treelayout,顶点的名字被一些彩色矩形内(PREF有不同类型的项目不同的颜色),我也想有一些写在两个顶点之间的边上。最重要的是,我非常喜欢顶点是我在项目中创建的一些对象,所以当我单击一个顶点以获取放置在顶点上的对象的实例时。

到目前为止,我尝试了两种框架,以有我的图形取材容易,没有工作太上绘制算法:

一开始我尝试jgraph frameowork:

package mainPack; 

    import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.Rectangle; 
    import java.util.ArrayList; 
    import java.util.HashMap; 
    import java.util.Map; 

    import javax.swing.JApplet; 
    import javax.swing.JFrame; 

    import org.jgraph.JGraph; 
    import org.jgraph.graph.DefaultGraphCell; 
    import org.jgraph.graph.GraphConstants; 
    import org.jgrapht.ListenableGraph; 
    import org.jgrapht.ext.JGraphModelAdapter; 
    import org.jgrapht.graph.ListenableDirectedGraph; 
    import org.jgrapht.graph.DefaultEdge; 
    import org.jgrapht.graph.ListenableDirectedWeightedGraph; 

    /** 
    * A demo applet that shows how to use JGraph to visualize JGraphT graphs. 
    * 
    * @author Barak Naveh 
    * 
    * @since Aug 3, 2003 
    */ 
    public class Test extends JApplet { 
    private static final Color  DEFAULT_BG_COLOR = Color.decode("#FAFBFF"); 
      private static final Dimension DEFAULT_SIZE = new Dimension(530, 320); 

    // 
    private JGraphModelAdapter m_jgAdapter; 

    /** 
    * @see java.applet.Applet#init(). 
    */ 
    public void init() { 
     // create a JGraphT graph 
     ListenableGraph g = new ListenableDirectedGraph(DefaultEdge.class); 

     // create a visualization using JGraph, via an adapter 
     m_jgAdapter = new JGraphModelAdapter(g); 

     JGraph jgraph = new JGraph(m_jgAdapter); 

     adjustDisplaySettings(jgraph); 
     getContentPane().add(jgraph); 
     resize(DEFAULT_SIZE); 

     // add some sample data (graph manipulated via JGraphT) 
     g.addVertex("v1"); 
     g.addVertex("v2"); 
     g.addVertex("v3"); 
     g.addVertex("v4"); 

     g.addEdge("v1", "v2", "1"); 
     g.addEdge("v2", "v3", "2"); 
     g.addEdge("v3", "v1", "3"); 
     g.addEdge("v4", "v3", "4"); 

     // position vertices nicely within JGraph component 
     positionVertexAt("v1", 130, 40); 
     positionVertexAt("v2", 60, 200); 
     positionVertexAt("v3", 310, 230); 
     positionVertexAt("v4", 380, 70); 

     // that's all there is to it!... 
    } 


    private void adjustDisplaySettings(JGraph jg) { 
     jg.setPreferredSize(DEFAULT_SIZE); 

     Color c  = DEFAULT_BG_COLOR; 
     String colorStr = null; 

     try { 
      colorStr = getParameter("bgcolor"); 
     } 
     catch(Exception e) {} 

     if(colorStr != null) { 
      c = Color.decode(colorStr); 
     } 

     jg.setBackground(c); 
    } 


    private void positionVertexAt(Object vertex, int x, int y) { 
     DefaultGraphCell cell = m_jgAdapter.getVertexCell(vertex); 

     Map    attr = cell.getAttributes(); 
    //  Rectangle  b = new Rectangle((int)(Math.random()*1000),(int)(Math.random()*500),100,30); 

     Rectangle  b = new Rectangle(20,50 ,100,30); 



     GraphConstants.setBounds(attr, b); 

     Map cellAttr = new HashMap(); 
     cellAttr.put(cell, attr); 

     m_jgAdapter.edit(cellAttr, null, null, null); 
    } 

}

该框架适用于制作图形,顶点名称位于矩形内,边上的名称可以在使用MouseListener单击时获取顶点内的字符串。

但我找不到一种方法让它有一个TreeLayout并添加顶点作为一些对象,当点击顶点时我可能返回。我尝试使用本例中的泛型类,但试图运行它时只获得了Exceptions。我在互联网上搜索,但无法找到一种方法来应用此图上的树布局

我也尝试过Java JUNG Framework,它有更多的绘制图的选项。我发现这个例子:

@SuppressWarnings("serial") 
    public class TreeLayoutDemo extends JApplet { 

/** 
* the graph 
*/ 
Forest<String,Integer> graph; 

Factory<DirectedGraph<String,Integer>> graphFactory = 
    new Factory<DirectedGraph<String,Integer>>() { 

     public DirectedGraph<String, Integer> create() { 
      return new DirectedSparseMultigraph<String,Integer>(); 
     } 
    }; 

Factory<Tree<String,Integer>> treeFactory = 
    new Factory<Tree<String,Integer>>() { 

    public Tree<String, Integer> create() { 
     return new DelegateTree<String,Integer>(graphFactory); 
    } 
}; 

Factory<Integer> edgeFactory = new Factory<Integer>() { 
    int i=0; 
    public Integer create() { 
     return i++; 
    }}; 

Factory<String> vertexFactory = new Factory<String>() { 
    int i=0; 
    public String create() { 
     return "V"+i++; 
    }}; 

/** 
* the visual component and renderer for the graph 
*/ 
VisualizationViewer<String,Integer> vv; 

VisualizationServer.Paintable rings; 

String root; 

TreeLayout<String,Integer> treeLayout; 

RadialTreeLayout<String,Integer> radialLayout; 

public TreeLayoutDemo() { 

    // create a simple graph for the demo 
    graph = new DelegateForest<String,Integer>(); 





    createTree(); 

    treeLayout = new TreeLayout<String,Integer>(graph); 
    radialLayout = new RadialTreeLayout<String,Integer>(graph); 
    radialLayout.setSize(new Dimension(600,600)); 
    vv = new VisualizationViewer<String,Integer>(treeLayout, new Dimension(600,600)); 
    vv.setBackground(Color.white); 
    vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line()); 
    vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); 
    // vv.getRenderContext().setVertexShapeTransformer(arg0); 
    // add a listener for ToolTips 
    vv.setVertexToolTipTransformer(new ToStringLabeller()); 
    vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray)); 
    rings = new Rings(); 

    Container content = getContentPane(); 
    final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); 
    content.add(panel); 

    final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); 

    vv.setGraphMouse(graphMouse); 

    JComboBox modeBox = graphMouse.getModeComboBox(); 
    modeBox.addItemListener(graphMouse.getModeListener()); 
    graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); 

    final ScalingControl scaler = new CrossoverScalingControl(); 

    JButton plus = new JButton("+"); 
    plus.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      scaler.scale(vv, 1.1f, vv.getCenter()); 
     } 
    }); 
    JButton minus = new JButton("-"); 
    minus.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      scaler.scale(vv, 1/1.1f, vv.getCenter()); 
     } 
    }); 

    JToggleButton radial = new JToggleButton("Radial"); 
    radial.addItemListener(new ItemListener() { 

     public void itemStateChanged(ItemEvent e) { 
      if(e.getStateChange() == ItemEvent.SELECTED) { 

       LayoutTransition<String,Integer> lt = 
        new LayoutTransition<String,Integer>(vv, treeLayout, radialLayout); 
       Animator animator = new Animator(lt); 
       animator.start(); 
       vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); 
       vv.addPreRenderPaintable(rings); 
      } else { 
       LayoutTransition<String,Integer> lt = 
        new LayoutTransition<String,Integer>(vv, radialLayout, treeLayout); 
       Animator animator = new Animator(lt); 
       animator.start(); 
       vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); 
       vv.removePreRenderPaintable(rings); 
      } 
      vv.repaint(); 
     }}); 

    JPanel scaleGrid = new JPanel(new GridLayout(1,0)); 
    scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); 

    JPanel controls = new JPanel(); 
    scaleGrid.add(plus); 
    scaleGrid.add(minus); 
    controls.add(radial); 
    controls.add(scaleGrid); 
    controls.add(modeBox); 

    content.add(controls, BorderLayout.SOUTH); 
} 

class Rings implements VisualizationServer.Paintable { 

    Collection<Double> depths; 

    public Rings() { 
     depths = getDepths(); 
    } 

    private Collection<Double> getDepths() { 
     Set<Double> depths = new HashSet<Double>(); 
     Map<String,PolarPoint> polarLocations = radialLayout.getPolarLocations(); 
     for(String v : graph.getVertices()) { 
      PolarPoint pp = polarLocations.get(v); 
      depths.add(pp.getRadius()); 
     } 
     return depths; 
    } 

    public void paint(Graphics g) { 
     g.setColor(Color.lightGray); 

     Graphics2D g2d = (Graphics2D)g; 
     Point2D center = radialLayout.getCenter(); 

     Rectangle2D rectangle = new Rectangle2D.Double(); // (center.getX()-10, center.getY()-20, 20, 40); 

     Ellipse2D ellipse = new Ellipse2D.Double(); 
     for(double d : depths) { 


      ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, 
        center.getX()+d, center.getY()+d); 

      rectangle.setFrameFromDiagonal(center.getX()-d, center.getY()-d, 
        center.getX()+d, center.getY()+d); 

      Shape shape = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).transform(rectangle); 
      g2d.draw(shape); 
     } 
    } 

    public boolean useTransform() { 
     return true; 
    } 
} 

/** 
* 
*/ 
private void createTree() { 
    graph.addVertex("V0"); 
    graph.addEdge(edgeFactory.create(), "V0", "V1"); 
    graph.addEdge(edgeFactory.create(), "V0", "V2"); 
    graph.addEdge(edgeFactory.create(), "V1", "V4"); 
    graph.addEdge(edgeFactory.create(), "V2", "V3"); 
    graph.addEdge(edgeFactory.create(), "V2", "V5"); 
    graph.addEdge(edgeFactory.create(), "V4", "V6"); 
    graph.addEdge(edgeFactory.create(), "V4", "V7"); 
    graph.addEdge(edgeFactory.create(), "V3", "V8"); 
    graph.addEdge(edgeFactory.create(), "V6", "V9"); 
    graph.addEdge(edgeFactory.create(), "V4", "V10"); 

    graph.addVertex("A0"); 
    graph.addEdge(edgeFactory.create(), "A0", "A1"); 
    graph.addEdge(edgeFactory.create(), "A0", "A2"); 
    graph.addEdge(edgeFactory.create(), "A0", "A3"); 

    graph.addVertex("B0"); 
    graph.addEdge(edgeFactory.create(), "B0", "B1"); 
    graph.addEdge(edgeFactory.create(), "B0", "B2"); 
    graph.addEdge(edgeFactory.create(), "B1", "B4"); 
    graph.addEdge(edgeFactory.create(), "B2", "B3"); 
    graph.addEdge(edgeFactory.create(), "B2", "B5"); 
    graph.addEdge(edgeFactory.create(), "B4", "B6"); 
    graph.addEdge(edgeFactory.create(), "B4", "B7"); 
    graph.addEdge(edgeFactory.create(), "B3", "B8"); 
    graph.addEdge(edgeFactory.create(), "B6", "B9"); 




} 


/** 
* a driver for this demo 
*/ 
public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    Container content = frame.getContentPane(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    content.add(new TreeLayoutDemo()); 
    frame.pack(); 
    frame.setVisible(true); 
} 

}

利用这个框架我可以添加顶点为我创建和顶点名称一些对象所显示的内容中的toString该对象的回报()方法。它还有我非常想要的TreeLayout算法,但我无法设法改变顶点的外观。我希望它们看起来像JGraph框架绘制的顶点,但是使用JUNG,我只能得到一些圆,并且顶点名称在顶点形状之外。我发现了一个改变顶点形状的例子,但是文字仍然在外面。

所以,我非常希望得到一些关于如何在这两个框架之间绘制一些图形的建议:在形状内部使用顶点名称,使用Treelayout并添加顶点作为某些对象当我点击顶点时我可以返回。

Marco13的回答非常有用。我想通过为矩形的宽度设置String.length * 10来使矩形具有适合他的字符串的大小。

我认为这可能对其他人试图制作像这样的图形有用:在这个例子中,大多数泛型类中不会出现这种情况,可以用于任何需要的对象,字符串用于顶点,整数用于边缘类型。在Transformer函数中,您可以获得为Vertex或Edge分配的对象。像这样,我可以为具有某些特定属性的对象设置不同的形状,颜色和字体。

我的工作是如何制作一个MouseListener,当我点击它时返回Edge对象,但我希望这很容易。

回答

1

您可以在这样第二个示例配置VisualizationViewer

vv.getRenderContext().setVertexShapeTransformer(new Transformer<String, Shape>() 
    { 
     @Override 
     public Shape transform(String vertex) 
     { 
      return new Rectangle2D.Double(-10,-10,40,20); 
     } 
    }); 

    BasicVertexLabelRenderer<String, Integer> vertexLabelRenderer = 
     new BasicVertexLabelRenderer<String, Integer>(); 
    vertexLabelRenderer.setPosition(Renderer.VertexLabel.Position.CNTR); 
    vv.getRenderer().setVertexLabelRenderer(vertexLabelRenderer); 

,这会使得顶点为矩形,并把标签进入中心。扩展(如适应内容的矩形大小)可能有点烦琐,但应该可行。