drawing layers using java graphics API - java

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.

Related

How to get Alternative row colours using a gridControl component

I'm currently working on redoing the GUI of a project which uses the component GridControl which is an extension of gridView, found here:
http://techpubs.borland.com/books/jbuilder/jbuilder2/jbuilder/reference/borland.jbcl.control.GridControl.html
I'm not allowed to change the components used so I have to find a way to do this with gridControl, however I'm relatively new at programming, so don't really know what I'm doing. I've been asked to get the alternative rows of the table to be grey. I can't find a specific function of the component which caters for this like JTabel seems to have so I was hoping that someone would be able to help. The only one which seems related is .setBackground which seems to only affect the full table.
Thanks very much in advance.
Check out THIS link. It has a mention of this function:
public Color getBackgroundColor(..):callback method automatically invoked by the grid to retrieve the background color for each grid's cell. A programmer can override this method to specify distinct colors for grid's cells.
If the method is not overridden, then rows are colored alternatively with two different colors: one color is defined through ClientSettings.GRID_CELL_BACKGROUND attribute and the other color is slightly different from the first one, defined through getDeltaColor() method.
now, the defaule colour values for ClientSettings.GRID_CELL_BACKGROUND is rgb (238,238,238) which is grey, and for deltaColor is rgb (235,235,235) also grey.
so, the cells should all be grey, unless there's been an override for the function public Color getBackgroundColor(..), something like this:
public Color getBackgroundColor(int row,String attributedName,Object value) {
return new Color(255,255,255); /*for all cells to be White*/
}
In order to make alternate rows grey (assuming the other color white) find the override of the above method and change its body to get your required colours, for eg:
public Color getBackgroundColor(int row,String attributedName,Object value) {
if (row%2==0)
return new Color(255,255,255); /*sets White background for even rows*/
else
return new Color(238,238,238); /*sets Grey background for odd rows*/
}
I'm relatively new at programming, so don't really know what I'm doing hmm.. there are a lot of help/examples available online. you need to learn to search intelligently and follow it up with some background theory to learn on your own.. and you'll survive (for now).

defining regions in bitmap (java)

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.

JUNG edge label and shape

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.

Changing the min and max value of JSlider depanding on condition

I'm creating a Swing GUI in Netbeans. The purpose of this GUI is to open an (buffered)image (in a JLabel as icon) and apply Affine transforms on it. Now there are 4 transforms that I'm doing as follows.
Now, each transform requires two sliders to change the X and Y value, except that of rotate, which will require only one. I did it this way since its much better than having to do four tabs for all 4 types of transforms. Also I want it to be such that , for example, if an image is rotated, the same rotated image can be sheared by selecting shear from the Drop down list.
The problem is (are):
How do i repaint the label icon and apply different transform on the same repainted image?
Also, how do i change the minimum and maximum value of JSlider depanding on the effect selected?
You should store originally loaded BufferedImage, and create its copy - that way you won't "destroy" it.
As for the changing value there are methods setMaximum and setMinimum - add listener to list, as stated in Oracle tutorial and modify the values.
As a concrete example of #Daniel's answer, the article Image processing with Java 2D describes the program ImageDicer. It constructs a TreeMap<String, BufferedImageOp> each of which may be selected from a JComboBox and applied to a BufferedImage.
See also related examples here and here.

Can i create "complex" gradients to achieve shadow on swing(x) components

I'd like to create shadow effects around my JComponent and especially around my JTextField's (JXTextField's since i use SwingX api).
I already know about the DropShadowBorder class from SwingX but it's not exactly what i want to achieve. I decided to do it myself by using rounded rectangle and gradients.
My idea is to create a rounded rectangle, apply a gradient to it and then draw the component on top of this rectangle with a given offset to create the shadow effect.
The problem is that i'm only aware of the GradientPaint class that allow me to specify start and end point of my gradient. Unless i'm wrong, i think i can't achieve this effect which such a gradient, i think i would need a gradient that start at the center and then fade toward the edges. Is there a way to do such a gradient with the actual API or do i need to write it myself?
Thanks.
EDIT: The is to do a text field that looks like:
The shadow is more important on the bottom than on the right and left sides.
There is no easy way to achieve exactly what you want.
To create an exact effect of such shadow you will have to do several things:
Paint a black/gray (color of your shadow) rounded rectanle on a separate image sized to component plus some additional spacing at the sides
Blur that image to create a shadow from the flat rounded rectangle
Render that image under the field by either using your own UI or just replacing field's paintComponent method
Let me explain each step a bit more:
You need a separate image so that the background/component won't get blurred together with the shadow. Plus you cannot apply any filter directly to the Graphics - you need an Image.
You can read a good explanation of how-to-blur here: http://www.jhlabs.com/ip/blurring.html
You need to place (paint) the shadow image before the component itself and that is possible in two ways: paint it on the panel/container that contains the field or replace the field paintComponent method or UI itself.
If you need a radial gradient, there is one: RadialGradientPaint
http://docs.oracle.com/javase/6/docs/api/java/awt/RadialGradientPaint.html
(You specify a center point and a radius here)
BTW, what's wrong with DropShadowBorder? (it is very similar to what you want, and you could always take the source code and modify it)

Categories

Resources