Java Video Tutorial 48

Make a Java Paint ApplicationThis tutorial is going to be a ton of fun. Today I’ll show you how to Make a Java Paint Application!

One of you guys asked me to do this and it gives me a great opportunity to review and cover new topics all at once. Somethings I cover that you may want to brush up on include using the Java Box Layout, Java ArrayList, and Java Graphics2D.

All of the code follows the video and it is heavily commented. If you have questions, feel free to ask. Everything used is here Zipped Archive

If you like this video, tell Google please
Sharing is always appreciated

Code from the Video

import javax.swing.*;

import java.awt.event.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.*;

public class Lesson48 extends JFrame
{
	
		JButton brushBut, lineBut, ellipseBut, rectBut, strokeBut, fillBut;
		
		// Going to be used to monitor what shape to draw next
		
		int currentAction = 1;
		
		// Default stroke and fill colors
		
		Color strokeColor=Color.BLACK, fillColor=Color.BLACK;
	
        public static void main(String [] args)
        {
                new Lesson48();
        }

        public Lesson48()
        {
        	// Define the defaults for the JFrame
        	
            this.setSize(500, 500);
            this.setTitle("Java Paint");
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            JPanel buttonPanel = new JPanel();
            
            // Swing box that will hold all the buttons
            
            Box theBox = Box.createHorizontalBox();
            
            // Make all the buttons in makeMeButtons by passing the
            // button icon. 
            
            brushBut = makeMeButtons("./src/brush.png", 1);
            lineBut = makeMeButtons("./src/Line.png", 2);
            ellipseBut = makeMeButtons("./src/Ellipse.png", 3);
            rectBut = makeMeButtons("./src/Rectangle.png", 4);
            
            // Make all the buttons in makeMeColorButton by passing the
            // button icon and true for stroke color or false for fill
            
            strokeBut = makeMeColorButton("./src/Stroke.png", 5, true);
            fillBut = makeMeColorButton("./src/Fill.png", 6, false);
            
            // Add the buttons to the box
            
            theBox.add(brushBut);
            theBox.add(lineBut);
            theBox.add(ellipseBut);
            theBox.add(rectBut);
            theBox.add(strokeBut);
            theBox.add(fillBut);
            
            // Add the box of buttons to the panel
            
            buttonPanel.add(theBox);

            // Position the buttons in the bottom of the frame
            
            this.add(buttonPanel, BorderLayout.SOUTH);
            
            // Make the drawing area take up the rest of the frame
            
            this.add(new DrawingBoard(), BorderLayout.CENTER);
            
            // Show the frame
            
            this.setVisible(true);
        }
        
        // Spits out buttons based on the image supplied
        // actionNum represents each shape to be drawn
        
        public JButton makeMeButtons(String iconFile, final int actionNum){
        	JButton theBut = new JButton();
            Icon butIcon = new ImageIcon(iconFile);
            theBut.setIcon(butIcon);
            
            // Make the proper actionPerformed method execute when the
            // specific button is pressed
            
            theBut.addActionListener(new ActionListener() {

				public void actionPerformed(ActionEvent e) {
					currentAction = actionNum;
					System.out.println("actionNum: " + actionNum);
					
				}
            });
            
            return theBut;  
        }
        
        // Spits out buttons based on the image supplied and
        // whether a stroke or fill is to be defined
        
        public JButton makeMeColorButton(String iconFile, final int actionNum, final boolean stroke){
        	JButton theBut = new JButton();
            Icon butIcon = new ImageIcon(iconFile);
            theBut.setIcon(butIcon);
            
            theBut.addActionListener(new ActionListener() {

				public void actionPerformed(ActionEvent e) {
					
					if(stroke){
						
						// JColorChooser is a popup that lets you pick a color
						
						strokeColor = JColorChooser.showDialog(null,  "Pick a Stroke", Color.BLACK);
					} else {
						fillColor = JColorChooser.showDialog(null,  "Pick a Fill", Color.BLACK);
					}
					
				}
            });
            
            return theBut;  
        }

        private class DrawingBoard extends JComponent
        {
        	
        	// ArrayLists that contain each shape drawn along with
        	// that shapes stroke and fill
        	
                ArrayList<Shape> shapes = new ArrayList<Shape>();
                ArrayList<Color> shapeFill = new ArrayList<Color>();
                ArrayList<Color> shapeStroke = new ArrayList<Color>();
                Point drawStart, drawEnd;

                // Monitors events on the drawing area of the frame
                
                public DrawingBoard()
                {
                        this.addMouseListener(new MouseAdapter()
                          {
                            public void mousePressed(MouseEvent e)
                            {
                            	
                            	// When the mouse is pressed get x & y position
                            	
                            	drawStart = new Point(e.getX(), e.getY());
                            	drawEnd = drawStart;
                                repaint();
                                }

                            public void mouseReleased(MouseEvent e)
                                {
                            	
                            	  // Create a shape using the starting x & y
                            	  // and finishing x & y positions
                            	
                                  Shape aShape = drawRectangle(
                                		  drawStart.x, drawStart.y,
                                                      e.getX(), e.getY());
                                  
                                  // Add shapes, fills and colors to there ArrayLists
                                  
                                  shapes.add(aShape);
                                  shapeFill.add(fillColor);
                                  shapeStroke.add(strokeColor);
                                  
                                  drawStart = null;
                                  drawEnd = null;
                                  
                                  // repaint the drawing area
                                  
                                  repaint();
                                }
                          } );

                        this.addMouseMotionListener(new MouseMotionAdapter()
                        {
                          public void mouseDragged(MouseEvent e)
                          {
                        	  
                        	// Get the final x & y position after the mouse is dragged
                        	  
                        	drawEnd = new Point(e.getX(), e.getY());
                            repaint();
                          }
                        } );
                }
                

                public void paint(Graphics g)
                {
                		// Class used to define the shapes to be drawn
                	
                        Graphics2D graphSettings = (Graphics2D)g;

                        // Antialiasing cleans up the jagged lines and defines rendering rules
                        
                        graphSettings.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
                        
                        // Defines the line width of the stroke
                        
                        graphSettings.setStroke(new BasicStroke(2));

                        // Iterators created to cycle through strokes and fills
                        Iterator<Color> strokeCounter = shapeStroke.iterator();
                        Iterator<Color> fillCounter = shapeFill.iterator();
                        
                        // Eliminates transparent setting below
                        
                        graphSettings.setComposite(AlphaComposite.getInstance(
                                AlphaComposite.SRC_OVER, 1.0f));
                        
                        for (Shape s : shapes)
                        {
                        	// Grabs the next stroke from the color arraylist
                        	graphSettings.setPaint(strokeCounter.next());
                        	
                        	graphSettings.draw(s);
                        	
                        	// Grabs the next fill from the color arraylist
                        	graphSettings.setPaint(fillCounter.next());
                        	
                        	graphSettings.fill(s);
                        }

                        // Guide shape used for drawing
                        if (drawStart != null && drawEnd != null)
                        {
                        	// Makes the guide shape transparent
                            
                            graphSettings.setComposite(AlphaComposite.getInstance(
                                    AlphaComposite.SRC_OVER, 0.40f));
                        	
                            // Make guide shape gray for professional look
                            
                        	graphSettings.setPaint(Color.LIGHT_GRAY);
                        	
                        	// Create a new rectangle using x & y coordinates
                        	
                                Shape aShape = drawRectangle(drawStart.x, drawStart.y,
                                		drawEnd.x, drawEnd.y);
                                graphSettings.draw(aShape);
                        }
                }

                private Rectangle2D.Float drawRectangle(
                        int x1, int y1, int x2, int y2)
                {
                	// Get the top left hand corner for the shape
                	// Math.min returns the points closest to 0
                	
                        int x = Math.min(x1, x2);
                        int y = Math.min(y1, y2);
                        
                        // Gets the difference between the coordinates and 
                        
                        int width = Math.abs(x1 - x2);
                        int height = Math.abs(y1 - y2);

                        return new Rectangle2D.Float(
                                x, y, width, height);
                }
                
                // The other shapes will work similarly
                // More on this in the next tutorial
                
                private Ellipse2D.Float makeEllipse(
                        int x1, int y1, int x2, int y2)
                {
                        int x = Math.min(x1, x2);
                        int y = Math.min(y1, y2);
                        int width = Math.abs(x1 - x2);
                        int height = Math.abs(y1 - y2);

                        return new Ellipse2D.Float(
                                x, y, width, height);
                }
        }
}

23 Responses to “Java Video Tutorial 48”

  1. Punit says:

    wowwwwwww, it’s awesome..
    please make something for collision detection as well.

  2. Nokke says:

    Thanks alot for the amazing tutorial. I have studiet it around 3 times. I want to be able to create it with out looking att your code πŸ™‚

    • admin says:

      You’re very welcome πŸ™‚ Practicing and experimenting with your own ideas is the best way to go. If you learn to program out of your head, you’ll be able to make anything you can imagine

  3. ManuChao says:

    Great tutorial!
    I am learning Design Patterns and I noticed that those kind of software is the best way to learn how to use Design Patterns.
    Can you please make a case study video tutorial of a paint application by using Design Patterns ?
    I think it will help newbies like me, how to apply OOAD and Design Patterns in real world projects.
    Thanks in advance.

    • admin says:

      Thank you πŸ™‚ I am still working with Object Oriented Design in my current tutorial. I will cover more before it is over. I also will be covering design patterns further in my next tutorial on refactoring. I hope that helps

  4. Marten says:

    All the time when I made a mouseListener and checked(with the simple System.out.println method) whether the repaint method worked when I release the mouse or not I got no result.

    I put the System.out.println method in the paint(Graphics g) method, but it still doesn’t print something in the console when I repaint.

    Do you have any idea what probably may have gone wrong?

    Btw thanks for the time you spent with helping people! I appreciate it!

    • Derek Banas says:

      You are very welcome πŸ™‚ Did you copy the code directly from my website? Are you getting any error messages? I’ll do my best to help

      • Marten says:

        I only have used a part of your code but I tried to change it a little bit and play with it.

        private class drawStuff extends JComponent
        {
        public void paint(Graphics g)
        {
        Graphics2D graph2 = (Graphics2D)g;

        textArea.append(“PAINTING COMPONENT!\n”);

        }
        }

        • Marten says:

          I tried to repaint it in the timer that I used, a schoolmate told me that I should use paintComponent. He didn’t even know that there is just a paint method.

          I do not understand cause when I run the program, the paint method is called. (3 times; β€œPAINTING COMPONENT!\n” appears) And it still does when I delete the repaint method and then run it again. The repaint method makes no difference…

          The timer;
          //Timer
          new Timer((1000 / 60), new ActionListener() {

          public void actionPerformed(ActionEvent e) {
          repaint();

          }

          }).start();

          I’m still very glad there’s someone who want to help me(on the web)!

          • Anonymous says:

            Just made another version that works. I showed my friend who’s good at programming, but even he couldnt find a solution. We created a new file. I’m glad it now works.

            And again; Thanks for your tutorials!

  5. Jackwill says:

    Can I use this code for my assigment what do I need to change in this code to make it my own ?

  6. Satyaprakash Singh says:

    hey! thank you very much it’s really helpful to me to design more stuffs using this…

  7. umair says:

    I didn’t about “currentAction = actionNum;”

    Is it an alternative for “e.getSource=buton”

    Thank you

  8. Razvan says:

    What IDE do you use? I try opening the archived files you sent with eclipse,but eclipse does not recognize it as an eclipse project

Leave a Reply

Your email address will not be published.

Google+