I'm supposed to allow the user to draw shapes based on their combobox choices (eg. line, rectangle, circle), colour, fill state, etc. However, nothing is showing up.

Model class:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;

public class DrawPanel extends JPanel
{
  
  // Declare variables:
  private MyShape shapeObjects[]; // stores all of the shape objects the user draws
  private int numOfShapes; // counts the number of shapes in the array
  private int currentShapeType; // determines the type of shape to draw
  private MyShape currentShapeObject; // represents the current shape the user is drawing
  private Color currentShapeColor; // represents the current drawing currentShapeColor
  private boolean currentShapeFilled; // determines whether to draw a currentShapeFilled shape
  private JLabel statusLabel; // represents the status bar, displays the coordinates of the current mouse position
  
  // Constructor with a single JLabel parameter
  public DrawPanel( JLabel statusLabel ) {
    
    // Initialize variables:
    this.statusLabel = statusLabel;
    shapeObjects = new MyShape[100]; // 100 storage for user-drawn shapes
    numOfShapes = 0; // Defult number of shapes is 0
    currentShapeType = 1; // Default shape is a line
    currentShapeColor = Color.BLACK; // Default colour is black
    
    // Set background colour of the window to white
    setBackground( Color.WHITE );
    
    // Create and register listener for mouse and mouse motion events
    MouseHandler handler = new MouseHandler(); 
    addMouseListener( handler ); 
    addMouseMotionListener( handler ); 
    
  }
  
  // Mutators
  public void setCurrentShapeType( int currentShapeType ) {
    this.currentShapeType = currentShapeType;
  }
  
  public void setCurrentShapeColor( Color currentShapeColor ) {
    this.currentShapeColor = currentShapeColor;
  }
  
  public void setCurrentShapeFilled( boolean currentShapeFilled ) {
    this.currentShapeFilled = currentShapeFilled;
  }
  
  // Clears the last shape drawn by decrementing the instance variable numOfShapes.
  // Ensures that numOfShapes is never less than zero.
  public void clearLastShape() {
    
    // Do nothing if numOfShapes is less than or equal to zero.
    if ( numOfShapes <= 0) {
      return;
    }
    // Clear the current shape
    currentShapeObject = null;
    // Decrement the number of existing shapes
    numOfShapes--;
    repaint();
    
  }
  
  // Remove all the shapes in the current drawing by setting numOfShapes to zero
  public void clearDrawing() {
    numOfShapes = 0;
    repaint();
  }
  
  // Draws the shapes in the shapeObjects array.
  // Uses instance variable numOfShapes to determine how many shapes to draw.
  // Method paintComponent() should also call currentShapeObject’s draw() method,
  // provided that currentShapeObject is not null.
  public void paintComponent( Graphics g ) {
    
    // Inherit the paintComponent method from the superclass
    super.paintComponent( g );
    
    // Determine how many shapes to draw
    numOfShapes++;
    
    // If currentShapeObject is null, do nothing
    if ( currentShapeObject == null ) {
      return;
    } else {
      // Otherwise, draw the shapes
      currentShapeObject.draw( g );
    }
    
  }
  
  private class MouseHandler extends MouseAdapter implements MouseMotionListener {
    
    // Handles event when mouse is pressed
    public void mousePressed( MouseEvent event ) {
      
      // Determine current shape type
      if ( currentShapeType == 1 ) {
        currentShapeObject = new MyLine();
      } else if ( currentShapeType == 2 ) {
        currentShapeObject = new MyRectangle();
      } else {
        currentShapeObject = new MyOval();
      }
      
      // Get current mouse position
      int x1 = event.getX();
      int y1 = event.getY();
      
      // Create shape of the type specified by currentShapeType
      // Initializes both points to the mouse position
      currentShapeObject.setX1( x1 );
      currentShapeObject.setY1( y1 );
    }
    
  }
  
  // Handles event when mouse is released after dragging
  public void mouseReleased( MouseEvent event ) {
    
    // Get current mouse position
    int x2 = event.getX();
    int y2 = event.getY();
    
    // Finish drawing the shape and initialize current coordinates to currentShapeObject
    currentShapeObject.setX2( x2 );
    currentShapeObject.setY2( y2 );
    
    // Place it into the shapeObjects array
    shapeObjects[numOfShapes] = currentShapeObject;
    
    // Clear currentShapeObject's information
    currentShapeObject = null;
    repaint();
    
  }
  
  // Handles event when user moves the mouse
  // Sets the text of the statusLabel so that it displays (constantly updated) mouse coordinates
  public void mouseMoved( MouseEvent event )
  {
    statusLabel.setText( String.format( "(%d, %d)", event.getX(), event.getY() ) );
  }
  
  // Handles event when user drags mouse with button pressed
  // Calls method repaint() to allow the user to see the shape while dragging the mouse
  public void mouseDragged( MouseEvent event )
  {
    
    // Get current mouse position
    int x2 = event.getX();
    int y2 = event.getY();
    
    // Set second point of currentShapeObject to current mouse position
    currentShapeObject.setX2( x2 );
    currentShapeObject.setY2( y2 );
    
    // Update statusLabel with the current mouse position
    statusLabel.setText( String.format( "(%d, %d)", event.getX(), event.getY() ) );
    
  }
  
}

View:

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class DrawFrame extends JFrame
{
  
  // Declare variables:
  private JButton undo; // undoes the last shape drawn
  private JButton clear; // clears all shapes from the drawing
  private JComboBox colour; // selects the colour from the 13 predefined colours
  private JComboBox shape; // selects the shape to draw
  private JCheckBox fill; // specifies whether a shape should be filled or unfilled
  private JLabel status; // Status bar text
  private String colList[] = { "Black", "White", "Red", "Green", "Blue", "Yellow", "Orange", "Magenta", "Cyan", "Pink", "Dark Gray", "Gray", "Light Gray" }; // List for the colour JComboBox
  private String shapeList[] = { "Line", "Rectangle", "Oval" }; // List for the shape JComboBox
  
  // New DrawPanel object
  DrawPanel panel = new DrawPanel( status );
  
  // Constructor
  public DrawFrame() {
    
    // Main frame properties
    super( "SuperPaint Application" ); // Title bar text
    setLayout( new BorderLayout() ); // Set frame layout
    
    // Initialize variables:
    status = new JLabel();
    undo = new JButton( "Undo" );
    clear = new JButton( "Clear" );
    colour = new JComboBox( colList );
    shape = new JComboBox( shapeList );
    fill = new JCheckBox( "Filled" );
    
    // Add DrawPanel to the DrawFrame
    add( panel );
    
    // Panel in the north region of the border layout for components
    JPanel northPanel = new JPanel();
    northPanel.setLayout( new FlowLayout() );
    add( northPanel, BorderLayout.NORTH );
    // Add components into the north panel
    northPanel.add( undo );
    northPanel.add( clear );
    northPanel.add( colour );
    northPanel.add( shape );
    northPanel.add( fill );
    
    // Panel in the center region of the border layout for main drawings
    add( panel, BorderLayout.CENTER );
    
    // Status bar in the south region of border layout
    add( status, BorderLayout.SOUTH );
    
    // Create and register listeners for events
    ButtonHandlerU bHandlerU = new ButtonHandlerU();
    undo.addActionListener( bHandlerU );
    ButtonHandlerC bHandlerC = new ButtonHandlerC();
    clear.addActionListener( bHandlerC );
    ComboBoxHandlerC cmbHandlerC = new ComboBoxHandlerC();
    colour.addItemListener( cmbHandlerC );
    ComboBoxHandlerS cmbHandlerS = new ComboBoxHandlerS();
    shape.addItemListener( cmbHandlerS );
    CheckBoxHandler cbHandler = new CheckBoxHandler();
    fill.addItemListener( cbHandler );
    
  }
  
  // Inner class for button event handling for the undo button
  private class ButtonHandlerU implements ActionListener 
  {
    public void actionPerformed( ActionEvent event ) {
      panel.clearLastShape();
    }
  }
  
  // Inner class for button event handling for the clear button
  private class ButtonHandlerC implements ActionListener {
    public void actionPerformed( ActionEvent event ) {
      panel.clearDrawing();
    }
  }
  
  // Inner class for the colour combobox
  private class ComboBoxHandlerC implements ItemListener {
    
    public void itemStateChanged( ItemEvent event ) {
      // Determines whether check box is selected
      if ( event.getStateChange() == ItemEvent.SELECTED ) {
        // Set colour selections to actual colours
        if ( colour.getSelectedIndex() == 1 ) {
          panel.setCurrentShapeColor( Color.BLACK );
        } else if ( colour.getSelectedIndex() == 2 ) {
          panel.setCurrentShapeColor( Color.WHITE );
        } else if ( colour.getSelectedIndex() == 3 ) {
          panel.setCurrentShapeColor( Color.RED );
        } else if ( colour.getSelectedIndex() == 4 ) {
          panel.setCurrentShapeColor( Color.GREEN );
        } else if ( colour.getSelectedIndex() == 5 ) {
          panel.setCurrentShapeColor( Color.BLUE );
        } else if ( colour.getSelectedIndex() == 6 ) {
          panel.setCurrentShapeColor( Color.YELLOW );
        } else if ( colour.getSelectedIndex() == 7 ) {
          panel.setCurrentShapeColor( Color.ORANGE );
        } else if ( colour.getSelectedIndex() == 8 ) {
          panel.setCurrentShapeColor( Color.MAGENTA );
        } else if ( colour.getSelectedIndex() == 9 ) {
          panel.setCurrentShapeColor( Color.CYAN );
        } else if ( colour.getSelectedIndex() == 10 ) {
          panel.setCurrentShapeColor( Color.PINK );
        } else if ( colour.getSelectedIndex() == 11 ) {
          panel.setCurrentShapeColor( Color.darkGray );
        } else if ( colour.getSelectedIndex() == 12 ) {
          panel.setCurrentShapeColor( Color.GRAY );
        } else {
          panel.setCurrentShapeColor( Color.lightGray );
        }
      }
    }
  }
  
  // Inner class for the shape combobox
  private class ComboBoxHandlerS implements ItemListener {
    public void itemStateChanged( ItemEvent event ) {
      // Determines whether check box is selected
      if ( event.getStateChange() == ItemEvent.SELECTED ) {
        if ( shape.getSelectedIndex() == 1 ) {
          panel.setCurrentShapeType( 1 );
        } else if ( shape.getSelectedIndex() == 2 ) {
          panel.setCurrentShapeType( 2 );
        } else {
          panel.setCurrentShapeType( 3 );
        }
      }
    }
  }
  
  // Inner class for checkbox event handling for the fill state
  private class CheckBoxHandler implements ItemListener {
    public void itemStateChanged( ItemEvent event ) {
      if ( event.getSource() == fill ) {
        panel.setCurrentShapeFilled( true );
      } else {
        panel.setCurrentShapeFilled( false );
      }
    }
  }
  
}

A shape class for reference:

import java.awt.Color;
import java.awt.Graphics;

public class MyLine extends MyShape
{
  
  // No-parameter constructor
  public MyLine () {
    super.setX1(0);
    super.setY1(0);
    super.setX2(0);
    super.setY2(0);
    super.setColor(Color.BLACK);
  }
  
  // Constructor with parameters for the coordinates and colour
  public MyLine( int x1, int y1, int x2, int y2, Color colour ) {
    super.setX1(x1); // set x coordinate of first endpoint
    super.setY1(y1); // set y coordinate of first endpoint
    super.setX2(x2); // set x coordinate of second endpoint
    super.setY2(y2); // set y coordinate of second endpoint
    super.setColor(colour); // set the colour
  } // end MyLine constructor
  
  // Actually draws the line
  public void draw( Graphics g ) {
    g.setColor( super.getColor() );
    g.drawLine( super.getX1(), super.getY1(), super.getX2(), super.getY2() );
  }
 
  
}

I'm pretty sure it's something in setting the numOfShapes variable, or just a faulty draw method. Thanks if anyone can help!

Recommended Answers

All 7 Replies

Put some debugging println statements in relevant methods like paintComponent(), draw(), etc. (I assume you aren't using an IDE with a debugger) so you can see what is going on internally.

I glanced through the code and not jumped right out as a problem, but you didn't post the MyShape class, so I can't run the code here to look into it much further.

Put some debugging println statements in relevant methods like paintComponent(), draw(), etc. (I assume you aren't using an IDE with a debugger) so you can see what is going on internally.

I glanced through the code and not jumped right out as a problem, but you didn't post the MyShape class, so I can't run the code here to look into it much further.

Thanks for the suggestion! I saw that numOfShapes++ was being called twice merely upon running. Nothing happens when I click on the drawing frame, but as soon as I click the drop down arrow on either JComboBoxes, numOfShapes++ is called again. Same with selecting from the boxes. Method draw() is called as well as paintComponent() after I click on the drawing fame and go back to selecting things on the combo boxes again. The weird thing is, when I press the clear button, lines start appearing. ...Sometimes. Haven't figured out the pattern. They are also always lines, always black, and x1 and y1 seem to be always at the origin.

I'm completely lost on how to remedy this. Here's the MyShape class:

import java.awt.Color;
import java.awt.Graphics;

public abstract class MyShape {
  
  // Initialize variables
  private int x1; // x coordinate of first endpoint
  private int y1; // y coordinate of first endpoint
  private int x2; // x coordinate of second endpoint
  private int y2; // y coordinate of second endpoint
  private Color colour; // colour of the shape
  
  // A no-parameter constructor that sets all the coordinates of the shape to 0 and the 
  // colour to Color.BLACK
  public MyShape () {
    x1 = 0;
    y1 = 0;
    x2 = 0;
    y2 = 0;
    colour = Color.BLACK;
  }
  
  // A constructor that initializes the coordinates and colour to the values of the 
  // parameters supplied.
  public MyShape ( int x1, int y1, int x2, int y2, Color col ) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.colour = col;
  }
  
  // ------------------------------------------------------------------------------
  // Mutator methods for the individual coordinates and colour that allow the 
  // programmer to set any piece of data independently for a shape in the hierarchy.
  // ------------------------------------------------------------------------------
  
  public void setX1 (int x1) {
    this.x1 = x1;
  }
  
  public void setY1 (int y1) {
    this.y1 = y1;
  }
  
  public void setX2 (int x2) {
    this.x2 = x2;
  }
  
  public void setY2 (int y2) {
    this.y2 = y2;
  }
  
  public void setColor (Color colour) {
    this.colour = colour;
  }
  
  // ------------------------------------------------------------------------------
  // The following are accessor methods for the individual coordinates and colour that 
  // allow the programmer to retrieve any piece of data independently for a shape in 
  // the hierarchy.
  // ------------------------------------------------------------------------------
  
  public int getX1 () {
    return this.x1;
  }
  
  public int getY1 () {
    return this.y1;
  }
  
  public int getX2 () {
    return this.x2;
  }
  
  public int getY2 () {
    return this.y2;
  }
  
  public Color getColor () {
    return this.colour;
  }
  
  // The abstract method which will be called from the program’s paintComponent()
  // method to draw a shape on the screen
  public abstract void draw( Graphics g );
  
}

Thank you for your help!

Ok, a couple of things to help you get back on track.

First off, take a look at the brace on line 124 of your DrawPanel class. That's wrecking your MouseHandler and I'm sure causing all kinds of confusion as to why those mouse methods don't seem to be doing anything. You effectively only have a mousePressed() method in there. The rest are defined on DrawPanel and not doing you a bit of good.

Second, move numOfShapes++; to mousePressed() , where you actually create a new object. It has nothing to do with painting.

Third, if you want to paint multiple shapes, you have to loop the shapeObjects array and call draw on them, so you need to add that to your paintComponent() method. The currentShapeObject is just going to be painting the one you're dragging with the mouse. (Add a repaint in mouseDragged() also).

That isn't everything, but with some work it should get you to a better place with it. You may also want to add a setDefaultCloseOperation(EXIT_ON_CLOSE); line to your DrawFrame constructor as well, unless you're setting that somewhere else.

Thank you! Can't believe I missed the bracket thing...I've moved everything relating to mouse events before the ending brace. I'm getting a nullPointerException error in the mouseMoved and mouseDragged methods though, which I'm not understanding.

Moved and added everything else, thanks! About looping the shapeObjects array, I have the loop set up like this inside paintComponent():

for (int i = 0; i <= numOfShapes; i++) {
        shapeObjects[i].draw( g );
      }
      currentShapeObject.draw( g );
    }

Is that right?

I have setDefaultCloseOperation(EXIT_ON_CLOSE); on a test class, but thanks anyway!

I'm getting a nullPointerException error in the mouseMoved and mouseDragged methods though, which I'm not understanding

Take a look at the order in which you initialize the drawing panel and the status label in your DrawFrame class.

Moved and added everything else, thanks! About looping the shapeObjects array, I have the loop set up like this inside paintComponent():

for (int i = 0; i <= numOfShapes; i++) {
        shapeObjects[i].draw( g );
      }
      currentShapeObject.draw( g );
    }

Is that right?

Mostly. Make sure your shapes aren't null before you try to draw them from the array, since not all of those 100 are created yet. You'll still need the null check on currentShapeObject also, since it's only not null while the mouse button is down.

I have setDefaultCloseOperation(EXIT_ON_CLOSE); on a test class, but thanks anyway!

Ok, just wanted to mention it. I had to make my own main() method to run it, so I didn't know what you had going on in the launch class :)

Take a look at the order in which you initialize the drawing panel and the status label in your DrawFrame class.

Yup haha, I realized that right before I had to leave the computer, so I couldn't go back and say "Nevermind got it" and not waste your time xD Thanks though!

I'll add the null checking to the shapeObjects array. Thank you once again!

I'm running into another problem now. When I release the mouse, what I draw disappears--until I press the mouse down again. Deleting currentShapeObject = null; and repaint(); makes the lines appear fine, but I'm pretty sure those two commands are supposed to be there. Also, clearing the image only clears everything up to the very last line I've drawn.

The combobox selections aren't registering either. Every shape is black no matter what colour is chosen, and trying to draw a rectangle results in drawing a line while drawing an oval creates a rectangle, with screwed up x and y points (they initiate around twenty pixels off from where you click). Here's my modified drawPanel class:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;

public class DrawPanel extends JPanel
{
  
  // Declare variables:
  private MyShape shapeObjects[]; // stores all of the shape objects the user draws
  private int numOfShapes; // counts the number of shapes in the array
  private int currentShapeType; // determines the type of shape to draw
  private MyShape currentShapeObject; // represents the current shape the user is drawing
  private Color currentShapeColor; // represents the current drawing currentShapeColor
  private boolean currentShapeFilled; // determines whether to draw a currentShapeFilled shape
  private JLabel statusLabel; // represents the status bar, displays the coordinates of the current mouse position
  
  // Constructor with a single JLabel parameter
  public DrawPanel( JLabel statusLabel ) {
    
    // Initialize variables:
    this.statusLabel = statusLabel;
    shapeObjects = new MyShape[100]; // 100 storage for user-drawn shapes
    numOfShapes = 0; // Defult number of shapes is 0
    currentShapeType = 1; // Default shape is a line
    currentShapeColor = Color.BLACK; // Default colour is black
    
    // Set background colour of the window to white
    setBackground( Color.WHITE );
    
    // Create and register listener for mouse and mouse motion events
    MouseHandler handler = new MouseHandler(); 
    addMouseListener( handler ); 
    addMouseMotionListener( handler ); 
    
  }
  
  // Mutators
  public void setCurrentShapeType( int currentShapeType ) {
    this.currentShapeType = currentShapeType;
  }
  
  public void setCurrentShapeColor( Color currentShapeColor ) {
    this.currentShapeColor = currentShapeColor;
  }
  
  public void setCurrentShapeFilled( boolean currentShapeFilled ) {
    this.currentShapeFilled = currentShapeFilled;
  }
  
  // Clears the last shape drawn by decrementing the instance variable numOfShapes.
  // Ensures that numOfShapes is never less than zero.
  public void clearLastShape() {
    
    // Do nothing if numOfShapes is less than or equal to zero.
    if ( numOfShapes <= 0) {
      return;
    } else {
      // Clear the current shape
      currentShapeObject = null;
      // Decrement the number of existing shapes
      numOfShapes--;
      repaint();
    }
    
  }
  
  // Remove all the shapes in the current drawing by setting numOfShapes to zero
  public void clearDrawing() {
    numOfShapes = 0;
    repaint();
  }
  
  // Draws the shapes in the shapeObjects array.
  // Uses instance variable numOfShapes to determine how many shapes to draw.
  // Method paintComponent() should also call currentShapeObject’s draw() method,
  // provided that currentShapeObject is not null.
  public void paintComponent( Graphics g ) {
    
    // Inherit the paintComponent method from the superclass
    super.paintComponent( g );
    
    // If currentShapeObject is null, do nothing
    if ( currentShapeObject == null ) {
      return;
    } else {
      // Otherwise, draw the shapes
      for (int i = 0; i < numOfShapes; i++) {
        shapeObjects[i].draw( g );
      }
      currentShapeObject.draw( g );
    }
    
  }
  
  private class MouseHandler extends MouseAdapter implements MouseMotionListener {
    
    // Handles event when mouse is pressed
    public void mousePressed( MouseEvent event ) {
      
      // Determine current shape type
      if ( currentShapeType == 1 ) {
        currentShapeObject = new MyLine();
      } else if ( currentShapeType == 2 ) {
        currentShapeObject = new MyRectangle();
      } else {
        currentShapeObject = new MyOval();
      }
      
      // Get current mouse position
      int x1 = event.getX();
      int y1 = event.getY();
      
      // Create shape of the type specified by currentShapeType
      // Initializes both points to the mouse position
      currentShapeObject.setX1( x1 );
      currentShapeObject.setY1( y1 );
    }
    
    // Handles event when mouse is released after dragging
    public void mouseReleased( MouseEvent event ) {
      
      // Get current mouse position
      int x2 = event.getX();
      int y2 = event.getY();
      
      // Finish drawing the shape and initialize current coordinates to currentShapeObject
      currentShapeObject.setX2( x2 );
      currentShapeObject.setY2( y2 );
      
      // Place it into the shapeObjects array
      shapeObjects[numOfShapes] = currentShapeObject;
      numOfShapes++;
      
      // Clear currentShapeObject's information
      currentShapeObject = null;
      repaint();
      
    }
    
    // Handles event when user moves the mouse
    // Sets the text of the statusLabel so that it displays (constantly updated) mouse coordinates
    public void mouseMoved( MouseEvent event ) {
      statusLabel.setText( String.format( "(%d, %d)", event.getX(), event.getY() ) );
    }
    
    // Handles event when user drags mouse with button pressed
    // Calls method repaint() to allow the user to see the shape while dragging the mouse
    public void mouseDragged( MouseEvent event )
    {
      
      // Get current mouse position
      int x2 = event.getX();
      int y2 = event.getY();
      
      // Set second point of currentShapeObject to current mouse position
      currentShapeObject.setX2( x2 );
      currentShapeObject.setY2( y2 );
      
      // Update statusLabel with the current mouse position
      statusLabel.setText( String.format( "(%d, %d)", event.getX(), event.getY() ) );
      repaint();
      
    }
    
  }
  
}

And the rectangle class (and its superclass) if that does anything:

import java.awt.Color;
import java.awt.Graphics;

public abstract class MyBoundedShape extends MyShape
{
  
  private int x1; // x coordinate of first endpoint
  private int y1; // y coordinate of first endpoint
  private int x2; // x coordinate of second endpoint
  private int y2; // y coordinate of second endpoint
  private Color colour; // colour of the shape
  private boolean filled; // checks whether or not the shape is filled
  
  // A no-parameter constructor
  public MyBoundedShape () {
    x1 = 0;
    y1 = 0;
    x2 = 0;
    y2 = 0;
    colour = Color.BLACK;
    this.filled = false;
  }
  
  // A constructor that initializes the coordinates, colour, and fill state to the
  // values of the parameters supplied.
  public MyBoundedShape ( int x1, int y1, int x2, int y2, Color col, boolean filled ) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.colour = col;
    this.filled = filled;
  }
  
  // ------------------------------------------------------------------------------
  // Get and set methods that calculate the upper-left x-coordinate, upper-left 
  // y-coordinate, width, and height, and manipulate fill state.
  // ------------------------------------------------------------------------------
  
  // Method to get the width
  public int getWidth() {
    return ( Math.abs(x2 - x1) );
  }
  
  // Method to get the height
  public int getHeight () {
    return ( Math.abs(y2 - y1) );
  }
  
  // Method to get the upper x coordinate
  public int getUpperLeftX () {
    return ( Math.min(x1, x2) );
  }
  
  // Method to get the upper y coordinate
  public int getUpperLeftY () {
    return ( Math.min(y1, y2) );
  }
  
  // Method to get the fill state
  public boolean getFill () {
    return this.filled;
  }
  
  // Method to set the fill state
  public void setFill (boolean filled) {
    this.filled = filled;
  }
  
}
import java.awt.Color;
import java.awt.Graphics;

public class MyRectangle extends MyBoundedShape
{
  
  // No-parameter constructor
  public MyRectangle () {
    super.setX1(0);
    super.setY1(0);
    super.setX2(0);
    super.setY2(0);
    super.setColor(Color.BLACK);
    super.setFill(false);
  }
  
  // Constructor with parameters for the coordinates, colour, and fill state
  public MyRectangle( int x1, int y1, int x2, int y2, Color colour, boolean filled )
  {
    super.setX1(x1); // set x coordinate of first endpoint
    super.setY1(y1); // set y coordinate of first endpoint
    super.setX2(x2); // set x coordinate of second endpoint
    super.setY2(y2); // set y coordinate of second endpoint
    super.setColor(colour); // set the colour
    super.setFill(filled); // set whether or not the shape is filled
  }
  
  // Draw the shapes
  public void draw( Graphics g )
  {
    g.setColor( super.getColor() );
    g.drawRect( super.getX1(), super.getY1(), super.getX2(), super.getY2() );
    if ( super.getFill() == true ) {
      g.fillRect( super.getX1(), super.getY1(), super.getX2(), super.getY2() );
    }
  }
  
  
  
}

The painting issue is because you're only painting your shapes in the array when currentShapeObject is not null - which is only the case when the mouse button is down. If you change your painting code to this the problem resolves

// draw the shapes
      for (int i = 0; i < numOfShapes; i++) {
        shapeObjects[i].draw( g );
      }

    // If currentShapeObject is null, do nothing
    if ( currentShapeObject != null ) {
      currentShapeObject.draw( g );
    }

Keep in mind that currentShapeObject is the currently drawing object while you're dragging the mouse.

As far as the shape combo box problem, consider that the selection indices are zero-based. Read your event handler with that in mind.

On a more general note, you don't need to preface every call to an inherited method with "super.". You only need to use that if you've overridden the method and you want to execute the code in the parent class' version of that method. You can drop the "super" from most of the method calls in your shape objects.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.