I want to Color 2 Ovals in Java with Graphics2D. Oval1(point) Green and Oval2(point2) Blue. The Problem is that Oval2 becomes green and Oval1 black. Does somebody knows what the problem is?
left(oval1) right(oval2)
Here is the SSCCE:
GameView.java
import javax.swing.JFrame;
import stackoverflow.GameView;
public class GameView extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
private Game game = new Game();
public GameView(){
JFrame gameFrame = new JFrame("Game");
gameFrame.setSize(500, 300);
gameFrame.setVisible(true);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.add(game);
game.runGame();
}
public static void main(String[] args) throws InterruptedException {
new GameView();
}
}
Game.java
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import stackoverflow.Point;
public class Game extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
private Point point = new Point(Color.GREEN);
private Point point2 = new Point(Color.BLUE);
public void runGame(){
repaint();
point2.setX(300);
}
public void paint(Graphics g) {
point.paint(g);
point2.paint(g);
}
}
Point.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
public class Point {
private int x = 100;
private int y = 100;
private int width = 10;
private int height = 10;
private Color color;
public Point(Color color){
this.color = color;
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, width, height);
g2d.setColor(this.color);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Change the order of these calls...
g2d.fillOval(x, y, width, height);
g2d.setColor(this.color);
And you should be painting in JPanel.paintComponent instead.
Related
I'm new to Java (particularly graphics) and am currently working on a task that requires me to have multiple JComponent shapes bouncing off the JFrame walls. The core of the "bouncing off the walls" code was provided (RectangleMover).
I have 3 separate classes. While I was able to get one rectangle to bounce correctly, I can't seem to figure out how to get multiple shapes into the frame.
This is what I came up with: having a JPanel extended class paint the multiple objects. However, now in the RectangleMover class, the shapes appear, but the moveBox method is no longer working despite the objects being of the correct type (Shape) as underlying Rectangle objects. I'm referring specifically to the shapes I have in the shapes array and the for-each loop in the Timer listener.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.Timer;
import java.awt.event.ActionEvent;
public class Shape extends JComponent {
public static int i=-1;
public static int j=0;
private Rectangle box;
private Graphics2D g2;
Color c1 = randomColor();
Color c2 = randomColor();
Color c3 = randomColor();
Color c4 = randomColor();
public Shape(int x, int y,int width,int height) {
box = new Rectangle(x, y, width, height);
}
public void draw(Graphics g) {
g2 = (Graphics2D) g;
if(box.width<125) {
g2.setColor(c1);
g2.fill(box);
}
else if(box.width>=125 && box.width<=200) {
g2.setColor(c2);
g2.fill(box);
}
else if(box.width>200 && box.width<250) {
g2.setColor(c3);
g2.fill(box);
}
else {
g2.setColor(c4);
g2.fill(box);
}
}
public Color randomColor() {
Random random = new Random();
int a = random.nextInt(255);
int b = random.nextInt(255);
int c = random.nextInt(255);
Color myColor = new Color(a,b,c);
return myColor;
}
public void moveBox(int dx, int dy) {
box.translate(dx, dy);
repaint();
}
public void growSize() {
box.width+=1;
box.height+=1;
}
public void shrinkSize() {
box.width-=1;
box.height-=1;
}
public class ShapePanel extends JPanel {
private Graphics2D g2;
Shape box1 = new Shape(0,0,20,20);
Shape box2 = new Shape(0,0,80,30);
Shape box3 = new Shape(0,0,40,80);
public Shape[] shapes = {box1, box2, box3};
public void paintComponent(Graphics g) {
g2 = (Graphics2D) g;
g2.setColor(Color.BLUE);
g2.fillRect(0, 0, 500, 600);
for(Shape item: shapes) {
item.draw(g);
}
}
public Shape[] getArray() {
Shape[] newArray = shapes;
return newArray;
}
}
public class RectangleMover {
private static final int FRAME_WIDTH = 500;
private static final int FRAME_HEIGHT = 600;
private static int BOX_WIDTH = 20;
private static int BOX_HEIGHT = 20;
public static int x=0;
public static int y=0;
private static int dx=1;
private static int dy=1;
private Graphics2D g2;
private static ShapePanel sp = new ShapePanel();
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Screensaver");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(sp);
frame.revalidate();
frame.repaint();
frame.setVisible(true);
//Shape[] shapes = sp.getArray();
for(Shape item: sp.shapes)
System.out.println(item.toString());
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
if(x+BOX_WIDTH>= FRAME_WIDTH-260) {
dx=-1;
}
if(x<=0) {
dx=1;
}
if(y+BOX_HEIGHT>= FRAME_HEIGHT-180) {
dy=-1;
}
if(y<=0) {
dy=1;
}
x=x+dx;
y=y+dy;
//shapes.moveBox(dx,dy);
for(Shape item: sp.shapes) {
item.moveBox(dx, dy);
frame.revalidate();
frame.repaint();
}
if(dx==-1) {
//shapes.shrinkSize();
//rect.shrinkSize();
}
if(dx==1) {
//shapes.growSize();
//rect.growSize();
}
}
}
}
}
I have a program that paints different shapes that I put in the ArrayList, it works fine to iterate with shapes to paint them but my methods for moving them doesn't work. Is it something wrong with my move() method?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyShapes extends JPanel {
private Point2D.Float position;
private final DifferentShapes[] shapes = new DifferentShapes[]{new Circle(), new Triangle(), new Square()};
MovingAdapter ma = new MovingAdapter();
public MyShapes() {
addMouseMotionListener(ma);
addMouseListener(ma);
}
interface DifferentShapes {
void paint(Graphics2D graphics);
boolean contains(int x, int y);
void move(int dx, int dy);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D graphics = (Graphics2D) g;
for (DifferentShapes shape : this.shapes) {
shape.paint(graphics);
}
}
class MovingAdapter
public class MovingAdapter extends MouseAdapter {
private int x;
private int y;
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
}
public void mouseDragged(MouseEvent e) {
final int dx = e.getX() - x;
final int dy = e.getY() - y;
for (DifferentShapes shape : shapes) {
if (shape.contains(x, y)) {
shape.move(dx, dy);
}
}
x += dx;
y += dy;
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Shapes World");
MyShapes m = new MyShapes();
m.setDoubleBuffered(true);
frame.add(m);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class Circle
class Circle implements MyShapes.DifferentShapes {
public Circle() {
}
public static Ellipse2D.Float myCr = new Ellipse2D.Float(10,10, 100, 100);
public void paint(Graphics2D graphics) {
Graphics2D circle = (Graphics2D) graphics;
circle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
circle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
circle.setColor(new Color(0, 0, 117));
circle.fill(myCr);
}
#Override
public boolean contains(int x, int y) {
if (myCr.contains(x, y)) {
}
return true;
}
public void move(int dx, int dy) {
myCr.x += dx;
myCr.y += dy;
}
}
When I use regular if statement it works fine but not in the for loop and my move() method
The logic is right and you are correctly changing the coordinates. You just need to call repaint() in order to make the the changes display.
if (shape.contains(x, y)) {
shape.move(dx, dy);
repaint();
}
I am trying to code the game Pong on Java but am having difficulty displaying the graphics. Nothing appears, just a blank gray default screen when I try to run the program. I am using a Mac, and am running this code on Eclipse.
Any help would be much appreciated.
Thank you.
"Pong.java"
package pong;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Pong implements ActionListener{
public static Pong pong;
public int width = 700, height = 700;
public Renderer renderer;
public Paddle player1;
public Paddle player2;
public JFrame jframe;
public Pong(){
Timer timer = new Timer(20, this);
jframe = new JFrame("Pong");
renderer = new Renderer();
jframe.setSize(width, height);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.add(renderer);
start();
timer.start();
}
public void start(){
player1 = new Paddle(this, 1);
player2 = new Paddle(this, 2);
}
public void update() {
}
public void render(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
player1.render(g);
player2.render(g);
}
#Override
public void actionPerformed(ActionEvent e) {
update();
renderer.repaint();
}
public static void main(String[] args){
pong = new Pong();
}
}
"Renderer.java"
package pong;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Renderer extends JPanel {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Pong.pong.render(g);
}
}
"Paddle.java"
package pong;
import java.awt.Color;
import java.awt.Graphics;
public class Paddle {
public int paddleNumber;
public int x, y, width = 100, height = 500;
public int score;
public Paddle(Pong pong, int paddleNumber){
this.paddleNumber = paddleNumber;
if(paddleNumber == 1){
this.x = 0;
}
else if (paddleNumber == 2){
this.x = pong.width - width;
}
this.y = pong.height / 2 - this.height / 2;
}
public void render(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(x, y, width, height);
}
}
I read many other posts regarding this and I learned that the frame is set to BorderLayout by default. I added one shape to the west and one shape to the center of the frame. But still, only one shape comes up on the frame. The shape that comes up on the frame is the one whose location is at center.
Here is the code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class ShapeMover {
private static final int FRAME_WIDTH = 400;
private static final int FRAME_HEIGHT = 400;
private static final int SHAPE_WIDTH = 50;
private static final int INITIAL_X = 30;
private static final int INITIAL_Y = 100;
private static final int rec_x = 200;
private static final int rec_y = 200;
private static final int rec_height = 30;
private static final int rec_width = 50;
private boolean recToggle = true;
private boolean circleToggle = true;
private JFrame frame;
private CircleComponent myShape;
private RectangleComponent recShape;
private JButton circle, rectangle;
private JPanel panel, panel2;
private void initialSetUp() {
frame = new JFrame();
myShape = new CircleComponent(INITIAL_X, INITIAL_Y, SHAPE_WIDTH);
recShape = new RectangleComponent(rec_x, rec_y,rec_height, rec_width);
circle = new JButton("Click for circle");
event c = new event();
circle.addActionListener(c);
rectangle = new JButton("Click for rectangle");
event2 r = new event2();
rectangle.addActionListener(r);
panel = new JPanel();
panel.add(circle);
panel.add(rectangle);
frame.add(panel, BorderLayout.NORTH);
frame.add(myShape, BorderLayout.WEST);
frame.add(recShape,BorderLayout.CENTER);
myShape.setVisible(false);
recShape.setVisible(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setVisible(true);
} //method
public class event implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(circleToggle == true){
myShape.setVisible(true);
circleToggle = false;
}
else{
myShape.setVisible(false);
circleToggle = true;
}
}
}
public class event2 implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
if(recToggle == true){
recShape.setVisible(true);
recToggle = false;
}
else{
recShape.setVisible(false);
recToggle = true;
}
}
}
public static void main(String[] args) {
ShapeMover sm = new ShapeMover();
sm.initialSetUp();
} //main
} //class
I warn you the other code is pretty long.
Here is rectangle component:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;
public class RectangleComponent extends JComponent{
private CompoundShape shape2;
private Point mousePoint2;
public RectangleComponent(int x, int y, int height, int width){
shape2 = new RectangleShape(x, y, height, width);
addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent event2){
mousePoint2 = event2.getPoint();
if(!shape2.contains(mousePoint2)){
mousePoint2 = null;
}
}
});
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent event2){
if(mousePoint2 == null){
return;
}
Point lastMousePoint2 = mousePoint2;
mousePoint2 = event2.getPoint();
double dx = mousePoint2.getX() - lastMousePoint2.getX();
double dy = mousePoint2.getY() - lastMousePoint2.getY();
shape2.translate((int) dx, (int) dy);
repaint();
}
});
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
//shape.draw(g2);
shape2.draw(g2);
} //method
}
Here is the circle Component:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;
public class CircleComponent extends JComponent{
private Circle shape2;
private Point mousePoint2;
public CircleComponent(int x, int y, int width){
shape2 = new Circle(x, y, width);
addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent event2){
mousePoint2 = event2.getPoint();
if(!shape2.contains(mousePoint2)){
mousePoint2 = null;
}
}
});
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent event2){
if(mousePoint2 == null){
return;
}
Point lastMousePoint2 = mousePoint2;
mousePoint2 = event2.getPoint();
double dx = mousePoint2.getX() - lastMousePoint2.getX();
double dy = mousePoint2.getY() - lastMousePoint2.getY();
shape2.translate((int) dx, (int) dy);
repaint();
}
});
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
//shape.draw(g2);
shape2.draw(g2);
} //method
}
Here is circle:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
public class Circle implements CompoundShape {
private GeneralPath path = null;
private int x;
private int y;
private final int width;
public Circle(int x, int y, int width){
this.x = x;
this.y = y;
this.width = width;
}
#Override
public void draw(Graphics2D g2) {
Ellipse2D.Double c = new Ellipse2D.Double(x,y,width,width);
g2.setColor(Color.RED);
g2.fill(c);
g2.draw(c);
path = new GeneralPath();
path.append(c,false);
g2.draw(path);
}
#Override
public void translate(int dx, int dy) {
// TODO Auto-generated method stub
x = x + dx;
y = y + dy;
}
#Override
public boolean contains(Point point) {
// TODO Auto-generated method stub
if(path == null){
return false;
}
return path.contains(point);
}
}
Here is rectangle shape:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
public class RectangleShape implements CompoundShape {
private GeneralPath path = null;
private int x;
private int y;
private final int width;
private final int height;
public RectangleShape(int x, int y, int width, int height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
#Override
public void draw(Graphics2D g2) {
Rectangle r = new Rectangle(x,y,width,height);
g2.setColor(Color.BLUE);
g2.fill(r);
g2.draw(r);
path = new GeneralPath();
path.append(r,false);
g2.draw(path);
}
#Override
public void translate(int dx, int dy) {
// TODO Auto-generated method stub
x = x + dx;
y = y + dy;
}
#Override
public boolean contains(Point point) {
// TODO Auto-generated method stub
if(path == null){
return false;
}
return path.contains(point);
}
}
Here is compound shape:
import java.awt.Graphics2D;
import java.awt.Point;
public interface CompoundShape {
void draw(Graphics2D g2);
void translate(int dx, int dy);
boolean contains(Point point);
} //interface
Examples of iterating an ArrayList<Shape> can be seen in:
This answer to Get mouse detection with a dynamic shape.
This answer to 'Fill' Unicode characters in labels.
Of course, those examples are painting to an image, but once there is a Graphics (or Graphics2D as I prefer to work with) the principle is much the same. Copy/pasted from one example:
ArrayList<Shape> regions = separateShapeIntoRegions(imageShapeArea);
// ..
for (Shape region : regions) {
// ..
g.fill(region);
// ..
}
I have a Graphics object of JPanel and that is working fine:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
public class GraphicsTest extends JPanel
{
private Graphics2D g2d;
private String state;
private int x, y;
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.setClip(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
g2d.drawString("STATE: " + state, 5, 15);
g2d.drawString("Mouse Position: " + x + ", " + y, 5, 30);
g2d.setColor(Color.red);
Rectangle2D r2d = new Rectangle2D.Double(x,y,10,10);
g2d.draw(r2d);
Test t = new Test();
super.add(t);
repaint();
}
public void setState(String state) { this.state = state; }
public String getState() { return state; }
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
}
I was experimenting with a new Graphics component and when I instantiate a new Test and add it in GraphicsTest nothing happens. What is it that I am doing wrong?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
public class Test extends JComponent
{
private Graphics2D g2d;
private String state;
private int x, y;
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g2d = (Graphics2D) g.create();
g2d.setColor(Color.GREEN);
g2d.fill(new Rectangle2D.Double(60, 60,
10, 10));
repaint();
}
public void setState(String state) { this.state = state; }
public String getState() { return state; }
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
}
Thanks!
You should add Test component only once and set a layout:
public GraphicTest()
{
super();
setLayout(new BorderLayout());
add(new Test(),BorderLayout.CENTER);
}
Also, do not save Graphics2D objects because they will be invalid once paintComponent is finished and do not call repaint inside paintComponent. Use timers if you need animation and call repaint in setXXX methods that change the look of the component.