I know that one can use g2d.setPaint(new TexturePaint(img,rect)) in order to fill a shape with an Image, but the problem is that the shape is tessellated with the image instead of rescaling the single image to the bounding box of the shape in order to fill the whole area.
The latter is what I want to achieve.
For example, if I have an image of 20x20 and I want to fill an Ellipse2D of width = 200 and height = 300, I would like to fill that Ellipse2D with a rescaled version of 200x300 of the image instead of tessellating it with the 20x20 image.
Is there a way to achieve this and hopefully in an efficient way?
Try this:
g2d.setPaint(new TexturePaint(img.getScaledInstance(200, 300, 0),rect));
I never tried this out before but it seems like it should work.
Related
I'm making a little application using Swing and JFreeChart. I have to display an XYLineChart, and I want to draw some filled rectangles over it. I've used the XYShapeAnnotation to draw the rectangles, and I've tried to fill them with Graphics2D, but it doesn't work. I get the rectangle displayed over the chart, but not filled. The code looks like this:
Shape rectangle = new Rectangle2D.Double(0, 0, 7, 1);
g2.fill(rectangle);
XYShapeAnnotation shapeAnnotation = new XYShapeAnnotation(rectangle, new BasicStroke(2.f), Color.BLACK);
shapeAnnotation.setToolTipText("1");
plot.addAnnotation(shapeAnnotation);
I think the problem is that the filled rectangle position is not relative to the chart, but I don't really know how to fix this. I've also wanted to know if it's possible to display the lines in the chart over the rectangles, because I don't find any way to do it.
Use the XYShapeAnnotation constructor that allows you to specify both outlinePaint and fillPaint. You probably want something like this:
XYShapeAnnotation shapeAnnotation = new XYShapeAnnotation(
rectangle, new BasicStroke(2.f), Color.BLACK, Color.BLACK);
As a concrete example based on this answer, the following change produces the result shown:
renderer.addAnnotation(new XYShapeAnnotation(ellipse, stroke, color, color));
To display the lines in the chart over the rectangles, specify the background layer for the annotation, as shown here.
renderer.addAnnotation(new XYShapeAnnotation(
ellipse, stroke, color, color), Layer.BACKGROUND);
I am trying to draw a cushion like rectangle in processing like the pic shown. Is there any tricky way to use "light" to realize this? Does anyone have any idea about it? Thanks!
Pic reference: http://philogb.github.io/blog/2009/02/05/cushion-treemaps/
What you're talking about is called a radial gradient.
There are a number of ways to do it. One way would be to simply draw a bunch of circles. Here is a small example:
size(200, 200);
for(float diameter = 255; diameter > 0; diameter--){
noStroke();
fill(0, 255-diameter, 0);
ellipse(width/2, height/2, diameter, diameter);
}
You'll also have to limit your drawings to a rectangle shape. You might do that using the createGraphics() function to create a buffer, then draw the gradient to the buffer, then draw the buffer to the screen.
You should really break your problem down into smaller steps and take those steps on one at a time. First create a sketch that shows a simple gradient. Then create a sketch that uses a buffer. Get those both working by themselves before you combine them into one sketch. Good luck.
Another common method for implementing a collection of radial gradients of the type shown (a treemap) is:
create or acquire a single fairly high resolution image asset with a (jpeg/png) -- https://www.google.com/search?q=radial+gradient+box&tbm=isch
load the image
as you draw your boxes
optionally use tint() to tint the image green, red, etc. This works best with a grayscale source image.
scale your source image to the correct size for each box using the 5-argument image(img, x1, y1, x2, y2)
I want to rotate the text present on my JComponent to vertical, JComponent also contains border painted in paintComponent method, I don't want to rotate that border, only text.
I already used graphics2D rotate function, but it rotate component border as well, which fails when my component is rectangle.
Please suggest me any approch to rotate only text.
This is currently my JComponent :
And what I want :
Actually it's not duplicate. I already used below code:
Graphics2D g2 = (Graphics2D) g;
g2.rotate(Math.PI / 4, bi.getWidth() / 2, bi.getHeight() / 2);
but problem is that, it also rotate border, I don't want that.
All the solutions given are not working, it rotate the border as well. I don't want to rotate the border, only text.
This is what I get after rotate with some angle:
Remember that the Graphics object has a lot of state in it. This includes the current transformation. Your current code modifies the state and does not restore it to the original situation.
After drawing your image, you should "undo" the rotation. This can be done either by rotating in the other the direction or by creating a new graphics object (g2.create()) specifically to draw the rotated content. If you do the latter, make sure to dispose() the temporary graphics object you created.
I'm making a game where you start by drawing your map. At the moment it works by having an Area instance variable and then when the player clicks/drags the mouse it adds Ellipse2Ds to it. Here's what I mean:
Area land = new Area();
And then in the MouseDragged method
Point2D mouse = e.getPoint();
Ellipse2D ter = new Ellipse2D.Double(mouse.getX() - drawRad, mouse.getY() - drawRad, drawRad*2, drawRad*2);
land.add(new Area(ter));
And then basically the same except land.subtract(new Area(ter)) for erasing.
My problem with this is that after doing a lot of drawing it becomes very slow to draw the Area. the other problem is that I would like to be able to easily get the outline of the drawing, and I haven't found a good way of doing that using Areas. Using area.getPathIterator is not nearly accurate enough.
So I'm wondering what other ways of saving drawings are? I can't just have an array of Ellipses because then erasing wouldn't work.
Thanks!
If you are drawing the same thing over and over it may be worth while to draw it to an image once or load it from a file at start up and then just paint the image rather than painting all the individual shapes.
To load from a file, put your picture file in the same directory as your .java file and load:
BufferedImage img = ImageIO.read(this.getClass().getResource("picture.png"));
To draw on the image once:
BufferedImage img = new BufferedImage(width,height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = img.createGraphics();
In your paintComponent method you draw the image somewhere.
g.drawImage(img, 0, 0, this);
If you have something moving over a background, instead of adding and subtracting the moving item. Just draw the background and then draw the thing that moves, drawing the background will effectively erase the old position with less computation.
I have written a game, and now I would like to learn how to manipulate camera.
My drawing consists of this:
private void render()
{
// CREATE THE GRAPHICS
Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
// MAKE THE PICTURE WHERE WE WILL PAINT EVERYTHING AT ONCE
g.clearRect(0, 0, WIDTH, HEIGHT);
// PAINT ANYTHING WE NEED HERE
render(g);
g.dispose();
// SHOW THE WHOLE IMAGE RATHER THAN PAININT ONE OBJECT AT A TIME
bufferStrategy.show();
}
My BufferStrategy is created like so:
canvas = new Canvas();
// once again I add 1 because java is stupid that's why
canvas.setBounds(0, 0, WIDTH+1, HEIGHT+1);
//canvas.setBounds(bounds);
canvas.setIgnoreRepaint(true);
// SET GRAPHICS DEVICE
canvas.createBufferStrategy(2);
bufferStrategy = canvas.getBufferStrategy();
In the render function I draw my game world with all the platforms where they should be. Now if the game world is bigger than the window size, and I would like to be able to focus on the character and draw the part of the world where character is, how would I do that? So let's say my window is 300 x 300, and my game world is 900 x 900, and my character is located in the middle so that I would like to display the part of the graphics where x is 150 y is 150 and the width and height is 300 x 300.
So how would I go about taking that Graphics2D and shifting it over by specified values? I am very sorry if this question has been answered or is easy, but I am new to this and really would like some help.
Thanks for any help in advance.
I have tried all I know to no avail.
So how would I go about taking that Graphics2D and shifting it over by specified values?
Why must you shift the Graphics2D? Why not create an image that extends beyond the viewport and simply shift the viewport. Then if the user gets close to the edge of the viewport, add an image to the leading edge and lop off a portion on the trailing edge.
This is what affine transformations are for.
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/geom/AffineTransform.html
Shift the character to the center of the screen by applying a shift.
In your paint component, save the current transformation.
Create a new transformation that will then shift the screen to where you would like it to be.
Set Graphics2D to use your new transformation.
Draw the character at the original coordinates
Set Graphics2D to use the original transformation.