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.
Related
I have a graphics application in JAVA, which is made up of many different shapes (lines, circles, arcs, etc, which are drawn via the Graphics.drawLine(), drawArc()... methods). I would like to create mouse-over events on many, if not all of the drawn objects.
What I was thinking was to store some sort of bitmap with metadata in it, and use that to figure out which object the mouse is over. Is there a way to do this in Java? (looping through all the objects per mouse move doesn't seem viable).
Thanks,
John
Key-color solution
(moved from comment)
Create an off-screen graphics buffer (like BufferedImage), same size as subject image.
Draw all objects into this buffer. Each object with one own color. Depending on object count you can optimize image buffer: For example use 8-bit graphics.
Read resulting image buffer by pixel (example Java - get pixel array from image). Determine pixel color at current mouse position, and map color index (or RGB value) to the source object.
Pros:
The solution is "pixel-accurate": Object boundaries are exact - pixel to pixel.
Easy to solve overlapping objects problem. Just draw them at the desired order.
Object complexity is not limited. Theoretically bitmaps are also possible.
Cons:
To move one object, the complete off-screen buffer must be repainted
Number of objects can be limited when using low-bit image buffer
It depends on your specifications. You do not mention if those shapes are allowed to overlap, to move, how many of them can exist etc.
Solution a) The easiest approach that comes to mind is to implement each shape as a JComponent descedant (e.g. JPanel). So you would have a CirclePanel, an ArcPanel etc that extend JPanel and each one of them paints itself in the same way it is being done now.
Having the shapes as a JComponent allows you to add a MouseListener to each panel that would then handle the mouseEntered(), mouseExited() events.
Solution b) If on the other hand you need to draw all the shapes on a single component's area (as I understand is the case now) then you still do not need to iterate over all the shapes. You just need to introduce an algorithm to categorize the shapes based on their position, to be able to exclude them fast inside your "isMouseOver(Shape s)" test procedure.
For example lets say you divide the area to 2 equal sub-areas left and right (let's call them tiles). When you create each shape you test which tile they intersect to, and you store this information both in the shape and in the corresponding tile.
Now when you need to test if the mouse is over a shape, you decide which tile the mouse is over. This way you only have to check shapes that intersect either the left or the right tile. Assuming that your shapes are distributed uniformly on the screen, you have just rejected 50% of the shapes with one test.
Depending on how many shapes you have, you could use 4 or 8 tiles, or you could even create/delete tiles dynamically (e.g. based on how many objects tend to gather in one area of the screen or not).
I would suggest to try the first solution because it is easier and a cleaner approach. If you decide that it does not fit your needs, you could then go for an approach similar to the second one.
I wish to create a dynamic outline to a Shape (AWT) by adding objects (with draw functions) to appropriate positions on screen along the shape's perimeter. I want a roughly even distance between each object. (An alternative approach to the same affect will be fine.)
How might I acquire the locations for these objects? I know shapes have a path iterator, but I have no idea how to use it.
You might look at a library such as the one described in A Shape Diagram Editor.
If you want to experiment, GraphPanel is a simple object drawing program that features moveable, resizable, colored nodes connected by edges. If the nodes were a little smaller, they'd be moveable points on a Shape that can be iterated as shown here for Polygon.
Addendum: I want a roughly even distance between each object.
The class Node exposes a number of static methods that operate on a List<Node> such as selected. Existing implementations serve, for example, to translate or resize multiple selections as a unit. Functions for Align and Distribute could be implemented similarly. I'd look at LayoutManger as an example for the latter.
Use FlatteningPathIterator to get points for Shape's path.
Also you can use BasicStroke's method
public Shape createStrokedShape(Shape s)
to get Shape's outline with desire width.
This program will have an infinite canvas (ie as long as the user scrolls, it becomes bigger) with a tiled background image, and you can drag and drop blocks and draw arrows between blocks. Obviously I won't use a layout manager for placing blocks and lines, since they will be absolutely positioned (any link on this, possibily with a snapping feature?). The problem arises with blocks and lines. Basically I'll have two options:
Using a simple layout for each building block. This is the simplest and clearest approach, but does it scale well when you have hundreds of objects? This may not be uncommon, just imagine a database with 50 tables and dozens of relationships
Drawing everything with primitives (rectangles, bitmaps, etc). This seems too complicated (especially things like text padding and alignment) but may be more scalable if you have a large number of objects. Also there won't be any event handler
Please give me some hints based on your experience. I have never drawn with Java before - well I did something rather basic with PHP and on Android. Here is a simple preview
DISCLAIMER
You are not forced to answer this. I am looking for someone who did something like this before, what's the use of writing I can check an open source project? Do you know how difficult it is to understand someone else's code? I'm talking about implementations details here... Moreover, there is no guarantee that he's right. This project is just for study and will be funny, I don't want to sell it or anything and I don't need your authorization to start it.
Measuring and drawing text isn't such a pain, since java has built in classes for doing that. you may want to take a look at the 2D Text Tutorial for more information. In fact, I did some text drawing computations with a different graphics engine which is much more primitive, and in the end it was rather easy (at least for the single-line drawing, for going multiline see the previous link).
For the infinite canvas problem, that's also something I always wanted to be able to do. A quick search here at stackoverflow gives this which sounds nice, althought I'm not sure I like it. What you can do, is use the way GIMP has a scroll area that can extend as you move - catch the click of the middle mouse button for marking the initial intention to move the viewport. Then, when the mouse is dragged (while the button is clicked) move the viewport of the jscrollpane by the offset between the initial click and the current position. If we moved outside the bounds of the canvas, then you should simply enlarge the canvas.
In case you are still afraid of some of the manual drawing, you can actually have a JPanel as your canvas, with a fixed layout. Then you can override it's paint method for drawing the connectors, while having child components (such as buttongs and text areas) for other interaction (and each component may override it's own paint method in case it wants to have a custom-painted rect).
In my last drawing test in java, I made an application for drawing bezier curves (which are basically curves made of several control points). It was a JPanel with overidden paint method that drew the curve itself, and buttons with custom painting placed on the location of the control points. Clicking on the control point actually was clicking on a button, so it was easy to detect the matching control point (since each button had one control point associated with it). This is bad in terms of efficiency (manual hit detection may be faster) but it was easy in terms of programming.
Anyway, This idea can be extended by having one child JPanel for each class rectangle - this will provide easy click detection and custom painting, while the parent will draw the connectors.
So in short - go for nested JPanels with custom drawing, so that you can also place "on-canvas" widgets (and use real swing widgets such as text labels to do some ready drawing) while also having custom drawing (by overriding the paint method of the panels). Note that the con of this method is that some swing look-and-feel's may interfere with your drawing, so may need to mess a bit with that (as far as I remember, the metal and nimbus look-and-feel's were ok, and they are both cross-platform).
I'm doing a simulator project that tests several A* based algorithms and show how they work and their results.
The algorithms are all multi-agent and run on a grid map environment.
I used a JPanel for the grid which contains a two dimensional array of Cells where each Cell is a custom class that extends the Component class and use the paint method to draw the stuff i need inside each cell.
For the drawing inside the cell I use method such as Graphics.fillRect or Graphics.drawImage to fill each cell with a certain color or icon).
I'm using a special Icon for the start position and goal position of every agent on the grid.
My problem is that I want to be able to draw more than one item on the same cell.
For example I want to be able to show the path of one of the agents by painting the cells along the path in a special color and the path might go through a start position of a different agent, so I want to be able to fill the cell with the color and have an icon drawn on top.
In another example I want to be able to mix two colors using alpha blending.
If I use graphics.fillRect() with one color that has alpha and then use it again with a different color with alpha value it won't work since the last fillRect() will override the first call.
Is there a way I can achieve what I need using the same Cell Component I created or should I implement it differently?
Perhaps there is a better solution to this problem?
I would really appreciate any advice on this matter.
If you draw a rectangle with 50% alpha and then draw another one, the second one will override it instead of blending with it.
It depends on the mode. This convenient utility shows the result of blending different colors using the modes defined in AlphaComposite. The available source code may offer some insights for your project.
Addendum:
the stuff I was trying to composite was on the same Component.
The example cited does exactly this, as does this example. If AlphaComposite does not meet your requirements, you can always vary hue, saturation and/or value; this example composes a color table based on saturation.
I am looking for ways to zoom in a Java Swing application. That means that I would like to resize all components in a given JPanel by a given factor as if I would take an screenshot of the UI and just applied an "Image scale" operation. The font size as well as the size of checkboxes, textboxes, cursors etc. has to be adjusted.
It is possible to scale a component by applying transforms to a graphics object:
protected Graphics getComponentGraphics(Graphics g) {
Graphics2D g2d=(Graphics2D)g;
g2d.scale(2, 2);
return super.getComponentGraphics(g2d);
}
That works as long as you don't care about self-updating components. If you have a textbox in your application this approach ceases to work since the textbox updates itself every second to show the (blinking) cursor. And since it doesn't use the modified graphics object this time the component appears at the old location. Is there a possibility to change a components graphics object permanently? There is also a problem with the mouse click event handlers.
The other possibility would be to resize all child components of the JPanel (setPreferredSize) to a new size. That doesn't work for checkboxes since the displayed picture of the checkbox doesn't change its size.
I also thought of programming my own layout manager but I don't think that this will work since layout managers only change the position (and size) of objects but are not able to zoom into checkboxes (see previous paragraph). Or am I wrong with this hypothesis?
Do you have any ideas how one could achieve a zoomable Swing GUI without programming custom components? I looked for rotatable user interfaces because the problem seems familiar but I also didn't find any satisfying solution to this problem.
Thanks for your help,
Chris
You could give a try to the JXLayer library.
There are several tools in it, which could help you to make a zoom. Check the examples shown here. I would recommend you to read more about the TransformUI, from this library. From the example, it seems like it could help solving your problem.
Scaling the view is easy enough; transforming mouse coordinates is only slightly more difficult. Here's an elementary example. I'd keep JComponents out, although it might make sense to develop an analogous ScaledComponent that knows about the geometry. That's where #Gnoupi's suggestion of using a library comes in.
hey you can try this if you want to zoom a image like any other image viewer the use a JPanel draw an image using drawImage() method now create a button and when you click the button increase the size of the panel on the frame it appears as if the image is being viewed in Zoom
You might find Piccolo2D.java API useful: http://code.google.com/p/piccolo2d/
It is very simple.
It touts in particular its smooth zooming. You essentially make a "canvas" that can contain various elements, and can then zoom by just holding right-click and panning the mouse back and forth.
I worked on a team that used it to create this: http://sourceforge.net/apps/mediawiki/guitar/index.php?title=WebGuitar#EFG.2FGUI_Visualizer
The nodes you see there are clickable links themselves.
Since Java 9, there are VM arguments (actually meant to be used for high dpi scaling) that can render a application with a higher scaling factor:
java -Dsun.java2d.uiScale=2.0 -jar MyApplication.jar
Or:
java -Dsun.java2d.win.uiScaleX=2.0 -Dsun.java2d.win.uiScaleY=2.0 -jar MyApplication.jar