hello, I am trying to draw a circle by using paintComponent - java

circle class
This is a simple circle class with only with a constructor.
public class Circle {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public double getArea() {
return Math.PI * radius * radius;
}
#Override
public String toString() {
return "cicle [radius=" + radius + ", getRadius()=" + getRadius() + ", getArea()=" + getArea() + ", getClass()="
+ getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]";
}
}
Rock class
This is Rock class extends JPanel, that only have circle as variable. and overridden paintComponent.
import javax.swing.*;
import java.awt.*;
public class Rock extends JPanel {
private Circle circle;
public Rock(Circle circle) {
this.circle=circle;
}
public Circle getCircle() {
return circle;
}
public void setCircle(Circle circle) {
this.circle = circle;
}
#Override
public void paintComponent(Graphics j) {
super.paintComponent(j);
j.setColor(Color.black);
int radius=new Circle(100).getRadius();
j.fillOval(5, 5, radius, radius);
}
/*
* public void paintcomponent(Graphics g) { super.paintComponent(g);
* g.setColor(Color.black); int radius=new Circle(100).getRadius();
* g.fillOval(0, 0, radius, radius); }
*/
}
Gui Stuff
This is the class where I was trying to construct everything.
but when I added the Rock object to the layout, it would not appear.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class Gui extends JFrame implements ActionListener {
JFrame topFrame = null;
GridBagLayout grid=new GridBagLayout();
GridBagConstraints cons=new GridBagConstraints();
Graphics j;
Circle circle=new Circle(100);
Rock rock;
public Gui() {
rock=new Rock(circle);
RockGold h=new RockGold(circle);
JLabel lblResult=new JLabel(" Result ");
this.setLayout(grid);
cons=new GridBagConstraints();
cons.gridx=1;
cons.gridy=7;
cons.insets=new Insets(10,10,10,0);
this.add(rock,cons);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Main
This is the main with frames settings.
import javax.swing.JFrame;
public class main {
public static void main(String[] args) {
Gui gui=new Gui();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(900, 900);
gui.setVisible(true);
}
}

Here are some tips on how to draw a circle.
create a class extending JPanel
create an instance of JFrame-- Do not subclass it
add the JPanel to the JFrame.
override paintComponent in your panel (like you have been doing).
simply call fillOval() or drawOval() with the appropriate arguments.
Note the use of rendering hints below.
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// the following will visually smooth the edges.
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
g2d.fillOval(5,5, 100,100);
}
Please check out painting in the Java Tutorials

Related

Why is only one ball being drawn? There should be many more

I'm trying to have an ArrayList of Ball objects, and I want to draw them to the screen, but only one of them gets drawn and I don't know why.
Ball class:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.util.Random;
public class Ball extends JPanel{
int sX,sY;
Color color;
int speed;
int height;
int width;
int velX=0;
int velY=0;
Random randInt;
JFrame window;
public Ball(int sX,int sY,int height,int width){
this.sX=sX;
this.sY=sY;
this.color=color;
this.speed=speed;
this.height=height;
this.width=width;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;
g2d.setColor(color.RED);
Ellipse2D ellipse = new Ellipse2D.Double(sX,sY,width,height);
g2d.fill(ellipse);
}
public String getCoords(){
return "X: "+String.valueOf(sX)+" Y: "+String.valueOf(sY);
}
}
BallManager class (where it stores the arraylist of ball objects)
import javax.swing.*;
import java.util.ArrayList;
public class BallManager {
ArrayList<Ball> listOfBalls;
int width,height;
JFrame window;
Ball newBall;
public BallManager(JFrame window) {
this.listOfBalls=new ArrayList<Ball>();
this.window=window;
this.addBalls(100);
//this.drawBalls();
}
public void addBalls(int n){
for (int y=0;y<n;y+=20){
for(int x=0;x<n;x+=20){
this.listOfBalls.add(new Ball(x,y,10,10));
drawBalls();
}
}
System.out.println(listOfBalls.size());
}
public void drawBalls(){
for(Ball b:listOfBalls){
window.add(b);
System.out.println(b.getCoords());
}
}
}
Main class:
public class Main {
public static void main(String[] args){
JFrameWindow j= new JFrameWindow(300,500);
BallManager bm=new BallManager(j);
}
}
Window Class:
import javax.swing.*;
import java.awt.*;
public class JFrameWindow extends JFrame {
int width;
int height;
public JFrameWindow(int width,int height){
super("JFrame ballssssss");
this.width=width;
this.height=height;
this.setLocationRelativeTo(null);
this.setSize(this.width,this.height);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setVisible(true);
this.getContentPane().setBackground(Color.orange);
}
}
I have no clue what the problem is. It seems to me that the balls in the arraylist move in unison with each other but I don't know why.
You've got some things a little backwards:
The Ball class should not extend from JPanel nor any other Swing component. Instead it should be a logical class, one that knows the location, color of a ball and how to draw it, in a method, say public void draw(Graphics g).
There should be only one JPanel that holds the logical Balls in an ArrayList<Ball>, and draws them all within its paintComponent method via a for-loop.
This single JPanel should be added to the JFrame, BorderLayout.CENTER.
e.g.,
public class Ball {
private static final int RADIUS = 5;
private int x;
private int y;
private Color color;
// constructors
// getters / setters
// methods to move the ball
// or might use Graphics2D and rendering hints to smooth drawing
public void draw(Graphics g) {
g.setColor(color);
g.fillOval(x - RADIUS, y - RADIUS, 2 * RADIUS, 2 * RADIUS);
}
}
and
class BallPanel extends JPanel {
private List<Ball> balls = new ArrayList<>();
// constructor -- fill the balls list
// other methods....
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball ball : balls) {
ball.draw(g);
}
}
}

Draw Randomly-Sized Shape from User JList Selection of Shapes in Java GUI

I have to produce a randomly-sized shape (from 50 to 300 pixels) in a java GUI. There is a JList of 3 shapes (rectangle, square, circle) that the user can choose from, and when they choose one, a randomly-sized rectangle, square, or circle should appear in the GUI.
I guess I'm just having trouble figuring out where and how to implement the list selection listeners.
Here is my code so far:
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
public class ShapeSelectionWindow extends JPanel implements ListSelectionListener{
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
width = (int)Math.floor(Math.random()*250) + 50;
height = (int)Math.floor(Math.random()*250) + 50;
x = (int)Math.floor((615 - width) / 2);
y = (int)Math.floor((661 - height) / 2);
g.fillRect(x, y, width, height);
}
public static void main(String[] args) {
ShapeSelectionWindow ssw = new ShapeSelectionWindow();
JFrame jf = new JFrame();
JPanel shapeListPanel = new JPanel();
shapeListPanel.setBackground(Color.WHITE);
DefaultListModel<String> dlm = new DefaultListModel<String>();
dlm.addElement("Rectangle");
dlm.addElement("Square");
dlm.addElement("Circle");
JList<String> shapeList = new JList<String>(dlm);
shapeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
shapeListPanel.add(shapeList);
jf.getContentPane().setLayout(new BorderLayout());
jf.getContentPane().add(ssw, BorderLayout.CENTER);
jf.getContentPane().add(shapeListPanel, BorderLayout.EAST);
jf.setTitle("Simple Drawing GUI");
jf.setSize(700, 700);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
#Override
public void valueChanged(ListSelectionEvent e) {
// TODO Auto-generated method stub
}
}
The current paintComponent method is for painting a rectangle. Like I said, I'm not sure how to implement the list selection listeners for this project in order to produce different shapes based on the user's selection.
Your current approach is placing too many eggs in a single basket. Why would ShapeSelectionWindow be responsible for managing the JList? It's sole responsibility is to draw a random shape.
Instead, you should break your design down.
I would start by defining a simple "shape" entity...
public enum Shape {
RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
private String name;
private Shape(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
This just provides a limit set of options which can be used.
I would then update the "shape pane" to support these options...
public class ShapePane extends JPanel {
private Shape shape;
public void setShape(Shape shape) {
this.shape = shape;
repaint();
}
public Shape getShape() {
return shape;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
Shape shape = getShape();
if (shape == null) {
return;
}
width = (int) Math.floor(Math.random() * 250) + 50;
height = (int) Math.floor(Math.random() * 250) + 50;
x = (int) Math.floor((615 - width) / 2);
y = (int) Math.floor((661 - height) / 2);
switch (shape) {
case RECTANGLE:
g.fillRect(x, y, width, height);
break;
case SQUARE:
break;
case CIRCLE:
break;
}
}
}
The ShapePane doesn't care "how" the Shape is specified, it only cares when it changes and wants to paint it
I would then use another component to act as the primary controller between the JList and the ShapePane...
public class MainPane extends JPanel {
private JList<Shape> list;
private ShapePane shapePane;
public MainPane() {
setLayout(new BorderLayout());
DefaultListModel<Shape> model = new DefaultListModel<>();
model.addElement(Shape.SQUARE);
model.addElement(Shape.RECTANGLE);
model.addElement(Shape.CIRCLE);
shapePane = new ShapePane();
list = new JList<Shape>(model);
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
Shape shape = list.getSelectedValue();
shapePane.setShape(shape);
}
});
add(list, BorderLayout.WEST);
add(shapePane, BorderLayout.CENTER);
}
}
Runnable Example...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Shape {
RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
private String name;
private Shape(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
public class MainPane extends JPanel {
private JList<Shape> list;
private ShapePane shapePane;
public MainPane() {
setLayout(new BorderLayout());
DefaultListModel<Shape> model = new DefaultListModel<>();
model.addElement(Shape.SQUARE);
model.addElement(Shape.RECTANGLE);
model.addElement(Shape.CIRCLE);
shapePane = new ShapePane();
list = new JList<Shape>(model);
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
Shape shape = list.getSelectedValue();
shapePane.setShape(shape);
}
});
add(list, BorderLayout.WEST);
add(shapePane, BorderLayout.CENTER);
}
}
public class ShapePane extends JPanel {
private Shape shape;
public void setShape(Shape shape) {
this.shape = shape;
repaint();
}
public Shape getShape() {
return shape;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
public void paintComponent(Graphics g) {
int x, y, width, height;
super.paintComponent(g);
Shape shape = getShape();
if (shape == null) {
return;
}
width = (int) Math.floor(Math.random() * 250) + 50;
height = (int) Math.floor(Math.random() * 250) + 50;
x = (int) Math.floor((615 - width) / 2);
y = (int) Math.floor((661 - height) / 2);
switch (shape) {
case RECTANGLE:
g.fillRect(x, y, width, height);
break;
case SQUARE:
break;
case CIRCLE:
break;
}
}
}
}

JAVA, GUI JPanel, JFrame, paintComponent, Graphics

Regarding your comment to change add public display(Graphics g)
[link]http://www3.canyons.edu/Faculty/biblej/project6.html
1.)Project6 class will have to extend the JFrame class
2.)Project6 constructor will have to set up the GUI window.
3.)A new abstract method: public void display(Graphics g); should be added to the base and derived classes
4.)A custom JPanel must be set up with a paintComponent method
5.)The new display(Graphics g) method will have to draw the shapes on the GUI window and be called from a loop in the paintComponent method
public class Project6 extends JFrame {
//project6 constructor without parameters to set up new JFrame
public Project6() {
add(new NewPanel());
}
class NewPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//So do I need to add Graphics g here? or no?
for(int i = 0; i < thearray.length && thearray[i] != null; i++) {
thearray[i].display(**Graphics g**);
}}}
public static void main (String [] args) {
JFrame frame = new JFrame();
frame.setSize(800, 700);
frame.setTitle("Shapes");
frame.setLocationRelativeTo(null); //Center Frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Here is one of classes for example, Do I add it to the end like this? and do I need to add a public abstract void display(Graphics g) to the Shape parent class? and how would it call in the project6 class?
public class Rectangle extends Shape {
private int width;
private int height;
public Rectangle() {
setWidth(0);
setHeight(0);
setXPos(0);
setYPos(0);}
public Rectangle(int xPos, int yPos, int height, int width) {
setWidth(xPos);
setHeight(yPos);
setXPos(height);
setYPos(width);}
public int getWidth() {
return width;}
public void setWidth(int width) {
this.width = width;}
public int getHeight() {
return height;}
public void setHeight(int height) {
this.height = height;}
#Override
public void display() {
System.out.println("Rectangle: (" + getXPos() + ", " + getYPos() + ") " + " Height: " + height + " Width: " + width);}
#Override
public void display(Graphics g) {
g.drawRect(getXPos(), getYPos(), width, height); }
A new abstract method: public void display(Graphics g); should be added to the base and derived classes
You haven't done this step correctly because I notice that you are calling thearray[i].display(); when display is intended to have a parameter.
If you create the display method correctly, then you are handed the Graphics object that you can use, for example:
class Line extends Shape {
int x1, y1, x2, y2;
#Override
public void display(Graphics g) {
g.drawLine(x1, y1, x2, y2);
}
}

Graphics does not draw when used with polymorphism

I created interface Shape. Then I created two classes - Circle and Rectangle that implement Shape. . Then I wrote a class to use these shapes. When I try to draw a rectangle or a circle only, i see a window with the shape drawn. But when I try to draw both, only the first called shape is drawn. The second window shows but without the drawing in it. How can I get both shapes to be visible? What mistake am I doing? I am showing the Shape interface, Circle class and UseShapes class that contains main below. Rectangle class is similar to Circle.
public interface Shape
{
public void drawShape();
public double area();
}
import java.awt.*;
import java.awt.event.*;
public class Circle implements Shape
{
Frame fr;
int r;
final double PI = 3.141;
public Circle(int radius)
{
r = radius;
fr = new Frame("Circle");
fr.setBounds(300, 20, r + 200, r+ 300);
fr.addWindowListener(new WListener());
fr.setBackground(Color.cyan);
}
public void drawShape()
{
fr.setVisible(true);
Graphics g = fr.getGraphics();
g.setColor(Color.red);
g.drawOval(75, 75, r, r);
String ar = "Area of this Circle = " + area();
g.drawString(ar, 20,200);
}
public double area()
{
double ar = PI * r * r;
return ar;
}
class WListener extends WindowAdapter
{
#Override
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
#Override
public void windowClosed(WindowEvent we)
{
System.exit(0);
}
}
}
public class UseShapes
{
public static void main(String a[])
{
Shape sr;
// show a circle
sr = new Circle(100);
sr.drawShape();
//show Rectangle
sr = new Rectangle(70, 100);
sr.drawShape();
}
}

Paint ArrayList of Shape Objects to Frame

I'm having difficulty with drawing Shapes (Circle & Rectangle) into a Frame.
I have created both a Circle and a Rectangle Class that implements the Shape Interface. I have then created DrawableCircle and DrawableRectangle Classes that extend the Circle and Rectangle Classes appropriately, and implement the Drawable Interface.
I am now trying to create a ShapesDriver Class which extends Frame and has within it the main method and paint(Graphics g) method. Within ShapesDriver I need to create an ArrayList of type Drawable. This ArrayList holds an instance of DrawableCircle and DrawableRectangle. In the paint method I have to iterate through the ArrayList and invoke the draw method for each shape.
This is where I am stuck...
Any help would be appreciated!
Shape Interface
public interface Shape {
public double area();
}
Circle Class
public class Circle implements Shape{
private int radius;
private double area;
public Circle(int r){
radius = r;
}
#Override
public double area() {
area = Math.PI * (radius * radius);
return area;
}
}
Rectangle Class
public class Rectangle implements Shape{
double height;
double width;
double area;
public Rectangle(double h, double w){
height = h;
width = w;
}
#Override
public double area() {
area = height * width;
return area;
}
}
Drawable Interface
import java.awt.Color;
import java.awt.Graphics;
public interface DrawableInterface {
public void setColor(Color c);
public void setPosition(int x, int y);
public void draw(Graphics g);
}
DrawableCircle
import java.awt.Color;
import java.awt.Graphics;
public class DrawableCircle extends Circle implements DrawableInterface{
private Color col;
private int posX;
private int posY;
public DrawableCircle(int r){
super(r);
}
#Override
public void setColor(Color c) {
col = c;
}
#Override
public void setPosition(int x, int y) {
posX = x;
posY = y;
}
#Override
public void draw(Graphics g) {
g.setColor(col);
g.drawOval(posX, posY, 15, 15);
}
}
DrawableRectangle
import java.awt.Color;
import java.awt.Graphics;
public class DrawableRectangle extends Rectangle implements DrawableInterface{
private Color col;
private int posX;
private int posY;
public DrawableRectangle(double h, double w){
super(h, w);
}
#Override
public void setColor(Color c) {
col = c;
}
#Override
public void setPosition(int x, int y) {
posX = x;
posY = y;
}
#Override
public void draw(Graphics g) {
g.setColor(col);
g.drawRect(posX,posY,10,10);
}
}
ShapesDriver
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
public class ShapesDriver extends Frame {
static ArrayList<DrawableInterface> shapesArr = new ArrayList<DrawableInterface>();
public ShapesDriver() {
super("Shapes Object Array");
setSize(400, 300);
setLocation(200, 200);
setVisible(true);
}
public static void main(String[] args) {
DrawableCircle c = new DrawableCircle(500);
c.setColor(Color.GREEN);
c.setPosition(25, 25);
DrawableRectangle r = new DrawableRectangle(100, 50);
r.setColor(Color.RED);
r.setPosition(75, 75);
shapesArr.add(c);
shapesArr.add(r);
ShapesDriver shapeFrame = new ShapesDriver();
shapeFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
#Override
public void paint(Graphics g) {
for (DrawableInterface s : shapesArr) {
super.paint(g);
s.draw(g);
}
}
}
"This is where I am stuck..." -- where are you stuck exactly?
Myself, I would:
use a Swing GUI not an AWT GUI since Swing is much more powerful and flexible than AWT. There's almost never a need to create AWT GUI's.
Your GUI class, ShapesDriver does nothing. It extends Frame, but you never create an instance of the ShapesDriver. Instead it has a main method where you create a separate Frame. In my GUI code, I'd create a true GUI class, that had instance fields and methods, and would be sure to create an instance of this class somewhere.
In my GUI class I'd have my ArrayList of Shape and my drawing method, and would loop through the ArrayList within the drawing method, drawing each shape as I looped.
Since I would favor using Swing, my GUI class would extend JPanel, and my drawing method would be a paintComponent(Graphics g) method. If you're required to use AWT, then you could instead use a Panel and draw in its paint(Graphics g) method.
I'd then have a main method that creates the GUI, makes it visible, and does nothing else.

Categories

Resources