First of all, I am new to JUNG. I am trying to visualize trees in JUNG using the TreeLayout, but I am always faced with the issue of overlapping vertex labels. More so when the number of nodes and paths are many. Any ideas as to how to go about preventing such an overlap ?
I am aware of the vertex label renderer, but I did not get far with this either.
Here are a couple of options:
(1) Increase distx (the distance between adjacent tree leaves). This is an optional constructor argument.
(2) Use a Transformer for the rendered label that uses a substring of the label, or a shortened representation. Then separately set hover text to show the entire label.
Related
I am trying to create a JGraphXAdapter which receives a directed graph as a constructor argument and applied a mxHierarchicalLayout to it. Then, I use mxCellRenderer to create a BufferedImage and write the visualization to a png file.
The problem is that I do not want the edge labels to be visible. I tried (incorrectly) using this command, but it turns off all the labels.
JGraphXAdapter<String, DefaultEdge> graphAdapter = new JGraphXAdapter<>(directedGraph);
graphAdapter.setLabelsVisible(false);
Is there any way to just turn off the edge labels, but not the vertex labels? Thanks
graphAdapter.getEdgeToCellMap().forEach((edge, cell) -> cell.setValue(null));
Edit: there is not much to comment there... "cells" in JGraphX terminology are objects representing visuals of both edges and vertices. So, if you want to change how one specific element is drawn, you should first find its cell through edge->cell or vertex->cell map.
Cell's "value" is its reference to a represented object. Strings that you see on vertices and edges after JGraphX renders everything are basically cell.value == null ? "" : cell.value.toString() (might look a bit different in the source code).
Is it possible to change the edge shape in JUNG? For example, I would like to have the edge change it's color gradually in a way similar to a progress bar. What about the edge label font size?
Thanks.
Yes, sort of... Also - I'm not sure which version of JUNG you're using, but this works in the latest JUNG 2 release (I realize JUNG 3 might be under development currently, but last time I checked, it wasn't stable enough to be used for production-level code).
1. Labelling: First, you need to implement the Transformer<EdgeType,Font> interface that converts your edge instances into Font instances. Then call [VisualizationViewer instance].getRenderContext().setEdgeFontTransformer([Transformer<EdgeType,Font> instance]).
2. Color/Stroke Customization: This is a little trickier, because the only way you can have this change color gradually (that I am aware of) is by creating a Transformer<EdgeType,Paint> that returns different paints for edge type instances over time. There are several transformers used for edges - these control the draw, the fill, and the Stroke, and have similar method names like the one mentioned for the labeller in step 1. You will either need to control when the graph panel repaints manually or ensure that JUNG's animation renderer is turned on so that repaints happen continuously.
In other words, I'm trying to do something with JavaFX like what Batik allows you to do with Swing.
I want to be able to capture the appearance of an arbitrary node in my JavaFX UI, much like Node.snapshot() does, except that I need my image in a vector format like SVG, not a raster image. (And inserting a raster snapshot of my node into an SVG image is not good enough; it needs to be a proper, scalable vector image.)
This is a long-term project, so I'm even willing to go as far as implementing my own GraphicsContext, or whatever the equivalent is in JavaFX's retained mode API.
Does anyone know if there is a way to do this? Is what I'm hoping to do even possible in JavaFX?
I started to write a JavaFx Node to SVG converter which "extends" the ShapeConverter from Gerrit Grunwald which only converts Shape geometries:
https://github.com/stefaneidelloth/JavaFxNodeToSvg
... and stopped it after a certain amount of frustration.
Please feel free to improve it, add features and fix bugs.
The converter works for simple Node examples but fails for advanced examples like a Chart. My failed converter might serve you as a starting point. The current state is illustrated by the following figures. The left side shows the original JavaFx node and the right side shows the resulting svg output.
Simple node example (works):
Chart example (does not work):
The corresponging svg files are available here:
https://github.com/stefaneidelloth/JavaFxNodeToSvg/tree/master/output
Some further notes
In addition to the positioning problems that are illustrated by the Chart example above, some further issues have to be considered:
JavaFx provides more css functionality than the SVG standard elements. For example a (rectangular) JavaFx Region can have individual line styles for each of the four border lines. Such a Region can not simply be converted to a SVG rect. Instead, the four border lines of the Region need to be drawn individually. Furthermore, each end of such a border line can have two individual edge radii: a vertical radius and a horizontal radius. In order to convert the "four" border lines to corresponding SVG lines ... it might be necessary to further split the border line: draw two rounded parts and a straight part for each of the four border lines. Therefore, in some cases there might be 12 SVG path elements to draw the border of a single JavaFx Region. In addition, the background fill of the Region can have different radii than the border of the Region. Drawing the background of the Region might requires some more SVG elements. Therefore, even the conversion of a "rectangular Region" can get quite complex.
Please also note that JavaFx nodes might be animated. For example the opacity of a line is 0 at the beginning and fades to another value after a few milliseconds.
FadeTransition ft = new FadeTransition(Duration.millis(250), borderline);
ft.setToValue(0);
ft.play();
Therefore it only makes sense to convert Nodes where animations are disabled or to wait until the Nodes are in a stable state.
I would be very happy if the conversion of JavaFx Charts works one day, so that I can use JavaFx plotting with SVG export in one of my projects.
I decided to stop the development of the converter for the time being and to investigate the plotting and SVG export with JavaScript libraries (d3) instead. If that strategy turns out to be even worse, I might come back to the JavaFxNodeToSvgConverter.
Edit
The plotting with d3.js works very well and I decided not to use JavaFx for the purpose of plotting/svg creation. https://github.com/stefaneidelloth/javafx-d3
There is a simple JavaFX shape to SVG string converter, it will only convert basic shapes without css applied, not arbitrary nodes, but perhaps that might be all you need.
There is an open bug request in JFX JIRA at
https://javafx-jira.kenai.com/browse/RT-38559
(registration required; you can vote for the issue then). It currently says
Consider for a future version.
And is marked for version 9.
The idea is that if you are able to convert the JavaFX Nodes tree structure to a series of Graphics2D orders, then you can use Batik which has a Graphics2D driver.
The thing is that converting the JavaFX tree structure to Graphics2D orders is not as difficult as you might think (even if you process the CSS properties of the Nodes).
Some readers suggested that I should include some code, and not just the link to the library and pictures of it working. It is not so easy to do, because even if it is not so difficult to do, it still has 5000 lines of code.
How to perform the conversion:
you must have a Graphics2D to convert to SVG (for example the Batik SVGGraphics2D class);
iterate through the JavaFX structure;
for each Node in the structure, first convert the current javaFX transforms on this Node to an AffineTransform, and apply the transformation to the Node (you must do it in a Stack to be sure to revert to the initial AffineTransform at the end of the Node);
and for each Node, you have to transform to the appropriate Graphics2D orders.
Note that you don't need to support a lot of Node types, mainly:
Regions (controls are a special type of Region which can have an associated Graphics)
Groups
Shapes (Text, Rectangle, etc...)
ImageView for images
You may also need to take care of the Node Clipping to apply the associated Clipping in the Graphics2D.
Also you will have to take care of the CSS properties of the Node.
For all its worth, the library I used (which apllies this algorithm) is here: http://sourceforge.net/projects/jfxconverter/
The idea is that if you are able to convert the JavaFX Nodes tree structure to a series of Graphics2D orders, then you can use Batik which has a Graphics2D driver.
The thing is that converting the JavaFX tree structure to Graphics2D orders is not as difficult as you might think (even if you process the CSS properties of the Nodes).
You should create a SVGGraphics2D from a new empty SVGDocument, for example:
Document doc = SVGDOMImplementation.getDOMImplementation().createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);
SVGGraphics2D g2D = new SVGGraphics2D(doc);
Then you get the root node of the Scene you want to convert, and for this node, you get the type of the Node, which can be a Shape, Control, Region, ImageView, Group, SubScene, Shape3D
Depending on each node, you can get the characteristics of the node. For example, for a Shape, if its a Line, you can drawthe line in the SVGGraphics2D. For example:
g2D.drawLine((int) line.getStartX(), (int) line.getStartY(), (int) line.getEndX(), (int) line.getEndY());
Note that you will also need to take care of the transforms applied to the node, and the fill or draw of the Node.
Then you iterate on the Node children and do the same thing recursively.
At the end you should be able to save the document in SVG as Batik allows to do it natively.
I am trying to parse an XML file in java, after I have to represent it as a tree using Jframe like this
Trees are generally one of the easier linked constructs to lay out like this, because paths generally don't "merge" or "cross".
You can approach it in a roughly tabular way by traversing the tree "left to right": start at the root, and draw its representation at the top left of the area. Then, traverse its "left" branch one level at a time, drawing those nodes' representations on successively lower "rows", in the same "column" as the root. Then, as you move to the "right"-side nodes, draw that node in the next "column" available to the right on the same level. This will produce a ramp-shaped graph of the tree's structure.
You can add some pre-analysis of the number of levels and nodes at each level, which will allow you to "center" the tree into a rough pyramid shape by knowing the maximum number of levels the graph will require and the number of nodes at each level of that graph. But, that requires traversing the entire graph before you start drawing anything.
As for "arranging" a tree's nodes so they fit in the smallest area without arrows crossing or overlapping, that's a problem with a scope far exceeding the average SO answer.
There are lots of good libraries for visualizing graphs.
Here's a pretty extensive list of options: http://s6ai.livejournal.com/33969.html
Us the standard forms to print the image
http://www.java-forums.org/awt-swing/6763-how-display-image.html
Prefuse could probably create something aesthetically similar. Of course, you could go the primitive route and do the graphics manually. For an XML to graph transform, the TreeMLReader API may be of some use, however you might have to convert the XML to the TreeML format with XSLT first.
I plan on making a multi comparison program. It will compare multiple files by displaying N number of files in a grid where N = X * Y. X and Y are the width and height of the grid elements. Easy enough, I know how to do this pretty much.
The question:
How do and in what way is best to highlight individual characters in each of these grid elements? I plan on highlighting matching text that is found in the same position.
I'd use a JTextPane rather than a JTextArea, and read up on the StyledDocument class. This will give you all sorts of options.
You could use a JTextArea with a Highlighter. See the second example on this page for how.
I'm not sure what you mean by "Highlight the characters", but to bring attention to grid elements, or pairs of grid elements, you could set the background color of the appropriate component.