I know its a lot of code but I could really use some help identifying my problem. Thank you!
I am just now being introduced to inheritance and am challenging myself with this application to a painting program. The program is meant to draw different shapes (lines, oval, rectangles, etc.) and I used trial and error to get what I have so far. I no longer am getting errors but the program only shows a black screen. Changing colors doesn’t seem to do anything so I think it has something to do with my color variable.
This is the main class:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.io.*;
class Main extends JFrame implements ActionListener
{
// the draw panel
JPanel content;
CustomPanel contentCustom;
String filename = "";
File file = null;
// Menu Bar
JMenuBar bar;
// file menu
JMenu fileMenu;
JMenuItem openItem;
JMenuItem saveItem;
JMenuItem exitItem;
// mode menu
JMenu modeMenu;
JMenuItem lineItem;
JMenuItem rectItem;
JMenuItem ellipseItem;
JMenuItem freeItem;
// color menu
JMenu colorMenu;
JMenuItem colorItem;
public Main()
{
super("Paint - Line Mode Color="+Color.BLUE );
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create the menu bar
bar = new JMenuBar();
// create the menus
fileMenu = new JMenu("File");
fileMenu.setMnemonic('F'); // Alt F
modeMenu = new JMenu("Mode");
colorMenu = new JMenu("Color");
// **** create the menu items
// file menu items
saveItem = new JMenuItem("Save");
saveItem.setMnemonic('s');
saveItem.addActionListener(this);
openItem = new JMenuItem("Open");
openItem.setMnemonic('o');
openItem.addActionListener(this);
exitItem = new JMenuItem("Exit");
exitItem.setMnemonic('x');
exitItem.addActionListener(this);
// mode menu items
lineItem = new JMenuItem("Line");
lineItem.addActionListener(this);
rectItem = new JMenuItem("Rectangle");
rectItem.addActionListener(this);
ellipseItem = new JMenuItem("Ellipse");
ellipseItem.addActionListener(this);
freeItem = new JMenuItem("Free Draw");
freeItem.addActionListener(this);
// color menu items
colorItem = new JMenuItem("Color");
colorItem.addActionListener(this);
// **** add menu items to the menus
// fileMenu
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.addSeparator();
fileMenu.add(exitItem);
// modeMenu
modeMenu.add(lineItem);
modeMenu.add(rectItem);
modeMenu.add(ellipseItem);
modeMenu.add(freeItem);
// colorMenu
colorMenu.add(colorItem);
// **** add the menus to the bar
bar.add(fileMenu);
bar.add(modeMenu);
bar.add(colorMenu);
// **** set the bar to be the menu bar
setJMenuBar(bar);
// Container content = getContentPane(); replace this with our own
content = new CustomPanel();
contentCustom = (CustomPanel) content;
FlowLayout lay = new FlowLayout(FlowLayout.LEFT);
content.setLayout(lay);
setContentPane(content);
setVisible(true); // always do this last
}
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source == exitItem)
{
System.exit(0);
}
else if (source == lineItem)
{
contentCustom.setMyMode("Line");
setTitle("Paint - " + ((CustomPanel) content).getMyMode() + " Mode Color="+
((CustomPanel) content).getColor()
);
}
else if (source == rectItem)
{
((CustomPanel) content).setMyMode("Rectangle");
setTitle("Paint - " + ((CustomPanel) content).getMyMode() + " Mode Color="+
((CustomPanel) content).getColor()
);
}
else if (source == ellipseItem)
{
((CustomPanel) content).setMyMode("Ellipse");
setTitle("Paint - " + ((CustomPanel) content).getMyMode() + " Mode Color="+
((CustomPanel) content).getColor()
);
}
else if (source == freeItem)
{
((CustomPanel) content).setMyMode("Free");
setTitle("Paint - " + ((CustomPanel) content).getMyMode() + " Mode Color="+
((CustomPanel) content).getColor()
);
}
else if (source == colorItem)
{
Color color = Color.black;
Color newColor = JColorChooser.showDialog(this,"Draw Color",color);
if (newColor != null)
((CustomPanel) content).setColor(newColor);
setTitle("Paint - " + ((CustomPanel) content).getMyMode() + " Mode Color="+
((CustomPanel) content).getColor()
);
}
else if (source == saveItem)
{
try
{
JFileChooser fileChooser = null;
int result = JFileChooser.APPROVE_OPTION;
if (filename.equals(""))
{
fileChooser = new JFileChooser();
result = fileChooser.showSaveDialog(this);
}
if (result == JFileChooser.APPROVE_OPTION)
{
if (filename.equals(""))
{
filename = fileChooser.getSelectedFile().getName();
file = fileChooser.getSelectedFile();
}
// use contentCustom to reference the CustomPanel variables
FileWriter fw=null;
BufferedWriter bw=null;
try
{
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
for (int j=0; j < contentCustom.myList.size(); j++)
{
AbstractShapeObject myShape = contentCustom.myList.get(j);
String outLine = myShape.toString();
bw.write(outLine);
bw.newLine();
}
}
catch (Exception e1)
{
}
finally
{
try
{
bw.close();
}
catch (Exception e2)
{
}
}
}
else if (result == JFileChooser.CANCEL_OPTION)
{
}
}
catch (Exception ee)
{
}
}
else if (source == openItem)
{
try
{
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION)
{
file = fileChooser.getSelectedFile();
if (file != null)
{
filename = fileChooser.getSelectedFile().getName();
contentCustom.myList.clear();
FileReader fr=null;
BufferedReader br=null;
try
{
fr = new FileReader(file);
br = new BufferedReader(fr);
String s = br.readLine();
while (s != null)
{
StringTokenizer st = new StringTokenizer(s,",");
String mode = st.nextToken();
if (mode.equals("Line"))
{
int x1 = Integer.parseInt(st.nextToken());
int y1 = Integer.parseInt(st.nextToken());
int x2 = Integer.parseInt(st.nextToken());
int y2 = Integer.parseInt(st.nextToken());
int red = Integer.parseInt(st.nextToken());
int green = Integer.parseInt(st.nextToken());
int blue = Integer.parseInt(st.nextToken());
Color color = new Color(red,green,blue);
AbstractShapeObject myShape = new Line(x1,y1,x2,y2,color);
myShape.setMode("Line");
myShape.setKeep(true);
contentCustom.myList.add(myShape);
}
else if (mode.equals("Rectangle"))
{
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int width = Integer.parseInt(st.nextToken());
int height = Integer.parseInt(st.nextToken());
int red = Integer.parseInt(st.nextToken());
int green = Integer.parseInt(st.nextToken());
int blue = Integer.parseInt(st.nextToken());
Color color = new Color(red,green,blue);
AbstractShapeObject myShape = new Rectangle(x,y,width,height,color);
myShape.setMode("Rectangle");
myShape.setKeep(true);
contentCustom.myList.add(myShape);
}
else if (mode.equals("Ellipse"))
{
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int width = Integer.parseInt(st.nextToken());
int height = Integer.parseInt(st.nextToken());
int red = Integer.parseInt(st.nextToken());
int green = Integer.parseInt(st.nextToken());
int blue = Integer.parseInt(st.nextToken());
Color color = new Color(red,green,blue);
AbstractShapeObject myShape = new Ellipse(x,y,width,height,color);
myShape.setMode("Rectangle");
myShape.setKeep(true);
contentCustom.myList.add(myShape);
}
s = br.readLine();
} // end of while loop
contentCustom.repaint();
}
catch (Exception e1)
{
}
finally
{
try
{
br.close();
}
catch (Exception e2)
{
}
}
}
}
else if (result == JFileChooser.CANCEL_OPTION)
{
}
}
catch (Exception ee)
{
}
}
}
public static void main(String[] args)
{
Main paint = new Main();
}
} // end of class Main
This is the the AbstractShapeObject Class:
public abstract class AbstractShapeObject implements ShapeInterface
{
private int x;
private int y;
private int width;
private int height;
private Color color;
private int thickness;
private String mode; // Am I a Rectangle, Line, etc.
private boolean keep; // do I keep the shape or erase it later
public AbstractShapeObject()
{
this(0,0,0,0,defaultThickness,defaultColor);
}
public AbstractShapeObject(int x, int y)
{
this(x,y,defaultWidth,defaultHeight,defaultThickness,defaultColor);
}
public AbstractShapeObject(int x, int y, Color color)
{
this(x,y,defaultWidth,defaultHeight,defaultThickness,color);
}
public AbstractShapeObject(int x, int y, int thickness)
{
this(x,y,defaultWidth,defaultHeight,thickness,defaultColor);
}
public AbstractShapeObject(int x, int y, int thickness, Color color)
{
this(x,y,defaultWidth,defaultHeight,thickness,color);
}
public AbstractShapeObject(int x, int y, int width, int height)
{
this(x,y,width,height,defaultThickness,defaultColor);
}
public AbstractShapeObject(int x, int y, int width, int height, Color color)
{
this(x,y,width,height,defaultThickness,color);// call this(?????) (the constructor with all the parameters below)
}
public AbstractShapeObject(int x, int y, int width, int height, int thickness)
{
this(x,y,width,height,thickness,defaultColor);// call this(?????) (the constructor with all the parameters below)
}
public AbstractShapeObject(int x, int y, int width, int height, int thickness, Color color)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.thickness = thickness;
mode = "None";
keep = true;
}
// write all of your getter and setter methods here !!!
// do NOT write your draw methods here
// you will write your draw methods in the specific classes
// since you don't really know what to draw here
public int getX()
{
return x; //change me
}
public void setX(int x)
{this.x = x;
}
public int getY()
{
return y; //change me
}
public void setY(int y)
{this.y = y;
}
public int getWidth()
{
return width; //change me
}
public void setWidth(int width)
{this.width = width;
}
public int getHeight()
{
return height; //change me
}
public void setHeight(int height)
{this.height = height;
}
public int getThickness()
{
return thickness; //change me
}
public void setThickness(int thickness)
{this.thickness = thickness;
}
public Color getColor()
{
// ************* change this to ????? **************
// What are you getting?
return color; //change me!!!!!!!!!!
}
public void setColor(Color color)
{this.color = color;
}
public String getMode()
{
return mode; // change me
}
public void setMode(String mode)
{this.mode = mode;
}
public boolean getKeep()
{
return keep; // change me
}
public void setKeep(boolean keep)
{this.keep = keep;
}
// do NOT change this method
public void calcXYWidthHeight(int x1, int y1, int x2, int y2)
{
int width = Math.abs(x2-x1);
int height = Math.abs(y2-y1);
// now I need to find my upper left corner point
// find the x1 value
if (x2 <= x1)
{
x1 = x2;
}
// find the y1 value
if (y2 <= y1) // they have dragged the mouse up
{
y1 = y2;
}
// now set the instance variables of the class
setX(x1);
setY(y1);
setWidth(width);
setHeight(height);
}
} // end of class AbstractShapeObject
This is one of the shape classes I coded. All of them have the same format but this one is for drawing an ellipse:
import java.awt.*;
import java.awt.geom.*;
public class Ellipse extends AbstractShapeObject {
public Ellipse(int x, int y, int width, int height) {
super(x,y,width,height);
}
public Ellipse(int x, int y, int width, int height, Color color) {
super(x,y,width,height,color);// call the appropriate super constructor
}
public Ellipse(int x, int y, int width, int height, int thickness) {
super(x,y,width,height,thickness);// call the appropriate super constructor
}
public Ellipse(int x, int y, int width, int height, int thickness, Color color) {
super(x,y,width,height,thickness,color);// call the appropriate super constructor
}
public void draw(Graphics window)
{
// first, set your draw color
Color drawColor = window.getColor();
window.setColor(drawColor);// window.????(????);
// second, draw the shape (i.e. draw the ellipse or Oval)
window.drawOval(getX(),getY(),getWidth(),getHeight());// window.????(????);
}
// write the toString() method
// use the same format that is used for the Rectangle and Line classes
public String toString()
{
return getMode() + "," + getX() + "," + getY() + "," + getWidth() + "," + getHeight() + ","
+ getColor().getRed() + "," + getColor().getGreen() + "," + getColor().getBlue();
}
} // end of class Ellipse
This is the CustomPanel Class (this was provided to us so I don’t think its an error here):
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.awt.image.BufferedImage;
// this JPanel listens for the mouse events
public class CustomPanel extends JPanel implements MouseListener, MouseMotionListener
{
// for buffering
private BufferedImage back;
ArrayList <AbstractShapeObject> myList = new ArrayList<AbstractShapeObject>();
String myMode = "Line"; // None, Line, Rectangle, etc.
Color color = Color.blue; // current draw color
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
boolean drawing = false; // are we drawing with the mouse?
public CustomPanel()
{
addMouseListener(this);
addMouseMotionListener(this);
setBackground(Color.red);
}
public void setMyMode(String mode)
{
myMode = mode;
}
public String getMyMode()
{
return myMode;
}
public void setColor(Color color)
{
this.color = color;
}
public Color getColor()
{
return color;
}
public void removeTempShapes()
{
// get rid of temp objects
for (int j=0; j < myList.size(); j++)
{
AbstractShapeObject myShape = myList.get(j);
if (!myShape.getKeep())
{
myList.remove(j);
}
}
}
public void update(Graphics window)
{
paintComponent(window);
}
public void paintComponent(Graphics window)
{
super.paintComponent((Graphics2D)window);
Graphics2D g2 = (Graphics2D) window;
//take a snap shop of the current screen and same it as an image
//that is the exact same width and height as the current screen
back = (BufferedImage)(createImage(getWidth(),getHeight()));
//create a graphics reference to the back ground image
//we will draw all changes on the background image
Graphics gMemory = back.createGraphics();
// clear the screen
gMemory.setColor(Color.BLACK);
gMemory.fillRect(0,0,getWidth(),getHeight());
// draw all the objects
for (int j=0; j < myList.size(); j++)
{
AbstractShapeObject myShape = myList.get(j);
myShape.draw(gMemory);
}
// *** show the screen by copying the image to the graphics display ********
g2.drawImage(back, null, 0, 0);
}
/* mouse motion events... */
public void mouseMoved(MouseEvent event)
{
// DO NOT DO ANYTHING HERE
}
public void mouseDragged(MouseEvent event)
{
if (drawing)
{
if (myMode.equals("Line"))
{
x2 = event.getX();
y2 = event.getY();
// get rid of temp objects
removeTempShapes();
AbstractShapeObject myShape = new Line(x1,y1,x2,y2,color);
myShape.setMode("Line");
myShape.setKeep(false);
myList.add(myShape);
repaint();
} // end of if (myMode.equals("Line"))
else if (myMode.equals("Free"))
{
// update the from coordinates
x1 = x2;
y1 = y2;
// get the draw to coordinates
x2 = event.getX();
y2 = event.getY();
AbstractShapeObject myShape = new Line(x1,y1,x2,y2,color);
myShape.setMode("Free");
myShape.setKeep(true);
myList.add(myShape);
repaint();
} // end of if (myMode.equals("Line"))
else if (myMode.equals("Rectangle"))
{
// get the draw to coordinates (lower right)
x2 = event.getX();
y2 = event.getY();
// get rid of temp objects
removeTempShapes();
AbstractShapeObject myShape = new Rectangle(x1,y1,x2,y2,color);
myShape.calcXYWidthHeight(x1,y1,x2,y2);
myShape.setMode("Rectangle");
myShape.setKeep(false);
myList.add(myShape);
repaint();
} // end of if (myMode.equals("Line"))
else if (myMode.equals("Ellipse"))
{
// get the draw to coordinates (lower right)
x2 = event.getX();
y2 = event.getY();
// get rid of temp objects
removeTempShapes();
AbstractShapeObject myShape = new Ellipse(x1,y1,x2,y2,color);
myShape.calcXYWidthHeight(x1,y1,x2,y2);
myShape.setMode("Ellipse");
myShape.setKeep(false);
myList.add(myShape);
repaint();
} // end of if (myMode.equals("Ellipse"))
} // end of if (drawing)
}
/* mouse events... */
public void mouseClicked(MouseEvent event)
{
// DO NOT DO ANYTHING HERE
}
public void mousePressed(MouseEvent event)
{
drawing = true;
// save the original coordinates
x1 = event.getX();
y1 = event.getY();
// save where to draw to
x2 = event.getX();
y2 = event.getY();
}
public void mouseReleased(MouseEvent event)
{
if (drawing)
{
if (myMode.equals("Line"))
{
// get rid of temp objects
removeTempShapes();
x2 = event.getX();
y2 = event.getY();
AbstractShapeObject myShape = new Line(x1,y1,x2,y2,color);
myShape.setMode("Line");
myShape.setKeep(true);
myList.add(myShape);
}
else if (myMode.equals("Free"))
{
// nothing to do since it has already been drawn
}
else if (myMode.equals("Rectangle"))
{
// get rid of temp objects
removeTempShapes();
x2 = event.getX();
y2 = event.getY();
AbstractShapeObject myShape = new Rectangle(x1,y1,x2,y2,color);
myShape.calcXYWidthHeight(x1,y1,x2,y2);
myShape.setMode("Rectangle");
myShape.setKeep(true);
myList.add(myShape);
}
else if (myMode.equals("Ellipse"))
{
// get rid of temp objects
removeTempShapes();
x2 = event.getX();
y2 = event.getY();
AbstractShapeObject myShape = new Ellipse(x1,y1,x2,y2,color);
myShape.calcXYWidthHeight(x1,y1,x2,y2);
myShape.setMode("Ellipse");
myShape.setKeep(true);
myList.add(myShape);
}
drawing = false;
repaint();
} // end of if (drawing)
} // end of mouseReleased
public void mouseEntered(MouseEvent event)
{
// DO NOT DO ANYTHING HERE
}
public void mouseExited(MouseEvent event)
{
// DO NOT DO ANYTHING HERE
}
} // end of class CustomPanel
This is the ShapeInterface class (This was also provided):
// DO NOT TOUCH THIS FILE
// THE INTERFACE HAS BEEN WRITTEN FOR YOU
import java.awt.Color;
import java.awt.*;
public interface ShapeInterface
{
// all variables (constants) are public static final by default
public int defaultWidth = 1;
public int defaultHeight = 1;
public int defaultThickness = 1;
public Color defaultColor = Color.RED;
// these methods are all public abstract by default
public int getX();
public void setX(int x);
public int getY();
public void setY(int y);
public int getWidth();
public void setWidth(int width);
public int getHeight();
public void setHeight(int height);
public int getThickness();
public void setThickness(int thickness);
public Color getColor();
public void setColor(Color color);
public String getMode();
public void setMode(String mode);
public boolean getKeep();
public void setKeep(boolean keep);
public abstract void draw(Graphics window);
} //end of interface ShapeInterface
Advertisement
Answer
I didn’t check all the code, but there is an error in Ellipse
class, check my remarks
public void draw(Graphics window)
{
//This is a nonsense, get the Color from the graphics and setting back the same color will do nothing
Color drawColor = window.getColor();
//Here you should set your own color, since when your code is called the Graphic's color is black
//You have a color member variable in AbstractShape class, use it here
window.setColor(drawColor);// window.????(????);
// second, draw the shape (i.e. draw the ellipse or Oval)
window.drawOval(getX(),getY(),getWidth(),getHeight());// window.????(????);
}