2014-04-02 4 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을 갖고 싶어하고 나는 또한 갖고 싶어 : 내 그래프 보는 것을 원하는 두 꼭지점 사이의 가장자리에 쓰기. 그 중 꼭두각시를 프로젝트에서 만든 일부 개체로 만들기를 원합니다. 그래서 꼭지점을 클릭하여 꼭지점에 배치 된 개체의 인스턴스를 가져옵니다.

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); 
    } 

}

: 나는 jgraph의 frameowork을 시도 처음에는

:

지금까지, 내 ​​그래프를 쉽게 그려진 도면 알고리즘에 너무 많은 작업없이이 두 프레임 워크를 시도 이 프레임 워크는 그래프를 만들 때 잘 작동하며, Rectangle 내부에 정점 이름과 가장자리에 이름이 있으며 MouseListener를 사용하여 정점 안에있는 String을 클릭 할 수 있습니다.

그러나 TreeLayout을 만들고 버텍스를 클릭 할 때 반환 될 수있는 개체로 버텍스를 추가하는 방법을 찾지 못했습니다. 이 예제에있는 제네릭 클래스를 사용하려고 시도했지만이를 실행하려고 시도했을 때만 예외가 발생했습니다. 인터넷에서 수색했지만이 그래프에서 treelayout을 적용 할 방법을 찾지 못했습니다.

그래프를 그리는 데 더 많은 옵션이있는 Java JUNG Framework를 사용해 보았습니다. 에 toString의 객체를 반환() 메소드가 표시됩니다 내가 만든 정점 이름에 일부 개체로 정점을 추가 할 수 있습니다이 프레임 워크를 사용

@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); 
} 

}

:이 예를 발견했다. 또한 TreeLayout 알고리즘이 너무 많아 구현했지만 꼭지점 모양을 변경할 수는 없습니다. 저는 JGraph 프레임 워크에 의해 그려지는 꼭지점처럼 보이기를 원합니다. 그러나 JUNG에서는 단지 일부 원형 만 얻었고 꼭지점 이름은 꼭지점 모양 밖에 있습니다. 버텍스의 모양을 바꾸는 예제를 발견했지만 글쓰기는 여전히 바깥입니다.

그래서이 두 프레임 워크에서 얻을 수있는 것 사이에 어떤 그래프를 그릴 수있는 방법에 대한 제안을 많이 드리고자합니다. 모양 안에 정점 이름을 지정하고 Treelayout을 사용하고 정점을 개체로 추가합니다. 버텍스를 클릭하면 돌아올 수 있습니다.

Marco13의 대답은 매우 유용했습니다. Rectangle에 Rectangle의 너비에 String.length * 10을 설정하여 String을 맞출 수있는 크기로 만들었습니다.

이 그래프를 만들려는 다른 누군가에게 유용 할 것 같습니다 :이 예제에서 가장 일반적인 클래스에 나타나는 것은 대신에 Object가 필요하고 String은 Vertex이고 Integer는 가장자리 유형입니다. . Transformer 함수 안에서 Vertex 나 Edge에 할당 된 Object를 얻습니다. 이처럼 특정 속성을 가진 객체에 대해 다른 모양, 색상 및 글꼴을 설정할 수있었습니다.

클릭 할 때 Edge 객체를 반환하는 MouseListener를 만드는 방법을 알아 냈습니다. 그러나 쉽게 할 수 있기를 바랍니다.

답변

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); 

이 직사각형으로 정점을 렌더링하고, 중앙에 레이블을 넣어. 확장 (예 : 내용의 사각형 크기를 조정하는 것)은 다소 헷갈릴 수도 있지만 수행 할 수 있어야합니다.

관련 문제