How can I draw several rectangles in a row programmatically? - java

I want to put several rectangle i a row. But because I'm new to Android and specially to Bitmap, Canvas and so on, I need some help.
It should look like this, only with rectangles:
I have created one rectangle with this code:
Paint paint = new Paint();
paint.setColor(Color.parseColor("#CD5C5C"));
Bitmap bg = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bg);
canvas.drawRect(50, 80, 200, 200, paint);
RelativeLayout ll = (RelativeLayout) findViewById(R.id.rect);
ImageView iV = new ImageView(this);
iV.setImageBitmap(bg);
ll.addView(iV);
But now I dont know how to create more rectangles with different colors in a row.
I'm really new and sorry for that maybe stupid question but I need help for it.
Can anybody guide me how to do this in the best way?

The key here are these lines:
paint.setColor(Color.parseColor("#CD5C5C"));
canvas.drawRect(50, 80, 200, 200, paint);
They set the colour and draw a rectangle. You can now repeat these lines to get 2 rectangles:
paint.setColor(Color.parseColor("#CD5C5C"));
canvas.drawRect(50, 80, 200, 200, paint);
paint.setColor(Color.parseColor("#DDDDDD"));
canvas.drawRect(210, 80, 360, 200, paint);
Note that I have changed the colour and co-ordinates a little bit. You could continue doing this several times to get all of your rectangles drawn.
Better still use a variable for the x and y coordinates, and use a loop:
int left = 50; // initial start position of rectangles (50 pixels from left)
int top = 50; // 50 pixels from the top
int width = 150;
int height = 150;
for (int row = 0; row < 2; row++) { // draw 2 rows
for(int col = 0; col < 4; col++) { // draw 4 columns
paint.setColor(Color.parseColor("#CD5C5C"));
canvas.drawRect(left, top, left+width, top+height, paint);
left = (left + width + 10); // set new left co-ordinate + 10 pixel gap
// Do other things here
// i.e. change colour
}
top = top + height + 10; // move to new row by changing the top co-ordinate
}
Hope that helps.

This should do it. I tried to self-document my code as mush as possible. This is very dynamic i.e. you can adjust the height, width, xPad, yPad, etc. and the window will compensate.
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class RectanglesPanel extends JPanel {
public static final int[] COLORS = new int[] {
0xFFFFFF, 0xF67457, 0xFFC238, 0xEFEF38,
0xBCCACA, 0x75D1E0, 0x84E0C2, 0xC2E749
};
private static Random rand = new Random();
private int width = 80;
private int height = 50;
private int rows = 2;
private int cols = 4;
private int xPad = 20;
private int yPad = 30;
private float strokeWidth = 2.0f;
int windowWidth = calculateOffset(width, cols, xPad);
int windowHeight = calculateOffset(height, rows, yPad);
public RectanglesPanel() {
setPreferredSize(new Dimension(windowWidth, windowHeight));
}
private int calculateOffset(int whole, int partitions, int padding) {
return (whole * partitions) + (padding * (partitions + 1));
}
#Override
public void paintComponent(Graphics g) {
Stroke stroke = new BasicStroke(strokeWidth,
BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER);
((Graphics2D)g).setStroke(stroke);
// Fill in background.
g.setColor(new Color(0xF6F6F6));
g.fillRect(0, 0, windowWidth, windowHeight);
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
int x = calculateOffset(width, col, xPad);
int y = calculateOffset(height, row, yPad);
int color = (row * cols + col) % COLORS.length;
// Fill in rectangle.
g.setColor(new Color(COLORS[color]));
g.fillRect(x, y, width, height);
// Stroke the border of the rectangle.
g.setColor(new Color(0xE7E7E7));
g.drawRect(x, y, width, height);
}
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new RectanglesPanel();
frame.setContentPane(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

use for loop keeping the y coordinates constant
for(i=0;i<=200;i=i+40)
{
canvas.drawRect(i,0,i+30,100);
}
for next row increase y coordinate by your require amount and repeat the same or use nested for loops
you can set color by
myPaint.setColor(color.black);
myPaint.setStyle(Style.FILL);
canvas.drawRect(0,0,100,100, myPaint);

Related

Java Code not working. Using loops to draw stripes on the US Flag

I am attempting to draw the US flag using java. I have pretty much done all this coding using lots of variables. It should be at least displaying the stripes, blue box, and the stars(ovals in this case). However, when I run the code through the compiler, and run it, all it displayes is a white background with a red stripe on the top. Could I please receive some help to see where my error is? I have tried everything.
Here is the code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Color;
public class UsFlag extends JPanel {
int w = getWidth();
int h = getHeight();
int numberStripes = 13;
int numStarCol = 8;
int numStarRow = 6;
int stripeHeight = h/numberStripes;
int boxWidth = (int)(w*0.4);
int boxHeight = 7 * stripeHeight;
int starWidth = boxWidth/numStarCol;
int starHeight = boxHeight/numStarRow;
/*public UsFlag() {
//ask user to enter number of stripes, star columns, and star rows
}*/
#Override
public void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
//Background
g.setColor(Color.RED);
g.fillRect(0, 0, w, h);
//Stripes
g.setColor(Color.WHITE);
for (int i = 0; i < numberStripes; i += 1) {
g.fillRect(0,stripeHeight, w, stripeHeight);
stripeHeight = stripeHeight + 45;
}
//Blue Rect
g.setColor(Color.BLUE);
g.fillRect(0, 0, boxWidth, boxHeight);
//stars
int y = 0;
int x = 0;
for (int j = 0; j < numStarRow; j++){
for (int i = 0; i < numStarCol; i++){
g.setColor(Color.WHITE);
g.fillOval(5, 5, starWidth, starHeight);
x += starWidth;
}
y += starHeight;
x = 0;
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(400, 400);
window.setContentPane(new UsFlag());
window.setVisible(true);
}
}
The first two parameters for the fillRect() method and the fillOval() method are considered coordinates (x & y) for the object you want to paint. This means that for x you need to place a integer pixel value as to where you want the Left edge of the object is to Start being painting from along the horizontal plain, and for y you need to place a integer pixel value as to where you want the Top edge of the object is to Start being painting from along the vertical plain. For fillRect() for example:
g.fillRect(20, 20, 100, 30);
The other two parameters are for the Width (w) and Height (h) in pixels of the object to paint. Use the the variable i from your for loop (y = i + 30; for example) to draw objects below one another. Read this for more information.

I want to increase my number by one, 7 times from 0 in label of JFrame at specific location

Here's my code:
for (int count = 0; count < 7; count++) {
int z=0;
z++;
label = new JLabel(Integer.toString(z));
label.setLocation(12, 32);
add(label,Color.white);
}
I have two problems. One is with location. It is at upward center while I want (12,32). Other is with increment of z; it's not increasing and remains fixed at one. Output.
Alternatively, tell me an easy way to perform this task. I want labels in bullseye from 1-10 in each oval.
This is the full code if you not understand:
package bullseye;
import javax.swing.JPanel; import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class BullsEye extends JPanel {
private JLabel label;
public BullsEye() {
setBackground(Color.white);
setPreferredSize(new Dimension(600,600));
for (int count = 0; count < 7; count++) {
int z=0;
z++;
label = new JLabel(Integer.toString(z));
label.setLocation(12, 32);
add(label,Color.white);
}
}
public void paintComponent(Graphics page) {
super.paintComponent(page);
Graphics2D g2 = (Graphics2D) page;
g2.setStroke(new BasicStroke(3));
//Graphics 2D is used to increase stroke of white ovals.
//As we place white ovals as draw (not fill), and not use draw command for black ovals.
//So, stroke of white ovals only increase to 3 from 1 (default value).
int x = 150, y = 150, diameter = 300;
for (int count = 0; count < 7; count++) {
page.setColor(Color.white);
page.drawOval(x, y, diameter, diameter);
page.setColor(Color.black);
page.fillOval(x, y, diameter, diameter);
diameter = diameter-50;
x = x+25;
y = y+25;
}
page.setColor(Color.white);
page.fillOval(300-(10/2), 300-(10/2) , 10 , 10);
//Centre of frame is 300, 300. But oval starts its first point from 300, 300.
//As dimensions of oval are 10, 10. So, it means they have diametre of 10, 10 and radius of 5.
//So, from this we know centre is at 300-5, 300-5.
x = 250/2; y = 250/2; diameter = 350;
for (int count = 0; count < 3; count++){
page.setColor(Color.black);
page.drawOval(x, y, diameter, diameter);
diameter = diameter+50;
x = x-25;
y=y-25;
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Bullseye");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BullsEye panel = new BullsEye();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true); }
}
You never use count in the for loop
and z is badly used and also useless as count has already the value you need.
for (int count = 0; count < 7; count++) {
label = new JLabel(Integer.toString(count));
label.setLocation(12, 32);
add(label,Color.white);
}
You have to declare z outside of the loop
int z=0;
for (int count = 0; count < 7; count++) {
z++;
label = new JLabel(Integer.toString(z));
label.setLocation(12, 32);
add(label,Color.white);
}
And please indent your code for readability.

How to determine the coordinates of the next rectangle on JPanel

i have an arraylist RecArray of objects with each object containing two int values, one for the width and for the height of a rectangle. Each rectangle's height and width are a multiple of ten. the rectangles have to be passed on to the surface as in the given order in RecArray from left to right and from top to bottom. my problem is i can not find the x,y coordinates of the next rectangle. what im trying to do is, starting at the coordinate (0,0) i generate the first rectangle, add it to an arraylist RecList. Then i set the x and y coordinates. x becomes x = x+RecArray.get(0).getLength1() + 1. if x is greater than the width of the jpanel surface then it becomes 0 and y becomes y = y + 10 . starting from the second object in the RecArray i try to generate rectangles with the given coordinates and width&height. Then i try to compare them with all the previous rectangles to see if there is any overlapping. if there is no overlapping, the rectangle will be drawn, if there is overlapping, the x coordinate of the rec becomes x = RecList.get(j).width+1 and if that exceeds the width x becomes 0 and y is y=y+10. Then i regenate the current rectangle with the new coordinates and compare with the other rectangles in RecList again till i find the right spot for the current rectangle.ive been dealing with that issue for the last 5 days and am really fed up now. i would greatly appreciate any tipps. and Please be patient with me. im still learning programming.
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle rec = new Rectangle(x, y, RecArray.get(0).getWidth(),
RecArray.get(0).getHeight());
RecList.add(rec);
recPaint(g2,RecArray.get(0));
x = x + RecArray.get(0).getWidth() + 1;
int i;
for (i = 1; i < RecArray.size(); i++) {
if (x >= this.getArea().getWidth()) {
x = 0;
y = y + 10;
}
Rectangle rec1 = new Rectangle(x, y, RecArray.get(i)
.getWidth(), RecArray.get(i).getheight());
for (int j= 0; j < RecList.size(); j++) {
if (!recIntersect(rec1, RecList.get(j))) {
RecList.add(rec1);
recPaint(g2,RecArray.get(i));
break;
}
else {
x = RecList.get(j).width;
if (x >= this.getFlaeche().getLength1()) {
x = 0;
y = y + 10;
}
rec1 = new Rectangle(x, y,RecArray.get(i). .getWidth(),
RecArray.get(i).getHeight());
}
x = x + RecArray.get(i).getWidth();
}
//With this method using the given rec parameter a rectangle will be drawn on the g2 and filled in blue colour
private void recPaint (Graphics2D g2, RecType rec){
g2.setColor(Color.BLUE);
g2.fillRect(x, y, rec.getWidth(),
rec.getLength2());
g2.setColor(Color.BLACK);
g2.drawRect(x, y, rec.getHeight(),
rec.getLength2());
}
// returns true, if two rectangles overlap
private boolean recIntersect(Rectangle rec1, Rectangle rec2) {
if( rec1.intersects(rec2)){
return true;
}
return false;
}
Edit: apparently i haven't stated clearly what my problem is. my problem is, that the way i generate (x,y) coordinates of the rectangles is obviously wrong. the way my algorithm works doesnt get the results i want. i want my rectangles to be placed neatly next to/above/below each other WITHOUT overlapping, which is not the case.
Separate out your List of Rectangles. Calculate the X, Y coordinates once.
Since I didn't have your object class, I used the Dimension class, which holds a width and a length. I used the Rectangle class to hold the objects that will eventually be drawn in your Swing GUI.
Divide and conquer. Separate out your GUI model, view, and controller(s). This way, you can focus on one piece of the puzzle at a time.
Here are the results of my test code when I ran it with a drawing area of 500, 400.
java.awt.Rectangle[x=0,y=0,width=100,height=100]
java.awt.Rectangle[x=100,y=0,width=20,height=10]
java.awt.Rectangle[x=120,y=0,width=40,height=20]
java.awt.Rectangle[x=160,y=0,width=60,height=40]
java.awt.Rectangle[x=220,y=0,width=80,height=60]
java.awt.Rectangle[x=300,y=0,width=20,height=10]
java.awt.Rectangle[x=320,y=0,width=120,height=110]
Here are the results of my test code when I ran it with a drawing area of 200, 200.
java.awt.Rectangle[x=0,y=0,width=100,height=100]
java.awt.Rectangle[x=100,y=0,width=20,height=10]
java.awt.Rectangle[x=120,y=0,width=40,height=20]
java.awt.Rectangle[x=0,y=100,width=60,height=40]
java.awt.Rectangle[x=60,y=100,width=80,height=60]
java.awt.Rectangle[x=140,y=100,width=20,height=10]
And here's the code. I fit rectangles on the X axis until I can't fit another rectangle. Then I add the maximum height to Y, reset the X to zero, reset the maximum height and fit the next row of rectangles.
Create test applications like I did here and make sure that you can create the GUI model long before you create the GUI view and GUI controller.
package com.ggl.testing;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
public class CalculatingRectangles {
public static void main(String[] args) {
CalculatingRectangles calculatingRectangles = new CalculatingRectangles();
Dimension drawingArea = new Dimension(200, 200);
List<Dimension> dimensions = new ArrayList<>();
dimensions.add(new Dimension(100, 100));
dimensions.add(new Dimension(20, 10));
dimensions.add(new Dimension(40, 20));
dimensions.add(new Dimension(60, 40));
dimensions.add(new Dimension(80, 60));
dimensions.add(new Dimension(20, 10));
dimensions.add(new Dimension(120, 110));
List<Rectangle> rectangles = calculatingRectangles
.calculatingRectangles(drawingArea, dimensions);
System.out.println(displayRectangles(rectangles));
}
private static String displayRectangles(List<Rectangle> rectangles) {
StringBuilder builder = new StringBuilder();
for (Rectangle r : rectangles) {
builder.append(r);
builder.append(System.getProperty("line.separator"));
}
return builder.toString();
}
public List<Rectangle> calculatingRectangles(Dimension drawingArea,
List<Dimension> dimensions) {
int width = drawingArea.width;
int height = drawingArea.height;
int x = 0;
int y = 0;
int index = 0;
int maxHeight = 0;
boolean hasRoom = dimensions.size() > index;
List<Rectangle> rectangles = new ArrayList<>();
while (hasRoom) {
Dimension d = dimensions.get(index);
maxHeight = Math.max(maxHeight, d.height);
if ((x + d.width) <= width && (y + maxHeight) <= height) {
Rectangle r = new Rectangle(x, y, d.width, d.height);
x += d.width;
rectangles.add(r);
index++;
if (index >= dimensions.size()) {
hasRoom = false;
}
} else {
y += maxHeight;
if (y > height) {
hasRoom = false;
}
x = 0;
}
}
return rectangles;
}
}

AffineTransform seeming to ignore component bounds

I have the following:
public class ParametricEQView extends JPanel implements PluginView {
private static final int BAND_WIDTH = 3;
private static final int THROW_HEIGHT = 64;
private static final int WIDTH = 128*BAND_WIDTH + 2*MARGIN;
private static final int HEIGHT = 2*THROW_HEIGHT + 2*MARGIN;
private static final int MID_HEIGHT = THROW_HEIGHT + MARGIN;
private final ParametricEQ _peq;
public ParametricEQView(ParametricEQ peq) {
super();
_peq = peq;
SwingUtils.freezeSize(this, WIDTH, HEIGHT);
setToolTipText("Parametric Equalizer");
}
#Override
public void paint(Graphics g) {
final Graphics2D g2d = (Graphics2D) g;
final int max = findMax();
g.setColor(BACKGROUND);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(DATA);
final double scalingFactor = -((double) THROW_HEIGHT) / max;
final double[] fineLevels = _peq.getFineLevels();
int x = MARGIN;
int h;
final int[] xPoints = new int[128];
final int[] yPoints = new int[128];
for (int i = 0; i < 128; ++i) {
h = (int) (fineLevels[i] * scalingFactor);
xPoints[i] = x;
yPoints[i] = MID_HEIGHT + h;
x += BAND_WIDTH;
}
g.drawPolyline(xPoints, yPoints, 128);
g.setColor(AXES);
g.drawLine(MARGIN, MARGIN, MARGIN, HEIGHT-MARGIN);
g.drawLine(MARGIN, MID_HEIGHT, WIDTH-MARGIN, MID_HEIGHT);
g.setFont(AXIS_FONT);
final FontMetrics metrics = g.getFontMetrics();
int width = (int) metrics.getStringBounds(AXIS_LABEL_INPUT_MIDINUM, g).getWidth();
g.drawString(AXIS_LABEL_INPUT_MIDINUM, WIDTH-MARGIN-width, HEIGHT-3);
final AffineTransform atx = new AffineTransform();
atx.setToRotation(-Math.PI/2, 0, HEIGHT);
g2d.setTransform(atx);
final String topLabel = "+" + max;
width = (int) metrics.getStringBounds(topLabel, g).getWidth();
g2d.drawString(topLabel, HEIGHT-MARGIN-width, HEIGHT+10);
width = (int) metrics.getStringBounds(AXIS_LABEL_OUTPUT_VELOCITY, g).getWidth();
g2d.drawString(AXIS_LABEL_OUTPUT_VELOCITY, MID_HEIGHT-(width/2), HEIGHT+10);
g2d.drawString("-" + max, MARGIN, HEIGHT+10);
}
private int findMax() {
int max = 3;
for (int i = 0; i < 128; ++i)
max = Math.max(max, (int) Math.ceil(Math.abs(_peq.getFineLevels()[i])));
return max;
}
}
This is what it looks like:
The ParametricEQView is the component with the white background filling most of the window. In this image its coordinates are (0,0) in the containing frame and everything is great. However, if I resize the window so that the ParametricEQView moves over a bit (it has a fixed size and is set to be centered in its available space), the rotated text stays relative to the (0,0) of the frame instead of the component:
Everything else draws relative to the panel, it's just the rotated text that doesn't. What am I doing wrong?
When you call g2d.setTransform(atx); you override the transform currently set in the Graphics object, i.e. the translation between the panel and its parent frame. That's why the text is drawn in the frame referential, and not in the panel referential.
The correct code would be to get the current transform and modify it or directly call Graphics2D.rotate(double).
1) For custom paintings you need to override protected void paintComponent(Graphics g) instead of public void paint(Graphics g). Read more about customPaintings.
2)Seems you have your problem, because you do something like next for creation of GUI:
JFrame frame = new JFrame();
JPanel p = new JPanel();
ParametricEQView view = new ParametricEQView();
view.setPreferredSize(new Dimension(200,200));
p.add(view);
frame.add(p);
in that case ParametricEQView doesn't resize as you want, because JPanel use FlowLayout as default.
You need to use another LayoutManager for your panel, for example BorderLayout.
Try something like next:
JFrame frame = new JFrame();
ParametricEQView view = new ParametricEQView();
frame.add(view);
or
JPanel panel = new JPanel(new BorderLayout());
panel.add(view,BorderLayout.CENTER);
frame.add(panel);
in that case your ParametricEQView panel will be painting in proper way.

Rendering an isometric grid

I'm making a map editor for an isometric game, and I'm a bit stuck on rendering an isometric guide grid (a grid that shows where objects will be placed). That is, I need to draw lines across a Graphics object in such a way that it forms a grid with cells of variable width and height. What can I do to accomplish this?
So far I have:
//The number of cells in each direction
int nv=h/cellh;
int nh=w/cellw;
for(int i=1;i<=nv;++i){
g.drawLine(0,i*cellh,i*cellh*2,0);
}
But that just draws bottom left to upper right lines that begin on the left side.
This will work as you expect:
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
int width = getWidth();
int height = getHeight();
int sizeW = 50;
int sizeH = 50;
int countW = width / sizeW;
int countH = height / sizeH;
for (int i = 0; i <= countW + countH; i++) {
g.drawLine(0, i * sizeH, i * sizeH, 0);
g.drawLine(width - i * sizeW, 0, width, i * sizeW);
}
}

Categories

Resources