Okay I was wondering three things so right now my house background is white how do I make it part blue and green for the grass bottom part. Also my line is going downward how do I make go up toward northeast to make the triangle for the ceiling of the house? Last thing what about adding a tree do I make a bunch of arcs to get the "bush curviness" of the tree?
import java.awt.Color;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Polygon;
public class House extends Canvas {
public House() {
setBackground(Color.WHITE);
}
public void paint(Graphics window) {
window.setColor(Color.BLUE);
window.drawRect(250, 300, 50, 125);
window.fillRect(350, 300, 50, 135);
window.setColor(Color.PINK);
window.drawRect(200, 150, 350, 300);
window.fillRect(200, 150, 350, 300);
window.setColor(Color.GREEN);
Polygon poly = new Polygon();
poly.addPoint(100, 200);
poly.addPoint(200, 400);
poly.addPoint(300, 200);
window.fillPolygon(poly);
}
}
how do I make it part blue and green for the grass bottom part
Don't use "magic" numbers, use absolute known values, like getWidth and getHeight, for example:
window.setColor(Color.BLUE);
window.fillRect(0, 0, getWidth(), getHeight() / 2);
window.setColor(Color.GREEN);
window.fillRect(0, getHeight() / 2, getWidth(), getHeight() / 2);
Also my line is going downward how do I make go up toward northeast to make the triangle for the ceiling of the house?
It's doing exactly what you told it to, remember, the top/left corner is 0x0, meaning coordinates increase in size as the move right/down
Polygon poly = new Polygon();
poly.addPoint(100, 200);
poly.addPoint(200, 100);
poly.addPoint(300, 200);
Last thing what about adding a tree do I make a bunch of arcs to get the "bush curviness" of the tree?
You could just use a series of over lapping ovals, using Graphics#fillOval or Graphics#drawArc
I would strongly recommend that you have a look at 2D Graphics for techniques and ideas when using Graphics.
I'd also encourage you to have a look at Painting in AWT and Swing and Performing Custom Painting to understand how painting actually works in AWT/Swing
Related
If you run the code below, you will see that there is a red square with a blue line along the bottom and right edges of the square. However, as you can see in the code, the parameters for the rectangle being drawn are the same as the rectangle being filled.
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.blue);
g.drawRect(50, 50, 100, 100);
g.setColor(Color.red);
g.fillRect(50, 50, 100, 100);
}
};
panel.setPreferredSize(new Dimension(200, 200));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
Does anyone know the reasoning behind this behavior? Or is this a bug in Java's codebase?
It seems like drawing the rectangle adds 1 to the width and height of the rectangle you specify. This seems like un-intuitive behavior for one, but in my case it is also causing some undesired effects for a gui I am building.
This behavior is also found when drawing polygons with horizontal/vertical lines. Is there a simple way of getting some consistency in what is painted between the graphics draw and fill functions? It would be great if there was a way for any arbitrary polygon to completely paint over a previously drawn polyline using the same points.
One approach I had thought of was to both draw and fill whenever I want to fill a polygon and then just draw when I want to draw the polygon.
This would actually work in cases of opaque polygons, but in my case I have both opaque and transparent polygons so this approach is not an option.
This is clearly documented in the Graphics API:
drawRect
public void drawRect(int x,
int y,
int width,
int height)
Draws the outline of the specified rectangle. The left and right edges of the rectangle are at x and x + width. The top and bottom edges are at y and y + height. The rectangle is drawn using the graphics context's current color.
and
fillRect
public abstract void fillRect(int x,
int y,
int width,
int height)
Fills the specified rectangle. The left and right edges of the rectangle are at x and x + width - 1. The top and bottom edges are at y and y + height - 1. The resulting rectangle covers an area width pixels wide by height pixels tall. The rectangle is filled using the graphics context's current color.
Note the difference in the calculation for the right and bottom edges. Although this difference is clearly documented, there is no justification for this difference.
Finally, note that the first line of paintComponent() should be super.paintComponent(g);. This will ensure that the super class has a chance to initialize things, including clearing the region where you will draw.
I'm currently working on a project with the theme of earth hour, and we are only allowed to use rectangles, circles and triangles. Here's the image i'm tring to create (not exactly, mine will be much more simplified!):
https://www.google.com/search?q=earth+hour&biw=1366&bih=586&source=lnms&tbm=isch&sa=X&ved=0ahUKEwj__5H0vtvQAhXLrlQKHTi8BagQ_AUIBygC#imgrc=fQkBxn0a8LnwbM%3A
(not sure if you could see the link)
But when i'm coding it, i'm running into trouble to rotate those rectangles to stand on the tangent line of the circle. I'm a student just learnt some basics of java, like loops and arrays. So my quesiton is that if there's some understandable way that doesn't involve some complex and exotic methods that could rotate those rectangles? I know it will probably involve some complicated solutions that is beyond my knowledge. But any help is much appreciated.
this is part of the code that i build the building standing perpendicularly to the circle(earth):
// create mid buildings
Color blc = new Color(0, 0, 0);
Rectangle midBld = new Rectangle(240, 220, 20, 40, blc);
midBld.draw(g);
Rectangle midBld1 = new Rectangle(242, 190, 16, 30, blc);
midBld1.draw(g);
Triangle midBld2 = new Triangle(250, 160, 8, 30, blc);
midBld2.draw(g);
Triangle midBld3 = new Triangle(250, 160, -8, 30, blc);
midBld3.draw(g);
A Rectangle cannot be rotated, its edges are always in parallel to the axis. But you can rotate and translate the coordinate system in witch you draw the shapes. From Graphics2D API doc.
All coordinates passed to a Graphics2D object are specified in a device-independent coordinate system called User Space, which is used by applications. The Graphics2D object contains an AffineTransform object as part of its rendering state that defines how to convert coordinates from user space to device-dependent coordinates in Device Space.
Graphics2D also provide two methods that are useful in this task: translate that moves the origin of the coordinates and rotate that, well, rotates the system.
package graphics;
import javax.swing.*;
import java.awt.*;
/**
* Earth Hour
*/
public class RotateRect extends JFrame {
private static final int WIDTH = 400;
private static final int HEIGHT = 400;
public RotateRect() {
this.setSize(WIDTH, HEIGHT);
this.setTitle("Rotate Rectangles");
this.setContentPane(new JPanel() {
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// Background: White
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, this.getWidth(), this.getHeight());
// Draw "Earth": Center(200, 400), Radius=200
g2.setColor(Color.BLACK);
g2.fillOval(0, 200, 400, 400);
// Move origin to center of the canvas (surface of earth)
g2.translate(200, 200);
// Rotate the coordinate system, relative to the center of earth.
// note x, y are in the translated system
// Transforms are accumulative
g2.rotate(-Math.PI/6, 0, 200);
// Fill a rectangle with top-left corner at (-20, 80) in the rotated system
// It's important to make the rectangle symmetrical to the y-axis, otherwise the building looks
// funny.
// Also, make the building "sunk" a little, so that it's fully on the ground.
g2.fillRect(-20, -80, 40, 100);
g2.rotate(Math.PI/3, 0, 200);
g2.fillRect(-20, -80, 40, 100);
g2.rotate(-Math.PI/6, 0, 200);
g2.fill(new Rectangle(-20, -80, 40, 100));
}
});
}
public static void main(String [] args) {
RotateRect rr = new RotateRect();
rr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
EventQueue.invokeLater(()->rr.setVisible(true));
}
}
Super newbie here. I am trying to draw a Triangle on top of the Rectangles I draw but it does not appear. I know it is there because when I remove the 2 Rectangles and change the color to Yellow or something, it appears. I also need to put stars and sun on top of the Triangle... and yes it is a flag. I am not asking for the exact code. Hints for newbies will be appreciated. Please help!
import java.awt.*;
import java.awt.Polygon;
import java.awt.Graphics;
import javax.swing.*;
public class FlagShapes extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.WHITE);
//triangle of the flag
int[] xPoints={75, 75, 130};
int[] yPoints={75, 185, 130};
int nPoints=3;
g.setColor(Color.WHITE);
g.fillPolygon(xPoints, yPoints, nPoints);
//blue part of the flag
g.setColor(Color.BLUE);
g.fillRect(75, 75, 200, 55);
//red part of the flag
g.setColor(Color.RED);
g.fillRect(75, 130, 200, 55);
//pole drawing
g.setColor(Color.BLACK);
g.fillRect(72, 75, 2, 300);
}
}
So I found out the answer to my question (thanks Yahoo) Java's default rendering approach uses rasterisation. Just draw the two shapes in the same location Java will draw both even if they overlap. Whichever one is drawn first will be 'under' whichever one is drawn second.
I create a window with a panel with custom panel class and paint circles on it based on array data. How do I get both sets of circles to stay on screen?
import java.awt.Color;
import java.awt.*;
import javax.swing.*;
class DataPaint extends JPanel {
static int offsetY = 0;
int leftX = 20;
int[] guessColours;
Color purple = new Color(155, 10, 255);
Color pink = new Color(255, 125, 255);
Color[] Colours = { Color.blue, Color.cyan, Color.green, Color.orange,
pink, purple, Color.red, Color.yellow };
public DataPaint() {
setBackground(Color.WHITE);
}
public void paintClues(int[] guessColours) {
this.guessColours = guessColours;
offsetY += 30;
}
// naive attempt to make it work !!!!
// what is diff between paintComponent and paint?
public void update(Graphics g) {
paintComponent(g);
}
// paint circles based on array data
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < guessColours.length; i++) {
g2.setPaint(Colours[guessColours[i]]);
g2.fillOval(leftX + (i * 30), offsetY, 20, 20);
}
}
// create window with panel and paint circles on it based on array data
public static void main(String args[]) {
JFrame frame = new JFrame("data paint");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
DataPaint panel = new DataPaint();
frame.add(panel);
frame.setVisible(true);
int[] cols = { 2, 4, 5, 3, 6 };
int[] cols2 = { 1, 3, 7, 3, 4 };
// the second call replaces the first call on the panel?
panel.paintClues(cols);
panel.paintClues(cols2);
}
}
You don't stop it. The way Swing, and most GUI frameworks, work is that the paintComponent method or its analogue is always supposed to draw everything from scratch.
There are several reasons for this. One is is that if the window were resized, or any other sort of layout change occurred, or if the data-set being drawn changed in a complex way, you will need to be able to redraw anyway. Also, some window systems do not even store what is drawn in the window permanently, so you need to be able to redraw if your window is covered then uncovered. It is possible to have a component which has a permanent image that you can draw into, but that is not the usual way to do things and is less efficient unless you're writing, say, a paint program.
Change your data structures so that you keep all the information, and write your paintComponent so that it draws everything you want on screen every time it is called.
(There are refinements to make this efficient for partial updates of complex graphics, but you don't need to worry about those yet, as this is such a simple case. If you did need to do this, you would ask Swing to repaint a small region of your component (such as with JComponent.repaint(Rectangle r); it would then automatically prohibit drawing to areas outside that region while it calls your paintComponent method. That works fine to prevent flicker and save some filling work; then if it really matters for efficiency, inside paintComponent you compare that clip region (Graphics.getClip()) to what you're drawing and skip everything that doesn't intersect. But you really shouldn't worry about that yet for this simple case. First get your code working and using Swing correctly, then optimize if it matters.)
In your particular example, which I take it is intended to be a Mastermind game (you should mention that up front to help us read your code), put cols and cols2 into an int[][] field of DataPaint, and then use a loop inside of paintComponent to read every sub-array in that array and paint all of them.
(this is java) I have an oval, representing a unit. I want the colour of the oval to represent the unit's health. So a perfectly healthy unit will be all green. and with the unit's health decreasing the oval starts filling with red from the bottom. so, on 50% health the oval would be red in bottom half and green in the top half, and fully red when the unit's dead.
I'm sure the solution here must be obvious and trivial , but I just can't see it.
thanks a lot
You can draw a red oval in the background, then draw a green intersection of an oval and a rectangle, where the rectangle starts below the oval, then moves further to the top to reveal more of the red oval beneath.
You might like to read up on how to construct complex shapes out of primitives here
Override the paint method something like this:
public void paint(Graphics graphics)
{
super.paint(graphics);
Rectangle originalClipBounds = graphics.getClipBounds();
try
{
graphics.clipRect(100, 100, 100, 25);
graphics.setColor(Color.RED);
graphics.fillOval(100, 100, 100, 100);
}
finally
{
graphics.setClip(originalClipBounds);
}
try
{
graphics.clipRect(100, 125, 100, 75);
graphics.setColor(Color.BLUE);
graphics.fillOval(100, 100, 100, 100);
}
finally
{
graphics.setClip(originalClipBounds);
}
}
Might want to enhance it with some double buffering but you get the gist.
You can set the clip on the graphics when you draw the green. Only things within the clip actually get painted.
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor(Color.RED);
g2d.fillOval(10, 10, 200, 100);
g2d.setColor(Color.GREEN);
g2d.setClip(10, 10, 200, 50);
g2d.fillOval(10, 10, 200, 100);
}