Search code examples
javagraphicsnullpointerexceptionlistenerpaint

java simple paint program mouse listeners


I am trying to write a simple painting program in Java and I can't seem to get my head around the different types of mouse listeners and how they function.

I have made my mouse pressed listener such that it creates a new instance of a line to which points are added to whilst the mouse is being dragged, and then this line is added to my arraylist of lines upon the mouse being released and the value of the currentLine variable is reset so that a new line of points can be recorded.

This is NOT a null pointer exception misunderstanding issue, I know what a null pointer exception is; I do not understand WHY I am getting one due to my misunderstanding of mouse listeners. As you can see my mentality is that a new instance of a line is made when the mouse is pressed so that any points can be added when the mouse is being dragged.

If anyone has any advice to offer as to where I am going wrong I would greatly appreciate it. Thanks alot

My program consists of the following classes:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Canvas extends JPanel {

private ArrayList<Line> lines = new ArrayList<Line>();
private Line currentLine;

public Canvas() {

    this.init();
    this.frameInit();

}

private void init() {

    this.setPreferredSize(new Dimension(600,600));

    this.addMouseMotionListener(new MouseAdapter() {

        public void mousePressed(MouseEvent e) {

            currentLine = new Line();

        }

        public void mouseDragged(MouseEvent e) {

            currentLine.points.add(e.getPoint());
            repaint();

        }

        public void mouseReleased(MouseEvent e) {

            if(!currentLine.points.isEmpty()) {
                lines.add(currentLine);
            }

            currentLine=null;

        }

    });

}

private void frameInit() {

    JFrame window = new JFrame("GPaint");
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setContentPane(this);
    window.pack();
    window.setVisible(true);

}

public void paintComponent(Graphics g) {

    Graphics2D twoD = (Graphics2D) g;
    twoD.setColor(Color.RED);
    twoD.setStroke(new BasicStroke(6));

    if(!lines.isEmpty()) {

        for(Line l: lines) {

            if(l.points.size()>1) {

                for(int i=1; i<l.points.size()-1; i++) {

                    twoD.drawLine(l.points.get(i-1).x, l.points.get(i-1).y, l.points.get(i).x, l.points.get(i).y);

                }

            }

            if(l.points.size()==1){

                //0 index as there is only one point, so fill an oval
                twoD.fillOval(l.points.get(0).x-3, l.points.get(0).y-3, 6, 6);

            }

        }

    }

}

}

import java.awt.Point;
import java.util.ArrayList;

public class Line {

ArrayList<Point> points;

public Line() {

    points = new ArrayList<Point>();

}

}

Here is the results of the stack:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Canvas$1.mouseDragged(Canvas.java:39)
at java.awt.Component.processMouseMotionEvent(Component.java:6581)
at javax.swing.JComponent.processMouseMotionEvent(JComponent.java:3342)
at java.awt.Component.processEvent(Component.java:6302)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4542)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Solution

  • The problem is you need to register a MouseListener to receive mousePressed and mouseReleased events.

    Adding the following will solve your problem.

    this.addMouseListener(new MouseAdapter() {
    
        @Override
        public void mousePressed(MouseEvent e) {
            currentLine = new Line();
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
            if (!currentLine.points.isEmpty()) {
                lines.add(currentLine);
            }
            currentLine = null;
        }
    });