Drawing lines in loop - java

How to draw horizontal lines between those four lines and have same space between them like on image.
DrawPanel.java:
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int pieces = 5;
g.drawLine(0, height/2, width/2, 0);
g.drawLine(width/2, 0, width, height/2);
g.drawLine(0, height, width/2, height/2);
g.drawLine(width/2, height/2, width, height);
for (int i = 0; i < pieces; i++) {
int y = height * i/pieces;
if (y > height / 2)
g.drawLine(0, y, width / 2, y);
}
}
}
DrawPanelTest.java:
import javax.swing.JFrame;
public class DrawPanelTest {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(1280,720);
application.setVisible(true);
}
}
What i've got so far:
how to make those lines in bottom left corner fit between lines not in the for loop (something like show above)?

You could draw the bottom triangle to overwrite the lines, or you can calculate the distance away from the center that you need to start/end drawing the lines.
Since we know the height and width of the triangle (half the pyramid) you can calculate the top angle. Once you know the top angle, you can use that to calculate the width of the bottom side at each iteration of the line.
public class PyramidLinesTest {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(1280,720);
application.setVisible(true);
}
static class DrawPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int pieces = 5;
drawPyramids(g, width, height);
drawLines(g, width, height, pieces);
}
private void drawPyramids(Graphics g, int width, int height) {
g.drawLine(0, height/2, width/2, 0);
g.drawLine(width/2, 0, width, height/2);
g.drawLine(0, height, width/2, height/2);
g.drawLine(width/2, height/2, width, height);
}
private void drawLines(Graphics g, int width, int height, int pieces) {
// Determine the size of the side and bottom (adjacent and opposite)
double halfY = height / 2;
double halfW = width / 2;
// Tan = O / A
// Tan = halfW / halfY
double tanTheta = halfW / halfY;
double theta = Math.atan(tanTheta); // Radians Math.toDegrees()
double dist = halfY / pieces;
for (int i = 0; i < pieces; i++) {
// Start at halfY and move down by I distance
int y = (int) (halfY + (i * dist));
// Calculate the distance away from halfX using theta
// tan(theta) = O / A
// O = tan(theta) * A
int fromHalfW = (int) (Math.tan(theta) * (i * dist));
// Draw the lines accordingly
g.drawLine(0, y, (int) (halfW - fromHalfW), y);
g.drawLine((int) (halfW + fromHalfW), y, width, y);
}
}
}
}

Related

Rotate an image by 90 180 and 270 degrees when width and height can be any size

I am having trouble writing a function that takes a BufferedImage and a Cardinal Direction and rotates the image accordingly. I have looked on many threads on stack and tried implementing myself while going over the docs for some time now and the best I'm getting is that the image seems to be rotating, however the last pixel is correct and the rest are set white or transparent not sure.
Here is where I have got so far:
private BufferedImage rotateImg(BufferedImage image, String direction){
int width = image.getWidth();
int height = image.getHeight();
BufferedImage rotated = null;
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
switch(direction){
case "SOUTH":
rotated = new BufferedImage(width, height, image.getType());
rotated.setRGB((width - 1) - x, (height - 1) - y, image.getRGB(x,y));
break;
case "WEST":
//ROTATE LEFT
rotated = new BufferedImage(height, width, image.getType());
rotated.setRGB(y, (width - 1) - x, image.getRGB(x,y));
break;
case "EAST":
//ROTATE RIGHT
rotated = new BufferedImage(height, width, image.getType());
rotated.setRGB((height - 1) - y, x, image.getRGB(x,y));
break;
default:
return image;
}
}
}
return rotated;
}
Below there are four images but as they are so small its really hard to see them. A bit of browser zoom will show them.
When you get close the cyan pixel is staying where it should for the rotation. Its just im loosing the rest of the image.
I don't know if there's a fixed requirement to rotate this image by individual pixels or not, but I'm far to simple minded to even be bothered trying.
Instead, I'd (personally) drop straight into the Graphics API itself, for example...
public static BufferedImage rotateBy(BufferedImage source, double degrees) {
// The size of the original image
int w = source.getWidth();
int h = source.getHeight();
// The angel of the rotation in radians
double rads = Math.toRadians(degrees);
// Some nice math which demonstrates I have no idea what I'm talking about
// Okay, this calculates the amount of space the image will need in
// order not be clipped when it's rotated
double sin = Math.abs(Math.sin(rads));
double cos = Math.abs(Math.cos(rads));
int newWidth = (int) Math.floor(w * cos + h * sin);
int newHeight = (int) Math.floor(h * cos + w * sin);
// A new image, into which the original can be painted
BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = rotated.createGraphics();
// The transformation which will be used to actually rotate the image
// The translation, actually makes sure that the image is positioned onto
// the viewable area of the image
AffineTransform at = new AffineTransform();
at.translate((newWidth - w) / 2, (newHeight - h) / 2);
// And we rotate about the center of the image...
int x = w / 2;
int y = h / 2;
at.rotate(rads, x, y);
g2d.setTransform(at);
// And we paint the original image onto the new image
g2d.drawImage(source, 0, 0, null);
g2d.dispose();
return rotated;
}
This method will create a new image large enough to fit the rotated version of the source image.
You could then drop it into a helper class, add some helper methods and have a basic worker (and re-usable) solution, for example...
public class ImageUtilities {
public enum Direction {
NORTH, SOUTH, EAST, WEST
}
public static BufferedImage rotateBy(BufferedImage source, Direction direction) {
switch (direction) {
case NORTH:
return source;
case SOUTH:
return rotateBy(source, 180);
case EAST:
return rotateBy(source, 90);
case WEST:
return rotateBy(source, -90);
}
return null;
}
public static BufferedImage rotateBy(BufferedImage source, double degrees) {
// The size of the original image
int w = source.getWidth();
int h = source.getHeight();
// The angel of the rotation in radians
double rads = Math.toRadians(degrees);
// Some nice math which demonstrates I have no idea what I'm talking about
// Okay, this calculates the amount of space the image will need in
// order not be clipped when it's rotated
double sin = Math.abs(Math.sin(rads));
double cos = Math.abs(Math.cos(rads));
int newWidth = (int) Math.floor(w * cos + h * sin);
int newHeight = (int) Math.floor(h * cos + w * sin);
// A new image, into which the original can be painted
BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = rotated.createGraphics();
// The transformation which will be used to actually rotate the image
// The translation, actually makes sure that the image is positioned onto
// the viewable area of the image
AffineTransform at = new AffineTransform();
at.translate((newWidth - w) / 2, (newHeight - h) / 2);
// And we rotate about the center of the image...
int x = w / 2;
int y = h / 2;
at.rotate(rads, x, y);
g2d.setTransform(at);
// And we paint the original image onto the new image
g2d.drawImage(source, 0, 0, null);
g2d.dispose();
return rotated;
}
}
(although I might use RIGHT, LEFT, UPSIDE or something, but that's me :P)
Runnable example...
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage masterImage;
private BufferedImage northImage;
private BufferedImage southImage;
private BufferedImage eastImage;
private BufferedImage westImage;
public TestPane() throws IOException {
masterImage = ImageIO.read(new File("/absolute/path/to/your/image.png"));
northImage = ImageUtilities.rotateBy(masterImage, ImageUtilities.Direction.NORTH);
southImage = ImageUtilities.rotateBy(masterImage, ImageUtilities.Direction.SOUTH);
eastImage = ImageUtilities.rotateBy(masterImage, ImageUtilities.Direction.EAST);
westImage = ImageUtilities.rotateBy(masterImage, ImageUtilities.Direction.WEST);
setLayout(new GridLayout(3, 3));
add(new JLabel(""));
add(new JLabel(new ImageIcon(northImage)));
add(new JLabel(""));
add(new JLabel(new ImageIcon(westImage)));
add(new JLabel(new ImageIcon(masterImage)));
add(new JLabel(new ImageIcon(eastImage)));
add(new JLabel(""));
add(new JLabel(new ImageIcon(southImage)));
add(new JLabel(""));
}
}
public class ImageUtilities {
public enum Direction {
NORTH, SOUTH, EAST, WEST
}
public static BufferedImage rotateBy(BufferedImage source, Direction direction) {
switch (direction) {
case NORTH:
return source;
case SOUTH:
return rotateBy(source, 180);
case EAST:
return rotateBy(source, 90);
case WEST:
return rotateBy(source, -90);
}
return null;
}
public static BufferedImage rotateBy(BufferedImage source, double degrees) {
// The size of the original image
int w = source.getWidth();
int h = source.getHeight();
// The angel of the rotation in radians
double rads = Math.toRadians(degrees);
// Some nice math which demonstrates I have no idea what I'm talking about
// Okay, this calculates the amount of space the image will need in
// order not be clipped when it's rotated
double sin = Math.abs(Math.sin(rads));
double cos = Math.abs(Math.cos(rads));
int newWidth = (int) Math.floor(w * cos + h * sin);
int newHeight = (int) Math.floor(h * cos + w * sin);
// A new image, into which the original can be painted
BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = rotated.createGraphics();
// The transformation which will be used to actually rotate the image
// The translation, actually makes sure that the image is positioned onto
// the viewable area of the image
AffineTransform at = new AffineTransform();
at.translate((newWidth - w) / 2, (newHeight - h) / 2);
// And we rotate about the center of the image...
int x = w / 2;
int y = h / 2;
at.rotate(rads, x, y);
g2d.setTransform(at);
// And we paint the original image onto the new image
g2d.drawImage(source, 0, 0, null);
g2d.dispose();
return rotated;
}
}
}
But the image is rotating in the wrong direction!
Okay, so change the angle of rotation to meet your needs!
As commented, the actual code is creating a new image for each pixel, that is, inside the inner loop. Only the image created in the last iteration is returned, containing just the last pixel.
The following code creates one single image - I tried to maintain the original code as much as possible:
private static BufferedImage rotateImg(BufferedImage image, String direction){
int width = image.getWidth();
int height = image.getHeight();
BufferedImage rotated = null;
switch(direction){
case "SOUTH":
rotated = new BufferedImage(width, height, image.getType());
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB((width - 1) - x, (height - 1) - y, image.getRGB(x,y));
}
}
break;
case "WEST":
//ROTATE LEFT
rotated = new BufferedImage(height, width, image.getType());
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB(y, (width - 1) - x, image.getRGB(x,y));
}
}
break;
case "EAST":
//ROTATE RIGHT
rotated = new BufferedImage(height, width, image.getType());
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB((height - 1) - y, x, image.getRGB(x,y));
}
}
break;
default:
return image;
}
return rotated;
}
To avoid having the loop code repeated (easier to maintain) we can use two functions - calX and calcY:
private static BufferedImage rotateImg(BufferedImage image, String direction){
int width = image.getWidth();
int height = image.getHeight();
BufferedImage rotated = null;
IntBinaryOperator calcX;
IntBinaryOperator calcY;
switch(direction){
case "SOUTH":
rotated = new BufferedImage(width, height, image.getType());
calcX = (x, y) -> (width - 1) - x;
calcY = (x, y) -> (height - 1) - y;
break;
case "WEST":
//ROTATE LEFT
rotated = new BufferedImage(height, width, image.getType());
calcX = (x, y) -> y;
calcY = (x, y) -> (width - 1) - x;
break;
case "EAST":
//ROTATE RIGHT
rotated = new BufferedImage(height, width, image.getType());
calcX = (x, y) -> (height - 1) - y;
calcY = (x, y) -> x;
break;
default:
return image;
}
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB(calcX.applyAsInt(x, y), calcY.applyAsInt(x, y), image.getRGB(x,y));
}
}
return rotated;
}

Rotating a triangle around its axis

I have got a circle and a triangle inside. I need this figure to rotate around its axis and each time it rotates on a certain angle, it should be painted, overall to get something kind of 'ornament'(on the screen below). I've been trying with Graphics2D, but it went bad. How can I do that?
Code:
import org.omg.CORBA.TIMEOUT;
import javax.swing.*;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
public class Main extends JPanel {
public static void main(String[] args) {
JFrame frame = new JFrame("Laboratorna 1");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(new Main());
frame.setSize(1200, 800);
frame.setVisible(true);
}
public void paintComponent(Graphics g){
int num_2 = 8;
int bigOval_h = 300, bigOval_w = 300;
g.setColor(Color.BLUE);
g.drawOval(0+500, 0, bigOval_h, bigOval_w);
g.drawLine(150+500, 0, 20+500, 225);
g.drawLine(150+500, 0, 280+500, 225);
g.drawLine(20+500, 225,280+500, 225);
g.setColor(Color.RED);
}
}
The trick is to perform an affine transform for each angle. In addition you have to define the pivot point for each transform which equals the center of the circle. The following modifications of the paintComponent-method should possibly do the job.
public void paintComponent(Graphics g){
int num_2 = 8;
int bigOval_h = 300, bigOval_w = 300;
g.setColor(Color.BLUE);
g.drawOval(0 + 500, 0, bigOval_h, bigOval_w);
// REMOVE -------------------------------------------
// g.drawLine(150+500, 0, 20+500, 225);
// g.drawLine(150+500, 0, 280+500, 225);
// g.drawLine(20+500, 225,280+500, 225);
// REMOVE -------------------------------------------
g.setColor(Color.RED);
// ADD -------------------------------------------------------------------
// Create, transform and draw the lines
Line2D lin1 = new Line2D.Float(150f + 500f, 0f, 20f + 500f, 225f);
Line2D lin2 = new Line2D.Float(150f + 500f, 0f, 280f + 500f, 225f);
Line2D lin3 = new Line2D.Float(20f + 500f, 225f, 280f + 500f, 225f);
double pivotX = 500.0 + bigOval_w / 2.0; // center of the circle (x)
double pivotY = 0.0 + bigOval_h / 2.0; // center of the circle (y)
for (int i = 0; i < num_2; i++) {
AffineTransform affineTransform = AffineTransform.getRotateInstance(Math.toRadians(360.0 / num_2 * i), pivotX, pivotY);
((Graphics2D)g).draw(affineTransform.createTransformedShape(lin1));
((Graphics2D)g).draw(affineTransform.createTransformedShape(lin2));
((Graphics2D)g).draw(affineTransform.createTransformedShape(lin3));
}
// ADD -------------------------------------------------------------------
}
The output is:
One way to define a polygon is radius, rotation, and number of sides. A triangle is a 3 sided polygon. So a triangle class can simply save radius and rotation and then compute the three vertices of the polygon for drawing around a center point.
public class Triangle {
private final int radius;
private final double rotation;
public Triangle(int radius, double rotation) {
this.radius = radius;
this.rotation = rotation;
}
public void paintComponent(Graphics2D g, Point center) {
int[] xVertices = new int[3];
int[] yVertices = new int[3];
xVertices[0] = (int) (center.getX() - (Math.cos(rotation) * radius));
yVertices[0] = (int) (center.getY() - (Math.sin(rotation) * radius));
xVertices[1] = (int) (center.getX() - (Math.cos(Math.PI * 0.66667 + rotation) * radius));
yVertices[1] = (int) (center.getY() - (Math.sin(Math.PI * 0.66667 + rotation) * radius));
xVertices[2] = (int) (center.getX() - (Math.cos(Math.PI * 1.33333 + rotation) * radius));
yVertices[2] = (int) (center.getY() - (Math.sin(Math.PI * 1.33333 + rotation) * radius));
Polygon polygon = new Polygon(xVertices, yVertices, 3);
g.setColor(Color.RED);
g.drawPolygon(polygon);
}
}
This would give two triangles rotated PI radians.
Triangle t = new Triangle(100, 0.0);
t.paintComponent((Graphics2D)g, new Point(250,250));
Triangle t2 = new Triangle(100, Math.PI);
t2.paintComponent((Graphics2D)g, new Point(250,250));

Drawing graphics in Java

I am trying to draw a circle in side a square and having multiple square circles in java. I am almost done but my output isn't coming out as I wanted to. The picture is what I am trying to do but it's not working out.
Here is my code:
a.awt.*;
public class SquaredCircles {
public static final int WIDTH=400;
public static final int HEIGHT=400;
public static void main (String[] args) {
DrawingPanel panel = new DrawingPanel(WIDTH,HEIGHT);
Graphics g = panel.getGraphics ();
panel.setBackground(new Color(0, 255, 255 ) );
int x = 0;
int y = 0;
int size = 100;
int rows = 5;
int numSquares = 1;
drawManySquares ( g, numSquares, x, y, size, rows );
x = 10;
y = 120;
size = 24;
rows = 4;
numSquares = 4;
drawManySquares( g, numSquares, x, y, size, rows );
x = 150;
y = 20;
size = 40;
rows = 6;
numSquares = 5;
drawManySquares( g, numSquares, x, y, size, rows );
x = 130;
y = 275;
size = 36;
rows = 3;
numSquares = 3;
drawManySquares( g, numSquares, x, y, size, rows );
}
public static void drawManySquares( Graphics g, int numSquares, int x, int y, int size, int rows ) {
for ( int i = 0; i < numSquares; i++ ) {
for ( int j = 0; j < numSquares; j++ ) {
drawOneSquare( g, x + i size, y + j size, size, rows );
}
}
}
public static void drawOneSquare( Graphics g, int x, int y, int size, int rows ) {
g.setColor ( Color.GREEN);
g.fillRect(x , y, size, size);
g.setColor ( Color.YELLOW);
g.fillOval ( x, y, size, size);
g.setColor ( Color.BLACK);
g.drawLine(size / 2, x, size / 2, size);
g.setColor ( Color.BLACK);
g.drawLine(x, size / 2, size, size / 2);
for (int i = 0; i <= rows; i = i + 1) {
g.setColor ( Color.BLACK);
g.drawOval(x + (i* (size/rows)), y+ (i*(size/rows)), size - (i*(size/rows +10 )) , size - (i*(size/rows +10)));
}
}
}
Start by having a look at Painting in AWT and Swing and Performing Custom Painting to see how painting should be done in Swing
Break down your problem into manageable chunks. The first thing you need to be able to do is paint a circle of a given size at a specific location, something like
public void paintCircleAt(Graphics2D g2d, int radius, int centerX, int centerY, Color stroke, Color fill) {
Ellipse2D.Double circle = new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2);
g2d.setColor(fill);
g2d.fill(circle);
g2d.setColor(stroke);
g2d.draw(circle);
}
So, this allows you to paint a circle of a given radius around the center points of x/y filled and outlined with the specified color, pretty simple.
Now, you need someway to paint a series of circles around the same center point, something like...
public void paintCirclesIn(Graphics2D g2d, int count, int radius, int centerX, int centerY, Color stroke, Color fill) {
System.out.println(radius + "; " + centerX + "; " + centerY);
int delta = radius / count;
int innerRadius = radius;
for (int index = 0; index < count; index++, innerRadius -= delta) {
paintCircleAt(g2d, innerRadius, centerX, centerY, stroke, fill);
}
}
Okay, this basically calculates the difference (delta) between each circle and the paints that many circles with that much difference in their radius from the previous one. Because of the way the painting is done, we start with the outer circle and paint in.
And finally, we need someway to paint a square and circles, something like...
public void paintCirclesInSquare(Graphics2D g2d, int count, int x, int y, int width, int height, Color squareStroke, Color squareFill, Color circleStroke, Color circleFill) {
int centerX = x + (width / 2);
int centerY = y + (height / 2);
int radius = Math.min(centerX, centerY);
Rectangle2D box = new Rectangle2D.Double(x, y, width, height);
g2d.setColor(squareFill);
g2d.fill(box);
g2d.setColor(squareStroke);
g2d.draw(box);
paintCirclesIn(g2d, count, radius, centerX, centerY, circleStroke, circleFill);
g2d.drawLine(centerX, y, centerX, y + height);
g2d.drawLine(x, centerY, x + width, centerY);
}
This, again, simply reuses the existing code we already have and adds to it, painting the square, the circles in the square and finally the lines.
Now, from here, you could write a method which took the number of columns/rows you wanted, the x/y position to start from, the size of each of square, the number of circles you need and the colors and reuse this functionality, but I'll leave that up to you ;)
Runnable example for you to play with...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CirclesAndSquares {
public static void main(String[] args) {
new CirclesAndSquares();
}
public CirclesAndSquares() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
int x = getWidth() / 2;
int y = getHeight() / 2;
// paintCircleAt(g2d, Math.min(x, y), y, y, Color.BLACK, Color.YELLOW);
// paintCirclesIn(g2d, 5, Math.min(x, y), x, y, Color.BLACK, Color.YELLOW);
paintCirclesInSquare(g2d, 5, 0, 0, getWidth() - 1, getHeight() - 1, Color.BLACK, Color.GREEN, Color.BLACK, Color.YELLOW);
g2d.dispose();
}
public void paintCirclesInSquare(Graphics2D g2d, int count, int x, int y, int width, int height, Color squareStroke, Color squareFill, Color circleStroke, Color circleFill) {
int centerX = x + (width / 2);
int centerY = y + (height / 2);
int radius = Math.min(centerX, centerY);
Rectangle2D box = new Rectangle2D.Double(x, y, width, height);
g2d.setColor(squareFill);
g2d.fill(box);
g2d.setColor(squareStroke);
g2d.draw(box);
paintCirclesIn(g2d, count, radius, centerX, centerY, circleStroke, circleFill);
g2d.drawLine(centerX, y, centerX, y + height);
g2d.drawLine(x, centerY, x + width, centerY);
}
public void paintCirclesIn(Graphics2D g2d, int count, int radius, int centerX, int centerY, Color stroke, Color fill) {
System.out.println(radius + "; " + centerX + "; " + centerY);
int delta = radius / count;
int innerRadius = radius;
for (int index = 0; index < count; index++, innerRadius -= delta) {
paintCircleAt(g2d, innerRadius, centerX, centerY, stroke, fill);
}
}
public void paintCircleAt(Graphics2D g2d, int radius, int centerX, int centerY, Color stroke, Color fill) {
Ellipse2D.Double circle = new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2);
g2d.setColor(fill);
g2d.fill(circle);
g2d.setColor(stroke);
g2d.draw(circle);
}
}
}

Drawing image on Graphics object does not work, but drawing lines work

For some reason painting an image does not appear to work on my Graphics object, please see the Triangle -> paintComponent() method.
Could I be missing something critical? Perhaps to do with not casting the Graphics object to Graphics2D? A transparency mask?
final JFrame jFrame = new JFrame();
jFrame.add(new Triangle());
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setSize(500,500);
jFrame.repaint();
jFrame.setVisible(true);
Triangle class:
public class Triangle extends JPanel {
private int x = 50;
private int y = 50;
private int width = 100;
private int length = 300;
private int direction = 0;
private BufferedImage renderedImage = null;
private Image getRenderedImage() {
if (renderedImage == null) {
BufferedImage image = new BufferedImage(100, 300, BufferedImage.TYPE_3BYTE_BGR);
drawGraphics(image.getGraphics());
}
return renderedImage;
}
private void drawGraphics(Graphics graphics) {
graphics.setColor(Color.BLUE);
// left
graphics.drawLine(
(int) Math.round(x - (width / 2.0)), y,
(int) x, y + length);
// right
graphics.drawLine(
(int) x, y + length,
(int) Math.round(x + (width / 2.0)), y);
// bottom
graphics.drawLine(
(int) Math.round(x - (width / 2.0)), y,
(int) Math.round(x + (width / 2.0)), y);
}
protected void paintComponent(Graphics graphics) {
// this works
//drawGraphics(graphics);
// this doesn't work
graphics.drawImage(getRenderedImage(), 0, 0, null);
}
}

How to make star shape in Java?

I'm trying to make some shapes with Java. I created two rectangles with two different colors but I want to create a star shape and I can't find useful source to help me doing this.
Here is my code:
import java.awt.*;
import javax.swing.*;
public class shapes extends JPanel{
#Override
public void paintComponent(Graphics GPHCS){
super.paintComponent(GPHCS);
GPHCS.setColor(Color.BLUE);
GPHCS.fillRect(25,25,100,30);
GPHCS.setColor(Color.GRAY);
GPHCS.fillRect(25,65,100,30);
GPHCS.setColor(new Color(190,81,215));
GPHCS.drawString("This is my text", 25, 120);
}
}
You could try using a polygon and some basic math:
int midX = 500;
int midY = 340;
int radius[] = {118,40,90,40};
int nPoints = 16;
int[] X = new int[nPoints];
int[] Y = new int[nPoints];
for (double current=0.0; current<nPoints; current++)
{
int i = (int) current;
double x = Math.cos(current*((2*Math.PI)/max))*radius[i % 4];
double y = Math.sin(current*((2*Math.PI)/max))*radius[i % 4];
X[i] = (int) x+midX;
Y[i] = (int) y+midY;
}
g.setColor(Color.WHITE);
g.fillPolygon(X, Y, nPoints);
You can also use existing classes e.g. http://java-sl.com/shapes.html for regular polygons and stars.
The Polygon class can be considered as a legacy class that has been there since Java 1.0, but should hardly be used any more in new code. The odd way of specifying the x/y coordinates in separate arrays, and, more importantly, the fact that it only supports int[] arrays limits its application areas. Although it implements the Shape interface, there are more modern implementations of this interface that can be used to represent polygons. In most cases, describing the polygon as a Path2D is easier and more flexible. One can create a Path2D p = new Path2D.Double(); and then do a sequence of moveTo and lineTo calls to geneate the desired shape.
The following program shows how the Path2D class may be used to generate star shapes. The most important method is the createStar method. It is very generic. It receives
the center coordinates for the star
the inner and outer radius of the star
the number of rays that the star should have
the angle where the first ray should be (i.e. the rotation angle of the star)
If desired, a simpler method may be wrapped around this one - as with the createDefaultStar example in the code below.
The program shows different stars, painted as lines and filled with different colors and radial gradient paints, as examples:
The complete program as a MCVE:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawStarShape
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new DrawStarShapePanel());
f.setSize(600, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class DrawStarShapePanel extends JPanel
{
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D) gr;
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.BLACK);
g.draw(createDefaultStar(50, 200, 200));
g.setPaint(Color.RED);
g.fill(createStar(400, 400, 40, 60, 10, 0));
g.setPaint(new RadialGradientPaint(
new Point(400, 200), 60, new float[] { 0, 1 },
new Color[] { Color.RED, Color.YELLOW }));
g.fill(createStar(400, 200, 20, 60, 8, 0));
g.setPaint(new RadialGradientPaint(
new Point(200, 400), 50, new float[] { 0, 0.3f, 1 },
new Color[] { Color.RED, Color.YELLOW, Color.ORANGE }));
g.fill(createStar(200, 400, 40, 50, 20, 0));
}
private static Shape createDefaultStar(double radius, double centerX,
double centerY)
{
return createStar(centerX, centerY, radius, radius * 2.63, 5,
Math.toRadians(-18));
}
private static Shape createStar(double centerX, double centerY,
double innerRadius, double outerRadius, int numRays,
double startAngleRad)
{
Path2D path = new Path2D.Double();
double deltaAngleRad = Math.PI / numRays;
for (int i = 0; i < numRays * 2; i++)
{
double angleRad = startAngleRad + i * deltaAngleRad;
double ca = Math.cos(angleRad);
double sa = Math.sin(angleRad);
double relX = ca;
double relY = sa;
if ((i & 1) == 0)
{
relX *= outerRadius;
relY *= outerRadius;
}
else
{
relX *= innerRadius;
relY *= innerRadius;
}
if (i == 0)
{
path.moveTo(centerX + relX, centerY + relY);
}
else
{
path.lineTo(centerX + relX, centerY + relY);
}
}
path.closePath();
return path;
}
}
I have 2 method.
1)
public static Bitmap drawStar(int W, int H, int color, boolean andRing)
{
Path path = new Path();
Bitmap output = Bitmap.createBitmap(W, H, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
float midW ,min ,fat ,half ,radius;
if(andRing)
{
midW = W / 2;
min = Math.min(W, H);
half = min / 2;
midW = midW - half;
fat = min / 17;
radius = half - fat;
paint.setStrokeWidth(fat);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(midW + half, half, radius, paint);
path.reset();
paint.setStyle(Paint.Style.FILL);
path.moveTo( half * 0.5f, half * 0.84f);
path.lineTo( half * 1.5f, half * 0.84f);
path.lineTo( half * 0.68f, half * 1.45f);
path.lineTo( half * 1.0f, half * 0.5f);
path.lineTo( half * 1.32f, half * 1.45f);
path.lineTo( half * 0.5f, half * 0.84f);
}
else
{
min = Math.min(W, H);
half = min/2;
path.reset();
paint.setStyle(Paint.Style.FILL);
path.moveTo( half * 0.1f , half * 0.65f);
path.lineTo( half * 1.9f , half * 0.65f);
path.lineTo( half * 0.40f , half * 1.65f);
path.lineTo( half , 0 );
path.lineTo( half * 1.60f, half * 1.65f);
path.lineTo( half * 0.1f, half * 0.65f);
}
canvas.drawPath(path, paint);
return output;
}
2)
public static Bitmap drawStar(int W,int H,int spikes,int innerRadius,int outerRadius, int backColor,boolean border, int borderColor)
{
if(W < 10)
W = 10;
if(H < 10)
H = 10;
if(spikes < 5)
spikes = 5;
int smallL = W;
if(H < W)
smallL = H;
if(outerRadius > smallL/2)
outerRadius = smallL/2;
if(innerRadius < 5)
innerRadius = 5;
if(border)
{
outerRadius -=2;
innerRadius -=2;
}
Path path = new Path();
Bitmap output = Bitmap.createBitmap(W, H, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(backColor);
int cx = W/2;
int cy = H/2;
double rot = Math.PI / 2 * 3;
float x,y;
double step = Math.PI / spikes;
path.moveTo(cx, cy - outerRadius);
for (int i = 0; i < spikes; i++)
{
x = (float) (cx + Math.cos(rot) * outerRadius);
y = (float) (cy + Math.sin(rot) * outerRadius);
path.lineTo(x, y);
rot += step;
x = (float) (cx + Math.cos(rot) * innerRadius);
y = (float) (cy + Math.sin(rot) * innerRadius);
path.lineTo(x, y);
rot += step;
}
path.lineTo(cx, cy - outerRadius);
path.close();
canvas.drawPath(path, paint);
if(border)
{
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(borderColor);
canvas.drawPath(path, paint);
}
return output;
}

Categories