Only one object will Render to Screen - java

I'm trying to make it so that both squares appear on the JFrame but only the one that I make last in the main method apperas and the other one does not. Have been trying to figure this out for about 3 hours now and wanna smash my computer screen. Any help would be AWESOME. Thank you.
public class Main extends JFrame{
static Main main;
static Enemy square, square2;
Render render;
Main(){
render = new Render();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,500);
setResizable(false);
add(render);
}
public void render(Graphics2D g){
square.render(g);
square2.render(g);
}
public static void main(String [] args){
main = new Main();
square2 = new Square(300,50);
square = new Square(50,50);
}
}
.....
public class Render extends JPanel {
public void paintComponent(Graphics g){
super.paintComponent(g);
Main.main.render((Graphics2D)g);
}
}
......
public class Enemy {
public static int x,y;
Enemy(int x, int y){
this.x = x;
this.y = y;
}
public void render(Graphics2D g){
}
}
.......
public class Square extends Enemy {
Square(int x, int y){
super(x,y);
}
public void render(Graphics2D g){
g.setColor(Color.red);
g.fillRect(x, y, 50, 50);
}
}

Static variables belongs to classes not objects.
Using static variables for Enemy positions means that if you create any instances of Enemy class they will share the same static x, y. You have 2 squares but they are always on top of each other.
Changing public static int x, y; to public int x, y; should solve your problem.

Related

How to clear components in JPanel?

I am new to Java programming. I developing a java app, which draws shapes (circles, lines, triangles, etc) on a windows frame. I define an abstract class Shapes.java to contain the framework for shapes:
public abstract class Shapes {
public abstract void draw(Graphics g);
}
Then, I define some classes such as Circle, Line, Triangle, and Rectangle which extend from the Shapes.java class.
public class Circle extends Shapes{
private int x;
private int y;
private int radius;
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
#Override
public void draw(Graphics g) {
g.drawOval(x-radius,y-radius,radius * 2, radius *2);
}}
In my Picture.java class, I settle a JFrame and add shapes on it:
public class Picture extends JFrame {
private static final long serialVersionUID = 1L;
private int width;
private int height;
private boolean isClear = false;
private ArrayList<Shapes> listShape = new ArrayList<Shapes>();
private class ShapesPanel extends JPanel{
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(isClear)
return;
else
for (Shapes s : listShape)
s.draw(g);
}
public void add(Shapes s){
listShape.add(s);
}
public Picture(int width, int height, String title) throws HeadlessException {
ShapesPanel mypanel = new ShapesPanel();
add(mypanel);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.width = width;
this.height = height;
this.setTitle(title);
}
public void draw(){
setLocationRelativeTo(null);
setSize(width, height);
setVisible(true);
repaint();
}
void clear(){//clear the componets in the JPanel
this.setIsClear(true);
this.validate();
this.repaint();
}
private void setIsClear(boolean b) {
// TODO Auto-generated method stub
this.isClear = b;
}
}
But when I invoke the clear() method in the main class, the program cannot repaint the new shapes again. How can I fix the bugs? Thanks.
public class MyPic {
public static void main(String[] args){
Picture pic = new Picture(420, 300, "shape demo");
Circle c1 = new Circle(320,80,80);
Rectangle r1 = new Rectangle(100,100,100,100);
Triangle t1 = new Triangle(100,100,200,100,150,50);
Line l1 = new Line(0,205,400,50);
pic.add(c1);
pic.add(r1);
pic.add(t1);
pic.add(l1);
pic.clear();
pic.draw();
pic.add(l1);//add l1 again
}
}
Okay, so by calling clear() you set a variable isClear to true. And then in your paintComponent you say:
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(isClear)
return;
which means 'if isClear is true, don't paint anything' (which it is, you just set it to true with clear()). So, no wonder.
Anyway, I think in the clear method, you might want to do listShape.clear() instead of setting that boolean.

Java: Can't paint() every item from an array

I'm writing a game in which i need to paint bricks of a random color. This is my progress so far. I have a class of Brick, AllBricks, and Overridden paint method for JPanel:
private static class Brick {
static int x;
static int y;
static Color color;
Brick(int _x, int _y, Color _color){
x = _x;
y = _y;
color = _color;
}
void paint(Graphics g) {
g.setColor(Color.WHITE);
g.drawRoundRect(x, y, BRICK_SIZE, BRICK_SIZE, BRICK_ARC_SIZE, BRICK_ARC_SIZE);
g.setColor(color);
g.fillRoundRect(x + 1, y + 1, BRICK_SIZE-2, BRICK_SIZE-2, BRICK_ARC_SIZE-1, BRICK_ARC_SIZE-1);
}
private static class AllBricks {
private ArrayList<Brick> bList = new ArrayList<>();
AllBricks(){ bList.clear(); }
void add (Brick b){ bList.add(b); }
void paint(Graphics g) {
if(bList.size()>0) {
for (Brick brick : bList) brick.paint(g);
}
}
}
private static class GameField extends JPanel {
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
allBricks.paint(g);
}
}
And now, when I call my main loop, adding new blocks and trying to draw them, i only see the last added block, but not all of them...
private void loop()
{
while (true) {
delay.wait(1000);
Brick b1 = new Brick(random.nextInt(WIN_WIDTH - BRICK_SIZE), random.nextInt(WIN_HEIGHT - BRICK_SIZE), COLORS.get(random.nextInt(COLORS.size() - 1)));
allBricks.add(b1);
mainField.repaint();
}
}
Can you, please, help me save previously painted blocks on the screen?
Your brick x and y coordinate shoudn't be static. Since it's static all Bricks have one shared x and y value (so all Bricks are drawn at the same position)

How to stop the shape from disappearing when you click on new location?

I have written this code that displays a shape on a mouse click, but I have problem. When I click on new location the shape disappear on the previous one. How can I stop that from happening?
First Class:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class MouseClick {
private static int x,y;
private static DrawingObjects object = new DrawingObjects();
public static void main(String[] args){
JFrame frame = new JFrame("MouseClick");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.add(object);
object.addMouseListener(new AL());
}
static class AL extends MouseAdapter{
public void mouseClicked (MouseEvent e){
x = e.getX();
y = e.getY();
object.drawing(x, y);
}
}
}
Second Class:
import javax.swing.*;
import java.awt.*;
public class DrawingObjects extends JPanel{
private static int x,y;
public void drawing(int xx, int yy){
x = xx;
y = yy;
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(x, y, 20, 20);
}
}
The best way to handle this is to keep track of every point that's been clicked on, and redraw each one in paintComponent.
So change private static int x, y to private List<Point> points = new ArrayList<>(), and add into that instead:
public void drawing(int x, int y){
points.add(new Point(x, y));
repaint();
}
Then go through each point when you redraw:
public void paintComponent(Graphics g){
super.paintComponent(g);
for(Point p : points){
g.fillRect(p.x, p.y, 20, 20);
}
}

Draw lines, circles anything (Java)

so i'm new in stackoverflow.
I am about to create a line, a triangle anything, but i'm just focusing on the line and in a good Object orient Programming.
So i create the class Point2D:
package draw;
/**
*
* #author Pedro
*/
public class Point2D {
private int x,y;
// Construtores
public Point2D(){
this(0,0);
}
public Point2D(int x, int y){
this.x=x;
this.y=y;
}
// Set's e Get's
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;
}
Later i create the class line using the class point2D to get the starting point and final point
package draw;
/**
*
* #author Pedro
*/
public class Linha extends Figura{
private Point2D pinicial;
private Point2D pfinal;
//construtores
public Linha(int xinicial, int yinicial, int xfinal, int yfinal){
pinicial=new Point2D(xinicial, yinicial);
pfinal=new Point2D(xfinal, yfinal);
}
public Linha(Point2D pinicial, Point2D pfinal){
this.pinicial=pinicial;
this.pfinal=pfinal;
}
//Get's e Set's
public Point2D getPinicial() {
return pinicial;
}
public void setPinicial(Point2D pinicial) {
this.pinicial = pinicial;
}
public Point2D getPfinal() {
return pfinal;
}
public void setPfinal(Point2D pfinal) {
this.pfinal = pfinal;
}
}
And then i created a Jframe with a button called "line" and put it a panel inside the jFrame that is the place where its going to get the line draw.
The problems is ... I dont know how to draw the line or how should i cal it.
Can you help me?
simply, in your JPanel class ovverride paintComponent() method:
JPanel panel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g)
g.drawLine(x1, y1, x2, y2);
}
}
Where x1, y1, x2, and y2, are the cords of your line.
If you ONLY want it to draw line AFTER the button is pressed, create a global boolean variable, in your main class, and when the button is pressed, set it to true, then when you create your JPanel do:
JPanel panel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
if (myBoolean) {
super.paintComponent(g)
g.drawLine(x1, y1, x2, y2);
}
}
}
Though the advice given in the other answer is too good, but just couldn't stop myself, from adding a word or two to the same, like, in order for the painting to take place, you need to call repaint(), from inside the actionPerformed attached to JButton.
As already stated by #camickr, the use of getPreferredSize() inside the extended class for Drawing, that will provide a valid staging area, where the drawing needs to be done. This example might can help too in this direction.
Moreover, in case you wanted to keep all the lines which have been drawn on the Board so far intact, then you can simply store them in a List and iterate on this List to draw them all again, whenever a new line is to be drawn.
A simple example is as follows:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
public class LineExample {
private DrawingBoard board;
private JButton drawLineButton;
private Random random;
private ActionListener buttonAction = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
int width = board.getWidth();
int height = board.getHeight();
Line line = new Line(random.nextInt(width),
random.nextInt(height),
random.nextInt(width),
random.nextInt(height));
board.setValues(line);
}
};
public LineExample() {
random = new Random();
}
private void displayGUI() {
JFrame frame = new JFrame("Drawing Lines Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel(new BorderLayout(5, 5));
board = new DrawingBoard(400, 400);
contentPane.add(board, BorderLayout.CENTER);
drawLineButton = new JButton("LINE");
drawLineButton.addActionListener(buttonAction);
contentPane.add(drawLineButton, BorderLayout.PAGE_END);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new LineExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
class DrawingBoard extends JPanel {
private int width;
private int height;
private List<Line> lines;
public DrawingBoard(int w, int h) {
width = w;
height = h;
lines = new ArrayList<Line>();
}
public void setValues(Line line) {
lines.add(line);
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Line line : lines) {
int xs = line.getXStart();
int ys = line.getYStart();
int xe = line.getXEnd();
int ye = line.getYEnd();
g.drawLine(xs, ys, xe, ye);
}
}
}
class Line {
private Point startPoint;
private Point endPoint;
public Line(int xs, int ys, int xe, int ye) {
startPoint = new Point(xs, ys);
endPoint = new Point(xe, ye);
}
public int getXStart() {
return startPoint.getX();
}
public int getYStart() {
return startPoint.getY();
}
public int getXEnd() {
return endPoint.getX();
}
public int getYEnd() {
return endPoint.getY();
}
}
class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}

Java Dragging Drawn Balls

I have created a program which draws a circle when I click on the screen. I have it working so that I can draw as many circles as I want. I can even drag one circle and not the others if I hard code which circle I am dragging. The code is:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.List;
import java.util.ArrayList;
public class DrawBall extends JPanel implements MouseListener, MouseMotionListener {
private List<Ball> balls;
private int x, y;
private int numBalls = 0;
boolean drag = false;
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Draw Ball");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new DrawBall();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.setSize(300, 300);
frame.setVisible(true);
}
public DrawBall() {
super(new BorderLayout());
balls = new ArrayList<Ball>(10);
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RederingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for(Ball ball: balls) {
ball.paint(g2d);
}
g2d.dispose();
}
public void mouseClicked(MouseEvent event) {
x = (int) event.getPoint().getX();
y = (int) event.getPoint().getY();
Ball ball = new Ball(Color.red, numBalls, 30);
ball.setX(x);
ball.setY(y);
balls.add(ball);
numBalls = numBalls + 1;
repaint();
}
public void mousePressed(MouseEvent event) {
drag = true;
}
public void mouseReleased(MouseEvent event) {
drag = false;
}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseDragged(MouseEvent event) {
if(drag == true) {
x = (int) event.getPoint().getX();
y = (int) event.getPoint().getY();
if(event.getSource() == balls.get(0)) {
Ball ball = balls.get(0);
ball.setX(x);
ball.setY(y);
balls.set(0,ball);
}
repaing();
}
}
public void mouseMoved(MouseEvent event) {}
public class Ball {
private Color color;
private int x, y, diameter, id;
public Ball(Color color, int id, int diameter) {
setColor(color);
setID(id);
setDiameter(diameter);
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setID(int id) {
this.id = id;
}
public void setDiameter(int diameter) {
this.diameter = diameter;
}
public void setColor(Color color) {
this.color = color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getID() {
return id;
}
public int getDiameter() {
return diameter;
}
public Color getColor() {
return color;
}
protected void paint(Graphics2D g2d) {
int x = getX();
int y = getY();
g2d.setColor(getColor());
g2d.fillOval(x, y, getDiameter(), getDiameter());
}
}
}
My question is this: In my mouseDragged method, is there an easy way to tell which circle I am hovering over? I have played around with the event.getSource() but it doesn't seem to be working for my circles, at least not in the way I would expect. Thanks for any help.
Modify your Ball class so it creates a circle based on the center point and the radius, rather than the upper left point and the diameter.
Then, you can calculate if you click inside of a circle by applying the distance formula to the point you've clicked and the center point of each of the balls in turn.
The first ball where the distance is less than the radius is the ball you've clicked on. Or, if you want to be more sophisticated, the ball with the smallest distance less than the radius is the ball you've clicked on.
In this case, the event source is the JPanel, not the Ball. Try adding a System.out.println(event.getSource()); in your mouseDragged() method to see for yourself. As others have suggested, just calculate distance from the mouse pressed point to your circles. Basing it on center/radius will make the math easier.
You could modify you Ball class to take advantage of the Shape's API and use an Ellipse2D to maintain the coordinates of the circle and render it.
You could then simply use the Ellipse2D#contains to determine if the shape was clicked or not.
You will have to loop through the collection of balls checking each one until you either reach the end or find the ball you are looking for

Categories