Skip to content

Repository files navigation

Paint Program

A Java Swing-based paint application developed as a Data Structures and Algorithms project during senior year of high school (May 2020).

Project Overview

This is a fully functional drawing application built using Java Swing that allows users to create digital artwork with various tools including freehand drawing and rectangle shapes. The program supports multiple colors, adjustable brush sizes, and includes undo/redo functionality along with file save/load capabilities.

Features

  • Drawing Tools

    • Freehand drawing (continuous line drawing)
    • Rectangle shape tool
  • Color Selection

    • 7 preset colors: Red, Orange, Yellow, Green, Blue, Magenta, White
    • JColorChooser for custom color selection
  • Brush Size Control

    • Adjustable stylus/pen width (1-50 pixels) via horizontal scrollbar
  • Undo/Redo Functionality

    • Full undo/redo support for all drawing operations
    • Separate tracking for lines and shapes
  • File Operations

    • Save drawings as PNG images
    • Load existing images to edit or use as background

Code Structure

Main Class: PaintProgram

Location: PaintProgram.java:12

The main class extends JPanel and implements multiple listener interfaces:

  • MouseMotionListener - Tracks mouse dragging for drawing
  • MouseListener - Handles mouse press/release events
  • ActionListener - Processes button clicks and menu selections
  • AdjustmentListener - Monitors scrollbar changes for brush size
  • ChangeListener - Detects color chooser changes

Data Structures Used

1. ArrayLists (Dynamic Arrays)

  • ArrayList<ArrayList<Point>> lines (PaintProgram.java:14) - Stores all completed freehand lines
  • ArrayList<Shape> shapes (PaintProgram.java:15) - Stores all drawn shapes (rectangles)
  • ArrayList<Point> points (PaintProgram.java:17) - Temporary storage for current line being drawn

Theory: ArrayLists provide O(1) amortized time for adding elements and O(1) access time by index, making them ideal for storing and iterating through drawing elements during the paint operation.

2. Stacks (LIFO - Last In First Out)

  • Stack<Shape> undoShapes (PaintProgram.java:16) - Stores undone shapes
  • Stack<ArrayList<Point>> undoLines (PaintProgram.java:18) - Stores undone lines
  • Stack<String> commandOrder (PaintProgram.java:19) - Tracks order of operations
  • Stack<String> undoCommandOrder (PaintProgram.java:20) - Tracks undone operations

Theory: Stacks are perfect for undo/redo operations because they follow LIFO principle. The most recent action is the first to be undone, which matches user expectations. Operations are O(1) for push and pop.

Inner Classes

1. Point Class (PaintProgram.java:387-402)

Represents a single point in a freehand line with properties:

  • x, y coordinates
  • Color
  • Pen width

2. Shape Class (PaintProgram.java:404-434)

Base class for drawable shapes containing:

  • Position (x, y)
  • Dimensions (width, height)
  • Color
  • Pen width
  • Getter/setter methods

3. Block Class (PaintProgram.java:436-446)

Extends Shape to represent rectangles. Provides a getRect() method that returns a java.awt.Rectangle object for rendering.

Algorithm Analysis

Drawing Algorithm

Freehand Drawing (PaintProgram.java:239-240, 166-173):

1. On mouse drag: Add new Point to points ArrayList
2. On mouse release: Move points ArrayList to lines collection
3. On repaint: Iterate through all lines and draw line segments between consecutive points
  • Time Complexity: O(n) where n is number of points in all lines
  • Space Complexity: O(n) for storing all points

Rectangle Drawing (PaintProgram.java:241-263):

1. On first drag: Record starting coordinates, create new Shape
2. On continued drag: Calculate width/height from current position, update Shape
3. Handle negative dimensions (dragging left/up from start point)
4. On mouse release: Finalize shape
  • Time Complexity: O(1) for drawing, O(m) for rendering all m shapes
  • Space Complexity: O(m) where m is number of shapes

Undo/Redo Algorithm

Undo Operation (PaintProgram.java:294-318):

1. Pop command from commandOrder stack
2. Push command to undoCommandOrder stack
3. Based on command type:
   - If "freeLine": Pop from lines, push to undoLines
   - If "shape": Pop from shapes, push to undoShapes
4. Repaint canvas
  • Time Complexity: O(1) for undo operation + O(n+m) for repaint
  • Space Complexity: O(k) where k is number of undone operations

Redo Operation (PaintProgram.java:319-339):

1. Pop command from undoCommandOrder stack
2. Push command back to commandOrder stack
3. Restore the drawing element from undo stack to active collection
4. Repaint canvas
  • Time Complexity: O(1) for redo operation + O(n+m) for repaint

Rendering Algorithm

paintComponent Method (PaintProgram.java:131-186):

1. Clear canvas with black background
2. If loaded image exists, draw it
3. Iterate through all lines:
   - For each line, draw segments between consecutive points
   - Apply color and stroke width per point
4. Iterate through all shapes:
   - Draw each shape with its color and stroke width
5. Draw current line being drawn (if in freehand mode)
  • Time Complexity: O(n + m) where n is total points, m is total shapes
  • Space Complexity: O(1) additional space for rendering

Data Structures Theory

Why These Data Structures?

  1. ArrayList for Drawing Elements

    • Fast iteration for rendering (critical for repaint performance)
    • Dynamic sizing handles arbitrary number of drawing elements
    • Random access allows efficient rendering in any order
  2. Stack for Undo/Redo

    • Natural fit for "reverse last action" semantics
    • LIFO property matches user mental model
    • Efficient O(1) push/pop operations
    • Maintains operation history without complex tracking
  3. Nested ArrayList Structure (ArrayList<ArrayList<Point>>)

    • Separates individual lines while maintaining drawing order
    • Allows per-line operations (delete entire line on undo)
    • Preserves temporal and spatial grouping

Trade-offs Considered

ArrayList vs LinkedList:

  • Chose ArrayList for better cache locality during frequent iteration in paintComponent
  • Acceptable O(n) removal cost on undo (infrequent operation)

Stack vs Custom Implementation:

  • Used built-in Stack despite being legacy class
  • Alternative: Deque interface (recommended in modern Java)
  • Benefit: Simple, well-tested implementation

commandOrder Stack:

  • Tracks operation types separately from data
  • Allows heterogeneous undo/redo (mixing lines and shapes)
  • Small memory overhead (strings) vs maintaining complex polymorphic structure

GUI Components

  • JFrame - Main application window
  • JMenuBar - Top menu bar containing:
    • File menu (Save/Open)
    • Color menu (7 color buttons + color chooser)
    • Tool buttons (Free line, Rectangle)
    • Undo/Redo buttons
    • Size scrollbar
  • JPanel - Custom drawing canvas (extends PaintProgram)
  • JFileChooser - File selection dialogs

File Structure

Paint/
├── PaintProgram.java          # Main application source code
├── PaintProgram.class          # Compiled main class
├── PaintProgram$Point.class    # Compiled inner class
├── PaintProgram$Shape.class    # Compiled inner class
├── PaintProgram$Block.class    # Compiled inner class
├── FreeLine.png                # Free line tool icon
├── rectangle.png               # Rectangle tool icon
├── undo.png                    # Undo button icon
├── redo.png                    # Redo button icon
└── art/                        # Sample artwork created with the program
    ├── Ali.png
    ├── Earth.png
    ├── Hello.png
    ├── Husain.png
    └── bob.jpg.png

How to Run

Prerequisites

  • Java Development Kit (JDK) 8 or higher
  • Java Runtime Environment (JRE)

Compilation

javac PaintProgram.java

Execution

java PaintProgram

Technical Details

Graphics Rendering

  • Uses Graphics2D for advanced rendering capabilities
  • BasicStroke for variable line widths
  • Double buffering via Swing's built-in mechanism
  • Custom paintComponent override for drawing logic

Mouse Event Handling

  • mouseDragged - Captures drawing input
  • mouseReleased - Finalizes drawing operations
  • Continuous point capture for smooth freehand lines

File I/O

  • BufferedImage for image representation
  • ImageIO for PNG file reading/writing
  • Custom createImage() method converts canvas to BufferedImage

Learning Outcomes

This project demonstrates practical application of:

  • Data Structures: ArrayList, Stack, nested collections
  • Object-Oriented Programming: Inheritance (Shape/Block), encapsulation
  • Event-Driven Programming: Multiple listener interfaces
  • GUI Development: Swing framework, custom rendering
  • Algorithm Design: Undo/redo pattern, rendering optimization
  • File I/O: Image reading/writing with ImageIO

Limitations & Future Enhancements

Current Limitations:

  • Only rectangle shape supported (oval button visible but not implemented)
  • No eraser tool
  • No layer support
  • Limited to raster graphics (no vector format export)
  • Undo stack has no size limit (potential memory issue)

Potential Enhancements:

  • Add oval/circle drawing tool
  • Implement fill vs outline mode for shapes
  • Add eraser functionality
  • Support for more file formats (JPEG, GIF)
  • Implement zoom functionality
  • Add text tool
  • Layer support for complex compositions

Project Context

This project was completed in May 2020 as part of a Data Structures and Algorithms course at South Brunswick High School (SBHS). The primary educational goal was to demonstrate practical application of stack and list data structures in a real-world application.

The project successfully showcases:

  • Proper data structure selection based on use case
  • Algorithm efficiency considerations
  • Clean separation of data model and view
  • Professional Java programming practices

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages