A Java Swing-based paint application developed as a Data Structures and Algorithms project during senior year of high school (May 2020).
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.
-
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
Location: PaintProgram.java:12
The main class extends JPanel and implements multiple listener interfaces:
MouseMotionListener- Tracks mouse dragging for drawingMouseListener- Handles mouse press/release eventsActionListener- Processes button clicks and menu selectionsAdjustmentListener- Monitors scrollbar changes for brush sizeChangeListener- Detects color chooser changes
ArrayList<ArrayList<Point>> lines(PaintProgram.java:14) - Stores all completed freehand linesArrayList<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.
Stack<Shape> undoShapes(PaintProgram.java:16) - Stores undone shapesStack<ArrayList<Point>> undoLines(PaintProgram.java:18) - Stores undone linesStack<String> commandOrder(PaintProgram.java:19) - Tracks order of operationsStack<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.
Represents a single point in a freehand line with properties:
- x, y coordinates
- Color
- Pen width
Base class for drawable shapes containing:
- Position (x, y)
- Dimensions (width, height)
- Color
- Pen width
- Getter/setter methods
Extends Shape to represent rectangles. Provides a getRect() method that returns a java.awt.Rectangle object for rendering.
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 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
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
-
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
-
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
-
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
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
- 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
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
- Java Development Kit (JDK) 8 or higher
- Java Runtime Environment (JRE)
javac PaintProgram.javajava PaintProgram- Uses
Graphics2Dfor advanced rendering capabilities BasicStrokefor variable line widths- Double buffering via Swing's built-in mechanism
- Custom
paintComponentoverride for drawing logic
mouseDragged- Captures drawing inputmouseReleased- Finalizes drawing operations- Continuous point capture for smooth freehand lines
BufferedImagefor image representationImageIOfor PNG file reading/writing- Custom
createImage()method converts canvas to BufferedImage
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
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
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