Я пытаюсь использовать Jung для проекта, и чтобы получить желаемый внешний вид/поведение, я начинаю с некоторых тестовых данных.
Идея состоит в том, чтобы иметь очень большие вершины с метками поверх форм вершин. Данные для графика будут генерироваться во время выполнения, поэтому я не могу сделать статическую компоновку.
Как мне расположить график так, чтобы Вершины не перекрывались, но все же были достаточно большими, чтобы метки помещались внутри (настоящая метка будет иметь более длинные строки 20-30 символов). Я пытался использовать SpringLayout, но узлы по-прежнему перекрываются, кроме того, макет продолжает покачиваться (что раздражает).
Я также пробовал FRLayout, увеличивая множитель Repulsion, однако после того, как число становится достаточно большим, он просто создает круг с перекрывающимися вершинами.
Если я увеличиваю масштаб с помощью жестов мыши, узлы кажутся разделенными, и я получаю вид ближе к тому, что хочу. Так что, возможно, решение включает в себя увеличение при инициализации, просто не уверен, как именно это сделать и как решить, насколько увеличить масштаб, поскольку это может зависеть от количества узлов.
Как правило, мои данные будут иметь небольшое количество узлов (менее 50 и чаще менее 10). Однако он управляется данными, поэтому у меня нет полного контроля над этими размерами.
Наконец, когда график действительно появляется, он также частично находится за пределами экрана. В идеале он будет отображаться в верхней левой части видимой области. Есть ли способ контролировать это?
Ниже приведен пример класса, с которым я работаю, чтобы лучше показать, что я имею в виду (обрезанный для выпуска).
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.TestGraphs;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
import edu.uci.ics.jung.algorithms.layout.SpringLayout;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.AbstractVertexShapeTransformer;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import java.awt.BorderLayout;
import java.awt.Color;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;
import edu.uci.ics.jung.visualization.picking.PickedState;
import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer;
import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer;
import edu.uci.ics.jung.visualization.renderers.VertexLabelAsShapeRenderer;
import java.awt.*;
public class IDRelationshipGraphPanel extends javax.swing.JPanel
{
private final VisualizationViewer<Integer,Number> vv;
protected Transformer<Integer,String> vs;
protected DefaultModalGraphMouse<Integer, Number> gm;
protected AbstractLayout layout;
protected VertexShapeSizeAspect<Integer,Number> vssa;
public IDRelationshipGraphPanel()
{
Graph<? extends Object, ? extends Object> g = TestGraphs.getOneComponentGraph();
layout = new SpringLayout( g) ;
vv= new VisualizationViewer<Integer,Number>(layout);
GraphZoomScrollPane scrollPane = new GraphZoomScrollPane(vv);
gm = new DefaultModalGraphMouse<Integer, Number>();
vv.setGraphMouse(gm);
add(scrollPane, BorderLayout.CENTER);
PickedState<Integer> picked_state = vv.getPickedVertexState();
VertexLabelAsShapeRenderer<Integer, Number> vlasr = new VertexLabelAsShapeRenderer<Integer, Number>(vv.getRenderContext());
vv.getRenderContext().setVertexShapeTransformer(vlasr);
vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.red));
vv.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(2.5f)));
// customize the renderer
vv.getRenderer().setVertexRenderer(new GradientVertexRenderer<Integer, Number>( new Color(175,224,228), new Color(133,170,173), true));
vv.getRenderer().setVertexLabelRenderer(vlasr);
vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Integer>());
vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<Integer, Number>());
vssa = new VertexShapeSizeAspect<Integer,Number>();
vv.getRenderContext().setVertexShapeTransformer(vssa);
vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
vv.getRenderContext().setArrowDrawPaintTransformer(new ConstantTransformer(Color.black));
}
private final static class VertexShapeSizeAspect<V,E>
extends AbstractVertexShapeTransformer <V>
implements Transformer<V,Shape> {
public VertexShapeSizeAspect()
{
setSizeTransformer(new Transformer<V,Integer>()
{
public Integer transform(V v)
{
return 150;
}
});
setAspectRatioTransformer(new Transformer<V,Float>()
{
public Float transform(V v)
{
return 1.0f;
}
});
}
public Shape transform(V v){return factory.getEllipse(v);}
}
}
Перекрытие вершин с помощью Spring Layout
Увеличение Spring Layout выглядит лучше