Vertex label color in Jung visualization

2019-08-10 21:49发布

问题:

I've created a graph with Jung and I'm looking into visualization options. I'm trying to change the color of the vertex labels, don't care if they are picked/unpicked, just from the get-go.

I.e. I want to paint the vertex labels white, leave edge labels black (default).

Can't seem to find a sample that works, the DefaultVertexLabelRenderer class should help I guess but I can't seem to get it to work. Any ideas? The code currently looks like this:

public static void main(String[] args) {
    Graph<Node, Double> g = MakeGraph.makeManual(); //graph created somewhere

     Layout<Node, Double> layout = new CircleLayout<Node, Double>(g);
     layout.setSize(new Dimension(300,300)); 
     VisualizationViewer<Node, Double> vv = new VisualizationViewer<Node, Double>(layout);
     vv.setPreferredSize(new Dimension(500,500)); 


    // Paints the vertex (as a shape)
     Transformer<Node,Paint> vertexPaint = new Transformer<Node,Paint>() {
         public Paint transform(Node node) {
             if(node.getNodeType().equals(NodeType.SLA)) return new Color(228,108,10);//Color.ORANGE;
             else return new Color(79,129,189);//Color.BLUE;
         }
     }; 

     //Wanna do this: paint the label text
     Transformer<Node,Paint> vertexLabelPaint = new Transformer<Node,Paint>() {
         public Paint transform(Node node) {
             return Color.WHITE;
         }
     };

     //Sets the vertex label font
     Transformer<Node,Font> vertexFont = new Transformer<Node,Font>() {
         public Font transform(Node node) {
             Font font = new Font("Calibri", Font.BOLD, 14);
             return font;
         }
     };

    //Sets the vertex shape's size, w.r.t. to the size of the text in the label
     Transformer<Node,Shape> vertexSize = new Transformer<Node,Shape>(){
            public Shape transform(Node node){
                Ellipse2D circle = new Ellipse2D.Double(-15, -15, 30, 30);
                AffineTransform affinetransform = new AffineTransform();
                FontRenderContext frc = new FontRenderContext(affinetransform,true,true);     
                Font font = new Font("Calibri", Font.BOLD, 14);
                int textwidth = (int)(font.getStringBounds(node.toString(), frc).getWidth());

                return AffineTransform.getScaleInstance(textwidth/14, 1).createTransformedShape(circle);
            }
        };


     vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.WHITE));
     vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint); //fill
     vv.getRenderContext().setVertexDrawPaintTransformer(vertexPaint); //outline
     vv.getRenderContext().setVertexFontTransformer(vertexFont);
     vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Node>());
     //COLOR ME WHITE! ^^
     vv.getRenderContext().setVertexShapeTransformer(vertexSize);
     vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);

     vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller<Double>());
     //LEAVE ME BLACK ^^

     DefaultModalGraphMouse<Node, Double> gm = new DefaultModalGraphMouse<Node, Double>();
    // gm.setMode(ModalGraphMouse.Mode.TRANSFORMING); 
     vv.setGraphMouse(gm); 

     JFrame frame = new JFrame("Test Graph");
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.getContentPane().add(vv);
     frame.pack();
     frame.setVisible(true);

}}

I tried

DefaultVertexLabelRenderer dvlr = new DefaultVertexLabelRenderer(Color.WHITE);
     dvlr.setForeground(Color.WHITE);
     vv.getRenderContext().setVertexLabelRenderer(dvlr);

to no avail.

回答1:

One option is to override the method that returns the renderer component for the labels, and sets the foreground color accordingly. Here this is implemented as a MCVE (which, when it is already provided in the question, makes it much easier to quickly try it out and find a solution...)

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;

import javax.swing.JComponent;
import javax.swing.JFrame;

import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer;

public class JungVertexLabelColors 
{
    public static void main(String[] args) 
    {
        JFrame jf = new JFrame();
        final Graph<String, String> g = getGraph();
        final VisualizationViewer<String, String> vv = 
            new VisualizationViewer<String, String>(
                new FRLayout<String, String>(g));
        DefaultModalGraphMouse<Node, Double> graphMouse = 
            new DefaultModalGraphMouse<Node, Double>();
        vv.setGraphMouse(graphMouse); 


        final Color vertexLabelColor = Color.RED;
        DefaultVertexLabelRenderer vertexLabelRenderer = 
            new DefaultVertexLabelRenderer(vertexLabelColor)
        {
            @Override
            public <V> Component getVertexLabelRendererComponent(
                JComponent vv, Object value, Font font, 
                boolean isSelected, V vertex) 
            {
                super.getVertexLabelRendererComponent(
                    vv, value, font, isSelected, vertex);
                setForeground(vertexLabelColor);
                return this;
            }
        };
        vv.getRenderContext().setVertexLabelRenderer(vertexLabelRenderer);
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<String>());



        jf.getContentPane().add(vv);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);
    }

    public static Graph<String, String> getGraph() 
    {
        Graph<String, String> g = new DirectedSparseGraph<String, String>();
        g.addVertex("v0");
        g.addVertex("v1");
        g.addVertex("v2");
        g.addVertex("v3");
        g.addVertex("v4");
        g.addEdge("e0", "v0", "v1");
        g.addEdge("e1", "v1", "v2");
        g.addEdge("e2", "v2", "v3");
        g.addEdge("e3", "v3", "v4");
        g.addEdge("e4", "v4", "v0");
        g.addEdge("e5", "v1", "v3");
        g.addEdge("e6", "v2", "v4");
        return g;
    }    
}

(It's indeed a bit strange that there seems to be no easier way, but according to the implementation of DefaultVertexLabelRenderer, there is no way to influence the default label color with the renderer itself: It simply takes the foreground color from the VisualizationViewer. (So visualizationViewer.setForeground(Color.RED) would change the color, but this would affect all labels...))



标签: java jung jung2