Related
I created an application which allows instantiating shapes which can be circle rectangle or anything and used sorting technique (Bubble Sort) to sort the six shapes based on interfaces.
The problem is I am not familiar with Design patterns and what patterns are being used- I am new so i followed youtube videos and played around with it and it worked.
I have 1 main class where I have
MAIN :
public class Main {
public static void main(String[] args) {
JButton btnLoadShapes, btnSortShapes;
btnLoadShapes = new JButton("Load Shapes");
btnLoadShapes.setBounds(150, 10, 150, 30);
btnSortShapes = new JButton("Sort Shapes");
btnSortShapes.setBounds(310, 10, 150, 30);
JPanel panelShapes = new JPanel() {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Shape shape = new Shape();
g2d.setColor(Color.RED);
Square s = shape.getS();
g2d.fillRect(s.getX(),s.getY(),s.getWidth(), s.getHeight());
g2d.setColor(Color.BLUE);
Circle c = shape.getC();
g2d.fillOval(c.getX(),c.getY(), c.getWidth(), c.getHeight());
g2d.setColor(new Color(131, 21, 1));
Rectangle r = shape.getR();
g2d.fillRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
g2d.setColor(Color.PINK);
Circle C1 = shape.getC1();
g2d.fillOval(C1.getX(),C1.getY(), C1.getWidth(), C1.getHeight());
g2d.setColor(Color.green);
Square S1 = shape.getS1();
g2d.fillRect(S1.getX(),S1.getY(),S1.getWidth(), S1.getHeight());
g2d.setColor(Color.magenta);
Rectangle r2 = shape.getR2();
g2d.fillRect(r2.getX(),r2.getY(),r2.getWidth(), r2.getHeight());
}
};
panelShapes.setBounds(10, 50, 560, 500);
panelShapes.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panelShapes.setVisible(false);
btnLoadShapes.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panelShapes.setVisible(true);
}
});
and i have created 3 different classes Circle Rectangle and Square - from which i call for rectangle = shape.getC();
For example
public class Circle {
private int x, y, width, height;
public Circle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
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;
}
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;
}
}
Now the lastly I created 2 more classes called Shape and Sorting
where in shape i intiated public shape s = new Square with dimensions and set getters and setters and lastly i used sorting technique.
Can someone help me understand what are the design patterns that are being used here?
( I assume that Factory method is being used = since i defined main (* interface) and created subclasses ( Shapes rectangle circle) to instantiate.
Sorry if i sound out the place- I am just trying to understand and learn it.
A "factory" creates "something", the important thing in this context is, you don't care "how" it's created, only that it conforms to the specified type.
For example, you have a ShapeFactory which can create different shapes, you don't care "how" those shapes are defined or implemented, only that they conform to the notion of a "shape"
So, lets start with a basic concept...
public interface Shape {
public void paint(Graphics2D g2d);
}
This just defines a basic concept and states that it can be painted.
Next, we need something to create those shapes...
public class ShapeFactory {
enum ShapeType {
CIRCLE, RECTANGE, SQUARE;
}
public static Shape create(ShapeType type, int x, int y, int width, int height, Color storkeColor, Color fillColor) {
return null;
}
}
Ok, as it stands, that's pretty boring, it's only ever going to return null right now, but this gives us a basic contract.
"Please factory, create me shape of the specified type, within the specified bounds, with the specified colors"
Now, as I said, the implementation is unimportant, to the caller, and we could have a dynamic factory which could delegate the creation to other factories which could create shapes differently based on a wide ranging set of needs ... but that's getting ahead of ourselves.
Let's go about creating some actual shapes...
public abstract class AbstractShape implements Shape {
private int x;
private int y;
private int width;
private int height;
private Color storkeColor;
private Color fillColor;
public AbstractShape(Color storkeColor, Color fillColor) {
this.storkeColor = storkeColor;
this.fillColor = fillColor;
}
public AbstractShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
this(storkeColor, fillColor);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
protected void setX(int x) {
this.x = x;
}
protected void setY(int y) {
this.y = y;
}
protected void setWidth(int width) {
this.width = width;
}
protected void setHeight(int height) {
this.height = height;
}
public Color getStorkeColor() {
return storkeColor;
}
public Color getFillColor() {
return fillColor;
}
#Override
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
Color storkeColor = getStorkeColor();
Color fillColor = getFillColor();
if (fillColor != null) {
g.setColor(fillColor);
paintFilled(g);
}
if (storkeColor != null) {
g.setColor(storkeColor);
paintStroked(g);
}
g.dispose();
}
abstract protected void paintFilled(Graphics2D g2d);
abstract protected void paintStroked(Graphics2D g2d);
}
public class CircleShape extends AbstractShape {
public CircleShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(storkeColor, fillColor);
int size = Math.min(width, height);
x = x + ((width - size) / 2);
y = y + ((height - size) / 2);
setX(x);
setY(y);
setWidth(size);
setHeight(size);
}
#Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillOval(getX(), getY(), getWidth(), getHeight());
}
#Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawOval(getX(), getY(), getWidth(), getHeight());
}
}
public class SquareShape extends AbstractShape {
public SquareShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(storkeColor, fillColor);
int size = Math.min(width, height);
x = x + ((width - size) / 2);
y = y + ((height - size) / 2);
setX(x);
setY(y);
setWidth(size);
setHeight(size);
}
#Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
}
#Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
public class RectagleShape extends AbstractShape {
public RectagleShape(int x, int y, int width, int height, Color storkeColor, Color fillColor) {
super(x, y, width, height, storkeColor, fillColor);
}
#Override
protected void paintFilled(Graphics2D g2d) {
g2d.fillRect(getX(), getY(), getWidth(), getHeight());
}
#Override
protected void paintStroked(Graphics2D g2d) {
g2d.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
I always like a abstract class to carry the "common" functionality and to help make life a little simpler.
The important thing here is to note that both CircleShape and SquareShape, by their nature are, well, square (they have equal width and height). So, in this implementation, I define them to fit within the middle of the specified bounds - this is a "implementation" detail.
"But isn't that what I'm doing you?" you ask. Well, no, not really. When you call shape.getS(), for example, it's return a concrete class, which I assume has the same properties as the last object created by it, otherwise it will move all over the place.
Instead, what I'm doing is allowing you to define the properties you want the shape to have and then making it.
You want a cake? Sure, pass me the ingredients and I'll make you a cake, you still end up with a cake, but depending on the ingredients it's a different "type" of cake.
So, based on the above, we could do something like...
public class TestPane extends JPanel {
private List<Shape> shapes = new ArrayList<>(25);
public TestPane() {
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.CIRCLE, 10, 10, 200, 100, Color.RED, Color.BLUE));
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.RECTANGE, 10, 120, 200, 100, Color.BLUE, Color.GREEN));
shapes.add(ShapeFactory.create(ShapeFactory.ShapeType.SQUARE, 10, 240, 200, 100, Color.GREEN, Color.YELLOW));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(220, 350);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Shape shape : shapes) {
shape.paint(g2d);
}
g2d.dispose();
}
}
I could have made the ShapeFactory with dedicated createCircle, createRectangle and createSquare methods, I could have had them return interfaces of Circle, Square and Rectangle (and I would have based those of Shape because I'm like that) and it would still be a factory.
One of things to keep in mind is, a "factory" should be implementation independent. I should be able to make use of "different" shape factories to get different effects, but at the end of the day, they'd still just be generating Shapes
Remember, a factory will take something and it will create something from it.
I want to make an application in order to draw forms (rectangle, line, square, arrow) like in paint using Java SWT Canvas. I'm using mouse events (Up, Down and move) to get the canvas Y and X position. And i have a button for each form types that get canvas mouse position and draw the selected form using the mouse events. My problem is, when i draw the first form (Circle, square, line) everything works, but when draw the second, the first erase. How can I make the first form stay on drawn after redraw the canvas?
Variables:
private static boolean drag = false;
private Canvas compCanvas;
private Button btnSend, btnAdd,btnFreeHand,btnArrow,btnCircle,btnSquare,btnLine;
private Composite mainPanel;
compCanvas = new Canvas(mainPanel, SWT.NONE);
mouseEvents():
private void mouseEvents(){
compCanvas.addListener(SWT.MouseDown, new Listener(){
public void handleEvent(Event e){
System.out.println("Mouse event on canvas DOWN: X VALUE:"+e.x+"Y VALUE:"+e.y);
startY = e.y;
startX = e.x;
drag = true;
}
});
compCanvas.addListener(SWT.MouseUp, new Listener(){
public void handleEvent(Event e){
System.out.println("Mouse event on canvas UP: X VALUE:"+e.x+"Y VALUE:"+e.y);
endY = e.y;
endX = e.x;
drag = false;
//compCanvas.redraw();
}
});
compCanvas.addListener(SWT.MouseMove, new Listener(){
public void handleEvent(Event e){
System.out.println("Mouse event on canvas MOVE: X VALUE:"+e.x+"Y VALUE:"+e.y);
if(drag){
endY = e.y;
endX = e.x;
compCanvas.redraw();
}
}
});
};
btnSquare.selectionListener() and Declaration:
btnSquare = new Button(compSendAdd, SWT.NONE);
btnSquare.setLayoutData(new RowData(25, 25));
btnSquare.setImage(squareIcon);
btnSquare.addSelectionListener(new SelectionListener(){
private void btnSquare(){
mouseEvents();
//LightweightSystem lws = new LightweightSystem(compCanvas);
compCanvas.addListener(SWT.Paint, new Listener(){
public void handleEvent(Event e){
if(drag){
GC gc = e.gc;
//gc.setAlpha(128);
int minX = Math.min(startX,endX);
int minY = Math.min(startY,endY);
int maxX = Math.max(startX, endX);
int maxY = Math.max(startY, endY);
int width = maxX - minX;
int height = maxY - minY;
gc.fillRectangle(minX, minY,width,height);
}
}
});
}
public void widgetSelected(SelectionEvent event) {
btnSquare();
}
public void widgetDefaultSelected(SelectionEvent event) {
btnSquare();
}
});
By default controls are filled with current background color each time the SWT.Paint listener is called. You need to turn this off.
Do this by specifying the SWT.NO_BACKGROUND style on the Canvas
compCanvas = new Canvas(mainPanel, SWT.NO_BACKGROUND);
You will also need to fill the background the first time the canvas is drawn.
Create class shape with x, y, width, height fields
class Shape {
public int x; // coordiates
public int y;
public int width;
public int heigth;
String type; // "rect" for example
public Shape(int x, int y, int width, int height, String type) {
this.x = x;
this.y = y;
this.width = width;
this.heigth = height;
this.type = type;
}
}
After mouse up store your shape in list according to which button is selected
List<Shape> shapes = new ArrayList<Shape>();
shapes.add(new Shape(x, y, width, height, getType()));
In PainListener You MUST redraw all shapes from your list
for(Shape s: shapes) {
//draw shape s
}
I am tasked with how to paint an arrayList of shapes in java.
I feel i have most of it right, there are two methods i am confused about however
the method in ShapeChooserPanel called public void setPoints(int x, int y)
Since Xs and Ys are arrays, how would i set the x and y values?
And the other is one is the final method in ShapeChooserPanel I cannot find out how to print the Shapes in the array, It should paint the current shape at the place the mouse was clicked.
My code is below
Main class:
import javax.swing.JFrame;
public class Lab2 {
public static void main (String[] args) {
JFrame myFrame = new JFrame("Lab 2");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.add(new ShapeChooserPanel());
myFrame.pack();
myFrame.setVisible(true);
}
}
ShapeChooserPanel class
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
public class ShapeChooserPanel extends JPanel {
private int currentX;
private int currentY;
private Color currentColor;
private int currentShape;
private JButton clearBtn;
private JRadioButton circle, square, triangle, box;
private DrawingPanel drawingPanel;
private JPanel controlsPanel;
//constants representing shape choice
private final int CIRCLE = 0;
private final int SQUARE = 1;
private final int TRIANGLE = 2;
private final int BOX = 3;
//constant delta used for setting distance between points
private final int DELTA = 25;
private int[] Xs;
private int[] Ys;
//store all the shapes to be painted UNCOMMENT when you have Shape.java defined
ArrayList<Shape> shapes;
public ShapeChooserPanel(){
//provide some default values paints a circle at (10,10) in blue
currentX = 10;
currentY = 10;
Xs = new int[4];//we will use all 4 points for the square, but only the first 3 for the triangle
Ys = new int[4];
setPoints(currentX,currentY);
currentShape = CIRCLE;
currentColor = Color.red;
shapes = new ArrayList<Shape>();
//instantiate the controls panel and set its layout to display everything in a single column
controlsPanel = new JPanel();
controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.Y_AXIS));
//TODO: add clear button *
// TODO: define radio buttons *
clearBtn = new JButton("Clear");
clearBtn.addActionListener(new ClearListener());
circle = new JRadioButton("Red Circle");
circle.addActionListener(new ShapeListener());
square = new JRadioButton("Cyan Square");
square.addActionListener(new ShapeListener());
triangle = new JRadioButton("Green Triangle");
triangle.addActionListener(new ShapeListener());
box = new JRadioButton("Blue Box");
box.addActionListener(new ShapeListener());
ButtonGroup group = new ButtonGroup();
group.add(clearBtn);
group.add(circle);
group.add(square);
group.add(triangle);
group.add(box);
controlsPanel.add(clearBtn);
controlsPanel.add(circle);
controlsPanel.add(square);
controlsPanel.add(triangle);
controlsPanel.add(box);
//TODO: add radio buttons to group *
//TODO add listeners to radio buttons *
//TODO: add radio buttons to controls panel *
drawingPanel = new DrawingPanel();
drawingPanel.setBorder(BorderFactory.createLineBorder(Color.black));
//TODO: set a border around the drawing panel *
drawingPanel.setPreferredSize(new Dimension(200,200));
drawingPanel.addMouseListener(new PanelListener());
add(drawingPanel);
add(controlsPanel);
setPreferredSize(new Dimension (300,400));
}//end constructor
public void setPoints(int x, int y) {
//TODO: set Xs and Ys *
Xs[0] = x;
Ys[0] = y;
}
private class ClearListener implements ActionListener{
public void actionPerformed(ActionEvent ae){
shapes.removeAll(shapes);
drawingPanel.repaint();
}
}
private class PanelListener implements MouseListener {
public void mouseClicked(MouseEvent me) {
currentX = me.getX();
currentY = me.getY();
//TODO: find coordinates of this mouse click *
//TODO: add a new shape to the shapes list*
shapes.addAll(shapes);
setPoints(currentX, currentY);
//TODO: call setPoints with current x and y values *
drawingPanel.repaint();
}
public void mouseExited(MouseEvent me){}
public void mouseEntered(MouseEvent me){}
public void mouseReleased(MouseEvent me){}
public void mousePressed(MouseEvent me){}
}
//Class to listen for radio button changes
private class ShapeListener implements ActionListener{
public void actionPerformed(ActionEvent me){
//TODO: determine which radio button was clicked *
if(me.getSource() == circle){
currentShape = CIRCLE;
currentColor = Color.red;
}
if(me.getSource() == square){
currentShape = SQUARE;
currentColor = Color.cyan;
}
if(me.getSource() == triangle){
currentShape = TRIANGLE;
currentColor = Color.green;
}
if(me.getSource() == box){
currentShape = BOX;
currentColor = Color.blue;
}
//TODO: set current shape and color *
drawingPanel.repaint();
}
}
private class DrawingPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
//TODO: paint all the shapes in our list
}
}
}
and my Shape class
import java.awt.Color;
public class Shape {
private int x,y;
private int type;
private Color c;
public Shape(int x, int y, int type, Color c) {
this.x = x;
this.y = y;
this.type = type;
this.c = c;
}
public int x(int x) {
return x;
}
public int y(int y) {
return y;
}
public int type(int type) {
return type;
}
public Color c(Color c) {
return c;
}
}
super.paintComponent(g) invokes the paintComponent method from the superclass of JPanel (the JComponent class) to erase whatever is currently drawn on the panel. This is useful for animation, but not for setting color.
I guess you'll have to set the color of the shapes in your Arraylist<Shape> shapes when you will create them, nonetheless it could be helpfull to see the Shape class. Maybe you could create a function changeColor(Color ColorToBeSet) in this shape class and loop through the shapes ArrayList to call it at the end of your ShapeListener
You could...
Define an "abstract" concept of a shape, which has the basic properties (location and size) and which can paint itself...
public abstract class Shape {
private int x, y;
private int width, height;
private Color c;
public Shape(int x, int y, int width, int height, Color c) {
this.x = x;
this.y = y;
this.c = c;
this.width = width;
this.height = height;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Color getColor() {
return c;
}
public abstract void paint(Graphics2D g2d);
}
Then you can implement the individual shapes...
public class Rectangle extends Shape {
public Rectangle(int x, int y, int width, int height, Color c) {
super(x, y, width, height, c);
}
#Override
public void paint(Graphics2D g2d) {
g2d.setColor(getColor());
g2d.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
public class Oval extends Shape {
public Oval(int x, int y, int width, int height, Color c) {
super(x, y, width, height, c);
}
#Override
public void paint(Graphics2D g2d) {
g2d.setColor(getColor());
g2d.drawOval(getX(), getY(), getWidth(), getHeight());
}
}
Then, you can simply call the paint method of each instance of Shape as required...
public class TestPane extends JPanel {
private List<Shape> shapes;
public TestPane() {
shapes = new ArrayList<>(25);
shapes.add(new Rectangle(10, 10, 20, 20, Color.RED));
shapes.add(new Oval(15, 15, 40, 20, Color.RED));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Shape shape : shapes) {
Graphics2D g2d = (Graphics2D) g.create();
shape.paint(g2d);
g2d.dispose();
}
}
}
I am working on a lab to practice inheritance, in which we are to create a horizontal ellipse as "Shape1" and then create a "Shape2" which extends Shape1 which draws it's superclass Shape1, and then draws a vertical ellipse over top to create a new looking shape. The shape is displaying fine in terms of inheritance and looks (color/location etc) however when running the program, the frame width is set to 1000, and the height is set to 700, but If I drag the frame by the corner to enlarge it, the shape is drawn over and over again as I keep dragging the frame larger. Ideally the shape should just stay where it is relative to the frame size. I think this is happening because while I drag the frame larger, the draw method is being called over and over again by the system, but I am not sure where this is happening or how to fix it. Any suggestions?
All classes are displayed below:
Shape1:
public class Shape1 {
private double x, y, r;
protected Color col;
private Random randGen = new Random();
public Shape1(double x, double y, double r) {
this.x = x;
this.y = y;
this.r = r;
this.col = new Color(randGen.nextFloat(), randGen.nextFloat(), randGen.nextFloat());
}
public double getX() {
return this.x;
}
public double getY() {
return this.y;
}
public double getR() {
return this.r;
}
public void draw(Graphics2D g2){
//Create a horizontal ellipse
Ellipse2D horizontalEllipse = new Ellipse2D.Double(x - 2*r, y - r, 4 * r, 2 * r);
g2.setPaint(col);
g2.fill(horizontalEllipse);
}
}
Shape2:
public class Shape2 extends Shape1 {
public Shape2(double x, double y, double r) {
super(x, y, r);
}
public void draw(Graphics2D g2) {
//Create a horizontal ellipse
Ellipse2D verticalEllipse = new Ellipse2D.Double(super.getX() - super.getR(),
super.getY() - 2*super.getR(),
2 * super.getR(), 4 * super.getR());
super.draw(g2);
g2.fill(verticalEllipse);
}
}
ShapeComponent:
public class ShapeComponent extends JComponent {
//Instance variables here
private Random coordGen = new Random();
private final int FRAME_WIDTH = 1000;
private final int FRAME_HEIGHT = 700;
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Shape2 myShape = new Shape2(1 + coordGen.nextInt(FRAME_WIDTH), 1 + coordGen.nextInt(FRAME_HEIGHT), 20);
//Draw shape here
myShape.draw(g2);
}
}
ShapeViewer(Where the JFrame is created):
public class ShapeViewer {
public static void main(String[] args) {
final int FRAME_WIDTH = 1000;
final int FRAME_HEIGHT = 700;
//A new frame
JFrame frame = new JFrame();
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Lab 5");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ShapeComponent component = new ShapeComponent();
frame.add(component);
//We can see it!
frame.setVisible(true);
}
}
because while I drag the frame larger, the draw method is being called over and over again by the system,
Correct, all components are repainted when the frame is resized.
Any suggestions?
Painting code should be based on properties of your class. If you want the painting to be a fixed size then you define the properties that control the painting and set these properties outside the painting method.
For example, you would never invoke Random.nextInt(...) in the painting method. This means the value will change every time the component is repainted.
So the Shape should be created in the constructor of your class and its size would be defined there, not each time you paint it.
i'm trying to make a rectangle in Java, done. I can also fill it in with solid colour, done. But I want to actually change the solid colour of the shape itself. I know with Graphics you can use g.setColor(); but I have had my component setup a special way as shown below:
public class Design extends JComponent {
private static final long serialVersionUID = 1L;
private List<Shape> shapesDraw = new ArrayList<Shape>();
private List<Shape> shapesFill = new ArrayList<Shape>();
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int screenWidth = gd.getDisplayMode().getWidth();
int screenHeight = gd.getDisplayMode().getHeight();
public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for(Shape s : shapesDraw){
g2d.draw(s);
}
for(Shape s : shapesFill){
g2d.fill(s);
}
}
public void drawRect(int xPos, int yPos, int width, int height) {
shapesDraw.add(new Rectangle(xPos, yPos, width, height));
repaint();
}
public void fillRect(int xPos, int yPos, int width, int height) {
shapesFill.add(new Rectangle(xPos, yPos, width, height));
repaint();
}
public void drawTriangle(int leftX, int topX, int rightX, int leftY, int topY, int rightY) {
shapesDraw.add(new Polygon(
new int[]{leftX, topX, rightX},
new int[]{leftY, topY, rightY},
3));
repaint();
}
public void fillTriangle(int leftX, int topX, int rightX, int leftY, int topY, int rightY) {
shapesFill.add(new Polygon(
new int[]{leftX, topX, rightX},
new int[]{leftY, topY, rightY},
3));
repaint();
}
public Dimension getPreferredSize() {
return new Dimension(screenWidth, screenHeight);
}
public int getWidth() {
return screenWidth;
}
public int getHeight() {
return screenHeight;
}
}
As you can see, instead of just drawing and filling, it uses a list to draw off of that. Is there a way I can change the colour inside the list< shape >? I preferably want the colour to be changeable inside each draw/fill shape.
Thanks for the help.
Updated from answer:
My class as follows from your ShapeWrapper example:
public class Design extends JComponent {
private static final long serialVersionUID = 1L;
private List<ShapeWrapper> shapesDraw = new ArrayList<ShapeWrapper>();
private List<ShapeWrapper> shapesFill = new ArrayList<ShapeWrapper>();
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int screenWidth = gd.getDisplayMode().getWidth();
int screenHeight = gd.getDisplayMode().getHeight();
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for(ShapeWrapper s : shapesDraw){
g2d.setColor(s.color);
g2d.draw(s.shape);
}
for(ShapeWrapper s : shapesFill){
g2d.setColor(s.color);
g2d.fill(s.shape);
}
}
public void drawRect(int xPos, int yPos, int width, int height) {
shapesDraw.add(new Rectangle(xPos, yPos, width, height));
repaint();
}
public void fillRect(int xPos, int yPos, int width, int height) {
shapesFill.add(new Rectangle(xPos, yPos, width, height));
repaint();
}
public void drawTriangle(int leftX, int topX, int rightX, int leftY, int topY, int rightY) {
shapesDraw.add(new Polygon(
new int[]{leftX, topX, rightX},
new int[]{leftY, topY, rightY},
3));
repaint();
}
public void fillTriangle(int leftX, int topX, int rightX, int leftY, int topY, int rightY) {
shapesFill.add(new Polygon(
new int[]{leftX, topX, rightX},
new int[]{leftY, topY, rightY},
3));
repaint();
}
public Dimension getPreferredSize() {
return new Dimension(getWidth(), getHeight());
}
public int getWidth() {
return screenWidth;
}
public int getHeight() {
return screenHeight;
}
}
class ShapeWrapper {
Color color;
Shape shape;
public ShapeWrapper(Color color , Shape shape){
this.color = color;
this.shape = shape;
}
}
Now I am coding in Eclipse and everything works fine except for ONE thing!!
Every time it says shapesDraw/shapesFill.add() it says:
The method add(ShapeWrapper) in the type List is not applicable for the arguments (Rectangle)
So close! Please respond.
You can use something like:
private class ShapeWrapper {
private Color color;
private Shape shape;
public ShapeWrapper(Color color , Shape shape){
this.color = color;
this.shape = shape;
}
}
instead of plain Shape for storing Shape+Color.
And paint them like next :
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for(ShapeWrapper s: shapesDraw){
g2d.setColor(s.color);
g2d.draw(s.shape);
}
for(ShapeWrappers s : shapesFill){
g2d.setColor(s.color);
g2d.fill(s.shape);
}
}
EDIT: according your exception, you try to add to typed list(ShapeWrapper) an object of another class(Shape), fix your methods like next :
public void drawRect(int xPos, int yPos, int width, int height) {
ShapeWrapper wr = new ShapeWrapper(Color.RED,new Rectangle(xPos, yPos, width, height));
shapesDraw.add(wr);
repaint();
}