Reputation: 55
Right now I have a program that can move a rectangle left and right. I would like to make a JComboBox to change the shape and color of the object.
public class DrawShapes extends JFrame{
//code
private CanvasDrawArea canvas; // the custom drawing canvas (extends JPanel)
/** Constructor to set up the GUI */
public DrawShapes() {
// Panel for JComboBox and buttons
JPanel btnPanel = new JPanel(new FlowLayout());
JComboBox shapes = new JComboBox(shapeName);
btnPanel.add(shapes);
//code for left/right buttons
}
}
So above is the class that contains everything and the constructor that sets up the GUI. I also have an inner class that creates the shape
class CanvasDrawArea extends JPanel {
public void paintComponent(Graphics rect) {
super.paintComponent(rect);
setBackground(CANVAS_BACKGROUND);
rect.setColor(Color.BLUE);
rect.fillRect(x1, y1, rectWidth, rectHeight); //these int are defined earlier
}
}
I thought if I wanted to change the shape with the JComboBox, I would need to place the ActionListener for the JComboBox in the CanvasDrawArea class (the inner class). But if I do that, I can't add the shape JComboBox in the btnPanel. So how would I change the shape and color of the object being moved?
Here is the full code as of writing this question in case someone wants to look at it.
Edit: This is my current JPanel for my buttons. I only copied the code for the combo box.
JPanel btnPanel = new JPanel(new FlowLayout());
JComboBox shapes = new JComboBox(shapeName);
shapes.setSelectedIndex(1);
btnPanel.add(shapes);
shapes.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource(); //copies shapes combo box
String msg = (String)cb.getSelectedItem();
switch(msg){
case "Rectangle":
Rectangle blueRect = new Rectangle(x1, y1, rectWidth, rectHeight, blue);
canvas.add(blueRect);
repaint();
case "Circle":
Circle blueCirc = new Circle(x2, y2, circWidth, circHeight, blue);
canvas.add(blueCirc);
repaint();
}//switch end
}//method end
}); //action listener end
And here's my current Rectangle Class
public Rectangle(int x, int y, int width, int height, Color color) {
setLocation(x, y);
setSize(width, height);
setColor(color);
}
@Override
public void paint(Graphics g) {
g.setColor(getColor());
g.fillRect(getX(), getY(), getWidth(), getHeight());
}
My Circle
class is the same as my Rectangle
class. But when I run the app, only the rectangle shows up and is no longer able to be moved.
Upvotes: 0
Views: 2369
Reputation: 347332
CanvasDrawArea
to allow it to accept different instances of this "shape" and repaint itself.JComboBox
and place it within the same container as the CanvasDrawArea
, but not within it. When the user changes the selection, tell the instance of the CanvasDrawArea
to change the shape accordingly...The core concept is, the CanvasDrawArea
is responsible for drawing the shape, that's it. You allow the shape to be changed by some means, via a series of setters and getters, which provides flexibility, but doesn't tie you into a given mechanism (so that the only to change the shape is by triggering an ActionEvent
), but allows you to change the way in which the shape changing mechanism works (such as via a random selection, radio buttons or list for example)
For example...
class CanvasDrawArea extends JPanel {
//...
private MyShape shape;
//..
public void setShape(MyShape shape) {
this.shape = shape;
repaint();
}
public MyShape getShape() {
return shape;
}
//...
public void paintComponent(Graphics rect) {
super.paintComponent(rect);
MyShape shape = getShape();
if (shape != null) {
shape.paint(rect);
}
}
}
paint
method, for example; setBackground(CANVAS_BACKGROUND);
is a really bad idea. This will schedule another repaint which could cause the repaint manager to repeatedly repaint your component, consuming your CPU. Instead you should have been setting this values before hand, perhaps in the constructor...Start by defining the concept of a "shape" and define it's requirements, for example...
public interface MyShape {
public void setLocation(int x, int y);
public void setSize(int width, int height);
public void setColor(Color color);
public int getX();
public int getY();
public int getWidth();
public int getHeight();
public Color getColor();
public void paint(Graphics g);
}
The create the actual implementations, for example...
public abstract class AbstractShape implements MyShape {
private int x, y;
private int width, height;
private Color color;
@Override
public void setLocation(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public void setSize(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public int getWidth() {
return width;
}
@Override
public int getHeight() {
return height;
}
@Override
public void setColor(Color color) {
this.color = color;
}
@Override
public int getX() {
return x;
}
@Override
public int getY() {
return y;
}
@Override
public Color getColor() {
return color;
}
}
public class Rectangle extends AbstractShape {
public Rectangle() {
}
public Rectangle(int x, int y, int width, int height, Color color) {
setLocation(x, y);
setSize(width, height);
setColor(color);
}
@Override
public void paint(Graphics g) {
g.setColor(getColor());
g.drawRect(getX(), getY(), getWidth(), getHeight());
}
}
Where possible, always deal with the interface
, this means that when you create more shapes, it will be easier to integrate them
Upvotes: 4
Reputation:
Well firstly it depends if you want it to change shape automatically or when a action happens. If it's auto for the location set up a TimerTask loop and make a var as the x or y and add to it
int xLoc = 0
Then xLoc = xLoc + 1;
For changing the colour well in your graphics have a int colour = 1; then have if statements if it is 1 set to green if it's 2 blue ect. The way to make this update is to repaint() in your TimerTask
Timer timer = new Timer();
Upvotes: 0
Reputation: 136
Right now it seems like you're just painting and moving the entire canvas rather than moving a shape. In order to change the shape from a rectangle you're going to need to put a shape into your canvas. At that point you can change the shape by swapping in different shape instances.
Using a factory pattern you can get an instance of a new shape just by passing in a string: http://www.oodesign.com/factory-pattern.html
You're then going to also need to keep track of a "current shape" object since the instance will be changing. This will require the proxy pattern to delegate move and color change actions to: http://java.dzone.com/articles/design-patterns-proxy
Upvotes: 0