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.????(????); }