How to use graphics2D from BufferedImage object, with "getGraphics()" method? - java

I'm trying to make a 2D game, but I can't figure out why my graphics from precedent frames are still there. The effect is when moving a rectangle on x with 1 pixel / frame, I get a long bar drawn on my screen.
In the class body I declared the objects beneath like that:
private int x, y;
private BufferedImage image;
private Graphics2D g;
This is how I'm initializing:
x = 10, y = 25;
image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_BGR);
g = (Graphics2D) image.getGraphics();
r = new Rectangle(x, y, 10, 10);
I have method where I draw graphics:
Graphics g2 = this.getGraphics();
g2.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.draw(r);
g2.dispose();
I also have a tick method where I move the rectangle:
x++;
The class extends Canvas and implements Runnable for the game loop and I use a JFrame object .
This is the result of 10x10 rectangle movement:
capture

Related

Rotating Rectangle with Color

I am starting to build a simulation in java and using a rectangle as a plane. But as I rotate the rectangle its foreground color won't stick to it. Can someone help me?
Screenshot:Here
Source Code:
private void drawTransform(Graphics g, double modifier) {
Rectangle rect = new Rectangle(130,350, 350, 15);
AffineTransform at = new AffineTransform();
at.rotate(-Math.toRadians(modifier), rect.getX(), rect.getY() + rect.height);
// Transform the shape and draw it to screen
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
g2d.fillRect(130, 350, 350, 15);
g2d.draw(at.createTransformedShape(rect));
}
Use fill instead of draw:
g2d.fill(at.createTransformedShape(rect));

How can I paint a custom circular JComponent without an "invisible box" around it?

I'm writing a JApplet that displays a diagram with numbers in circles and lines connecting the circles. I've created a class that extends JComponent to act as the circles. I overrode the paintComponent() method to draw a circle with the numbers inside, and I placed these circles on my applet, on which I drew the lines in the paint() method.
However, if the lines hit the circle at an angle, they cut out early, before the circle, at the square that outlines the entire JComponent, even though the background should be transparent. this forms an "invisible box" around the circle.
I've prepared a smaller program to demonstrate the issue:
And here is the code for that example:
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.*;
public class Circle extends JApplet {
private static final long serialVersionUID = 1L;
myCircle myC = new myCircle(10, 215, 215); // custom circle
Container c;
public void init() {
setSize(500, 500);
c = getContentPane();
c.setLayout(null);
c.setBackground(Color.lightGray);
c.add(myC);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
//draw lines
g2d.draw(new Line2D.Double(0f, 0f, 500f, 500f));
g2d.draw(new Line2D.Double(0f, 500f, 500f, 0f));
g2d.draw(new Line2D.Double(0f, 250f, 500f, 250f));
g2d.draw(new Line2D.Double(250f, 0f, 250f, 500f));
g2d.draw(new Line2D.Double(150f, 0f, 350f, 500f));
myC.repaint(); // put the circle on top
}
public class myCircle extends JComponent {
private static final long serialVersionUID = 1L;
int number; // number to display
public myCircle(int num, int x, int y) {
this.number = num;
this.setLocation(x, y);
this.setSize(75, 75);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
g2d.setColor(Color.white);
g2d.fill(new Ellipse2D.Float(1f, 1f, 70f, 70f));
g2d.setColor(Color.black);
g2d.draw(new Ellipse2D.Float(1f, 1f, 70f, 70f));
g2d.drawString(Integer.toString(number), 15f, 20f);
}
}
}
I wouldn't use a component to represent the circle shape alone. Instead, just paint it all on one JPanel (I'm using a JFrame instead of an applet):
public class Circle extends JPanel {
int number = 10;
float size = 500f;
float rad = 70f;
float stringLocX = 15f, stringLocy = 20f;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.LIGHT_GRAY);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
g2d.setColor(Color.BLACK);
g2d.draw(new Line2D.Double(0f, 0f, size, size));
g2d.draw(new Line2D.Double(0f, size, size, 0f));
g2d.draw(new Line2D.Double(0f, size / 2, size, size / 2));
g2d.draw(new Line2D.Double(size / 2, 0f, size / 2, size));
g2d.draw(new Line2D.Double(150f, 0f, 350f, 500f));
Ellipse2D.Float circle = new Ellipse2D.Float((size - rad) / 2, (size - rad) / 2, rad, rad);
g2d.setColor(Color.WHITE);
g2d.fill(circle);
g2d.setColor(Color.BLACK);
g2d.draw(circle);
g2d.drawString(Integer.toString(number), (size - rad) / 2 + stringLocX,
(size - rad) / 2 + stringLocy);
}
#Override
public Dimension getPreferredSize() {
return new Dimension((int) size, (int) size);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.add(new Circle());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
});
}
}
Depending on how many circles you have and what data they must contain, you can just keep a list of those numbers, then iterate over the list in painComponent and draw them.
Notes:
Don't use null layout.
Better to keep the hard coded numbers as fields so you can change them more easily, possibly make them final.
You need to look at the length of the line being drawn. From the edge of your figure to the circle is longer at an angle than at the sides. Recall for a triangle with 45 degrees, 45 degree, and 90 degree angles the ratio of the length of the sides is 1:1:sqrt(2)

How to remove original object after rotation in java graphics2D?

Specifically, I am trying to display only the rotated object. I have a drawn rectangle and I rotate it.
How to I display only the rotated rectangle and dispose of the old one?
EDITED:
The following is the code to rotate my rectangle:
private void rotateRectangle(Graphics g, Rectangle rect, Color c){
Graphics2D g2d = (Graphics2D) g.create();
x = rect.x;
y = rect.y;
g2d.setColor(c);
g2d.rotate(Math.PI/6, PANEL_WIDTH/2,PANEL_HEIGHT/2);
g2d.drawRect(PANEL_WIDTH/2-x/2, PANEL_HEIGHT/2-y/2, x, y);
}
And this is the paintComponent where I call it from:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setStroke(new BasicStroke(3));
//these are declared before
rect.x = x;
rect.y = y;
if(rotateClicked){
rotateRectangle(g2d,rect,squareColor);
rotateClicked = false;
}
drawRectangle(g2d, rect, squareColor);
getArea(x,y);
}
If custom rendering shapes with a Graphics object by overwriting paintComponent(Graphics g), ensure you use super.paintComponent(g) as the first line to clear the drawing area
From there draw your Rectangle/rotated Rectangle
Without using super.paintComponent(g), your previous drawings (the unrotated Rectangle) will remain visible
EDIT
With the update of source code: you are drawing both the new and the old rectangle because your if statement does not have an else clause
Try inserting an else clause so that it will draw one rectangle or the other, currently it maybe draws a rotated rectangle and then draws the unrotated rectangle
if(rotateClicked)
{
rotateRectangle(g2d,rect,squareColor);
rotateClicked = false;
}
else
drawRectangle(g2d, rect, squareColor);
You may or may not want a rotateClicked = true in the else so it will flip back and forth between rotated and unrotated

Creating images with a java

Hello) Help solve the problem:
We need to create a green square image and display it.
I could draw a square, but I need to create it using java.
Please help me to do this)
That's what I tried to do:
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class Game extends Canvas {
private static final long serialVersionUID = 1L;
private static final int WIDTH = 400;
private static final int HEIGHT = 400;
#Override
public void paint(Graphics g) {
super.paint(g);
int w = 10;
int h = 10;
int type = BufferedImage.TYPE_INT_ARGB;
BufferedImage image = new BufferedImage(w, h, type);
int color = 257; // RGBA value, each component in a byte
for (int x = 1; x < w; x++) {
for (int y = 1; y < h; y++) {
image.setRGB(x, y, color);
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(WIDTH, HEIGHT);
frame.add(new Game());
frame.setVisible(true);
}
}
But nothing is displayed (
Let me remind the goal - to create a picture in the form of green squares, help to make it)
The simplest approach would be to simply use the graphics API...
#Override
public void paint(Graphics g) {
super.paint(g);
int w = 10;
int h = 10;
g.setColor(Color.GREEN);
g.fillRect(0, 0, width, height);
}
But something tells me this isn't what you want, but it does form the basics for what you need to achieve your result.
Start by making image a instance field...
private BufferedImage image;
Then you need to create the image...
int type = BufferedImage.TYPE_INT_ARGB;
image = new BufferedImage(w, h, type);
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0, 0, w, h);
g2d.dispoe();
Then in you paint method, you need to draw the image...
g.drawImage(image, x, y, this);
Take a look at the 2D Graphics trail for mor details
You must use Graphics.drawRect() and Graphics.fillRect():
http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#drawRect%28int,%20int,%20int,%20int%29
http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#fillRect%28int,%20int,%20int,%20int%29
if you want to create an Image with rectangle containing it, first create the image, draw on it using it's graphics. I am writing code snippets for you:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
g.setColor(Color.blue);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
This will produce an image with Blue rectangle.

Inner-Transparent Selection Window in Java using GlassPane

I am trying to achieve the following
http://www.qksnap.com/i/3hunq/4ld0v/screenshot.png
I am currently able to draw rectangles successfully on a semi-transparent glasspane background using the following code:
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.black); // black background
g.fillRect(0, 0, frame.getWidth(), frame.getHeight());
g2.setColor(Color.GREEN.darker());
if (getRect() != null && isDrawing()) {
g2.draw(getRect()); // draw our rectangle (simple Rectangle class)
}
g2.dispose();
}
Which works great, however, I would love to have the area within the rectangle be completely transparent while the outside was still darken much like the screenshot above.
Any ideas?
..have the area within the rectangle be completely transparent while the outside was still darken much like the screenshot above.
Create a Rectangle (componentRect) that is the size of the component being painted.
Create an Area (componentArea) of that shape (new Area(componentRect)).
Create an Area (selectionArea) of the selectionRectangle.
Call componentArea.subtract(selectionArea) to remove the selected part.
Call Graphics.setClip(componentArea)
Paint the semi-transparent color.
(Clear the clipping area if more paint operations are required).
As Andrew has suggested (just beat me while I was finishing off my example)
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g.setColor(Color.black); // black background
Area area = new Area();
// This is the area that will filled...
area.add(new Area(new Rectangle2D.Float(0, 0, getWidth(), getHeight())));
g2.setColor(Color.GREEN.darker());
int width = getWidth() - 1;
int height = getHeight() - 1;
int openWidth = 200;
int openHeight = 200;
int x = (width - openWidth) / 2;
int y = (height - openHeight) / 2;
// This is the area that will be uneffected
area.subtract(new Area(new Rectangle2D.Float(x, y, openWidth, openHeight)));
// Set up a AlphaComposite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2.fill(area);
g2.dispose();
}

Categories