0

I can get the program to come up and paint with one color, but it will not change colors if i click one of the buttons. I keep getting a null pointer exception. I think it might be because I haven't initialized either the graphic, image, or both. If it is that problem I'm not quite sure how to go about fixing that. I'm fairly new to programming and any help would be much appreciated.

Code:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;


    public class Paint extends JFrame{
        //Class Variables
        private JFrame frame;
        PaintPanel paint_panel;
        private JPanel btn_panel;
        private JButton red_btn, green_btn, blue_btn, clear_btn, erase_btn ;



        //class to paint the panel in the frame
        public class PaintPanel extends JComponent{     
            //Class Variables
            private Graphics2D g;
            private int x1, y1, x2, y2;
            private Cursor paint_cursor, select_cursor;
            private Image image;

            //Constructor with Mouse listeners in it  
            public PaintPanel(){

                 addMouseListener(new MouseAdapter(){
                     public void mousePressed(MouseEvent e){
                             x1 = e.getX();
                             y1 = e.getY();
                             }
                    });
                 addMouseMotionListener(new MouseMotionAdapter(){

                     public void mouseDragged(MouseEvent e){
                             x2 = e.getX();
                             y2 = e.getY();

                             if(g != null)
                                 g.drawLine(x1, y1, x2, y2);
                             repaint();
                             x1 = x2;
                             y1 = y2;
                     }
             });
             }
            //PaintPanel Method that sets the cursor and does the drawing
            public void paintComponent(Graphics gr){
                super.paintComponent(gr);
                gr.setColor(Color.black);
                gr.fillRect(0, 0, this.getWidth(), this.getHeight());
                paint_cursor=new Cursor(Cursor.CROSSHAIR_CURSOR);
                select_cursor=new Cursor(Cursor.HAND_CURSOR);
                paint_panel.setCursor(paint_cursor);
                btn_panel.setCursor(select_cursor);
                if(image == null){
                    image = createImage(this.getWidth(), this.getHeight());
                    g = (Graphics2D)image.getGraphics();
                    clear1();
                 }
                 gr.drawImage(image, 0, 0, null);
         }
             public void clear1(){
                g.setPaint(Color.black);
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
                g.setPaint(Color.blue);
                repaint();  
             }
             public void red(){ 
                 g.drawLine(x1, y1, x2, y2);
                 g.setPaint(Color.red);

                 x1 = x2;
                 y1 = y2;
                 repaint();
             }
             public void blue(){    
                 g.drawLine(x1, y1, x2, y2);
                 g.setPaint(Color.blue);

                 x1 = x2;
                 y1 = y2;
                 repaint();
             }
             public void green(){   
                g.drawLine(x1, y1, x2, y2);
                g.setPaint(Color.green);

                 x1 = x2;
                 y1 = y2;
                 repaint();
             }
            }

        //Constructor
        public Paint(){

            frame = new JFrame("Paint Program");
            frame.setSize(500,500);
            frame.setLocation(500,100);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



            red_btn = new JButton("RED");
            green_btn = new JButton("GREEN");
            blue_btn = new JButton("BLUE");
            clear_btn = new JButton("CLEAR");
            erase_btn = new JButton("ERASE");

            btn_panel = new JPanel();
            paint_panel = new PaintPanel();

            btn_panel.setLayout(new GridLayout(5,1));

            btn_panel.add(red_btn);
            btn_panel.add(green_btn);
            btn_panel.add(blue_btn);
            btn_panel.add(clear_btn);
            btn_panel.add(erase_btn);
            frame.add(BorderLayout.CENTER, paint_panel);
            frame.add(BorderLayout.EAST, btn_panel);

            final PaintPanel pp1 = new PaintPanel();

            red_btn.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    pp1.red();
                }   
                });
            blue_btn.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    pp1.blue();
                }   
                });
            green_btn.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    pp1.green();
                }   
                });
            clear_btn.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    pp1.clear1();
                }   
                });
            erase_btn.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    pp1.green();
                }   
                });
        }
        //Makes the frame visible and working
        public void launch(){
            frame.setVisible(true);
        }

        //Main Method
        public static void main(String[] args){
            Paint p1 = new Paint();
            p1.launch();
        }
    }
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Which line is the NPE being thrown? – JRSofty Jul 05 '12 at 14:30
  • Welcome to Stack Overflow! Please restrict your code sample to a relevant portion. The ideal sample is [short, self-contained and compilable](http://sscce.org/). Reading through an entire source code is time-consuming, and will net you less answers. – David B Jul 05 '12 at 14:31
  • `private Graphics2D g;` The problems start there, I suspect.. Graphics objects are typically transient - there and gone. – Andrew Thompson Jul 05 '12 at 14:32
  • I i click the red button for example it throws it at: Line 69 in the red method --> g.drawLine(x1, y1, x2, y2); – user1504257 Jul 05 '12 at 14:35
  • and line 127 in the red_btn action listener – user1504257 Jul 05 '12 at 14:36
  • We don't have line numbers on the code. – David B Jul 05 '12 at 14:37
  • its the pp1.red(); in the red_btn action listener – user1504257 Jul 05 '12 at 14:40
  • For what you seem to be trying, I would recommend you keep a reference to a buffered image that is displayed in a `JLabel`. When you need to do something, anything, get the `Graphics` from it, draw to it, dispose of it, and call repaint. I put an example [here](http://stackoverflow.com/a/11330719/418556). You might want to reduce the '5000' to something more sensible. That was about scrolling a BIG animation. – Andrew Thompson Jul 05 '12 at 14:56

2 Answers2

1

Storing your graphics object is what's getting you into trouble. The simple answer is that all painting needs to be done via JComponent.paintComponent(...) so your red() green() blue() should be called by paintComponent with the Graphics object from paintComponent

Fundamentally, the way java painting works is that everything gets drawn in the same cycle, through the callback to paint() / paintcomponent(). The mechanism works this way so that components can look different at different times, with different mouse / click states, etc

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
1

You are calling red() method from the button listener, and once there you are using x1, x2, y1 and y2 values when you call drawLine. Where are you initialising those variables?

You are relying on those variables should be written when clicking with the mouse, but that may not happen. Try to initialize them in the constructor.

Roman Rdgz
  • 12,836
  • 41
  • 131
  • 207