Search code examples
javaswingbufferedimagegraphics2dpaintcomponent

repaint() not calling PaintComponent to use Graphics2D


I have spent a few days now trying to get the Graphics2D class to work within my code. I have it structured in such a way that when a click event is registered the call to repaint is done, however this only produces a nullpointer exception when it reaches the stage of calling repaint().

It is all working as expected when debugging and not called from within the paintComponent method, however when trying to call the code properly using paintComponent and repaint() to allow the Graphics2D class to display the lines to each point, It's not working.

I have included the parts of my code that I am having difficulty getting to work. Any help whatsoever will really be appreciated. Thank you in advance.

Below is the GUI class that incldes my mouseListener.

public class GUI extends JPanel implements MouseListener {

private JLabel label;

    public BufferedImage getImg() {
    return img;
    }

    public void mouseClicked(java.awt.event.MouseEvent e) {
    // TODO Auto-generated method stub
    label = new JLabel();

    //set point equal to the location of the mouse click on the image label
    Point b = e.getPoint();

    //place we are going to print the dots
    segmentation.x = b.x; //gets the x coordinate 
    segmentation.y = b.y; //gets the y coordinate

    System.out.println("x = " + segmentation.x);
    System.out.println("y = " + segmentation.y);        

    //set the global img in the segmentation class equal to that of the one in the current tab
    segmentation.setImg(tabbedPane.getSelectedIndex(), getImg());
    segmentation.paintUpdate();
    label = segmentation.getLabel();

    //if i run this line of code the existing label I already have with simply vanish because of the paintComponent method not being called upon properly.
    //tabbedPane.setComponentAt(tabbedPane.getSelectedIndex(), label);
}

This is the Segmentation class that includes the paintComponent method that I am having trouble calling upon properly.

public class Segmentation extends JLabel {

public int[] xpoints = new int[50];
public int[] ypoints = new int[50];
private int npoints = 0;
public int x;
public int y;
GeneralPath polyline;
Graphics2D g2;
JLabel label;
BufferedImage img;
ImageIcon icon;

public void paintUpdate() {
    repaint();
}

public void setImg(int tabNum, BufferedImage img) {
    this.img = img;
}

public GeneralPath createPath() {

    //      if (npoints > 0) {
    polyline.moveTo(xpoints[0], ypoints[0]);

    for(int i = 1; i < xpoints.length; i++) {
        //add the position of the point to the respective x and y arrays
        polyline.lineTo(xpoints[i], ypoints[i]);        
    }
    //      }
    return polyline;
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    System.out.println("we're in the paint component method");

    //set up for the new jlabel
    label = new JLabel();
    label.setIcon(new javax.swing.ImageIcon(img));
    label.setHorizontalAlignment(JLabel.LEFT);
    label.setVerticalAlignment(JLabel.TOP);

    //add the position of the point to the respective x and y arrays
    xpoints[npoints] = x;
    ypoints[npoints] = y;

    if (npoints == 0) {
        JOptionPane.showMessageDialog(null, "Your first point has been added successfully");
    }
    else {
        JOptionPane.showMessageDialog(null, "Your " + npoints + " rd/th" + " point has been added successfully");
    }

    polyline = createPath();

    // Draws the buffered image to the screen.
    g2.drawImage(img, 0, 0, this);

    g2.draw(polyline);

    npoints++;
}

Solution

  • Your Segmentation class has two JLabels, one the object of the class itself, which has a paintComponent override and is likely never used:

    public class Segmentation extends JLabel {
    

    and the other a JLabel called label which is held by composition in the class which doesn't have the method override which is in fact used and appears to be "shadowing" the class's instance:

    JLabel label
    

    If you want paintComponent to be called, you'll need to use the label object that in fact overrides that method.

    Also you appear to be creating components within the paintComponent(...) method (??). Never do that nor have program logic within this method.

    Edit:
    To draw on an image, I usually override paintComponent and draw with its Graphics/Graphics2D object. For example:

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.RenderingHints;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Line2D;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class DrawOnLabel extends JLabel {
       public static final String GIRAFFE_IMG_URL = "http://upload.wikimedia.org/wikipedia/commons/thumb" +
            "/9/9e/Giraffe_Mikumi_National_Park.jpg/474px-Giraffe_Mikumi_National_Park.jpg";
       private static final Color LINES_COLOR = Color.red;
       private static final Color CURRENT_LINE_COLOR = new Color(255, 200, 200);
       private List<Line2D> lineList = new ArrayList<Line2D>();
       private Line2D currentLine = null;
    
       public DrawOnLabel() throws IOException {
          URL giraffeUrl = new URL(GIRAFFE_IMG_URL);
          BufferedImage img = ImageIO.read(giraffeUrl);
          ImageIcon icon = new ImageIcon(img);
          setIcon(icon);
    
          MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
          addMouseListener(myMouseAdapter);
          addMouseMotionListener(myMouseAdapter);
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    
          g2.setColor(LINES_COLOR);
          for (Line2D line : lineList) {
             g2.draw(line);
          }
          if (currentLine != null) {
             g2.setColor(CURRENT_LINE_COLOR);
             g2.draw(currentLine);
          }
       }
    
       private class MyMouseAdapter extends MouseAdapter {
          Point p1 = null;
    
          @Override
          public void mousePressed(MouseEvent e) {
             p1 = e.getPoint();
          }
    
          @Override
          public void mouseReleased(MouseEvent e) {
             if (currentLine != null) {
                currentLine = new Line2D.Double(p1, e.getPoint());
                lineList.add(currentLine);
                currentLine = null;
                p1 = null;
                repaint();
             }
          }
    
          @Override
          public void mouseDragged(MouseEvent e) {
             if (p1 != null) {
                currentLine = new Line2D.Double(p1, e.getPoint());
                repaint();
             }
    
          }
       }
    
       private static void createAndShowGui() {
          DrawOnLabel mainPanel = null;
          try {
             mainPanel = new DrawOnLabel();
          } catch (IOException e) {
             e.printStackTrace();
             System.exit(-1);
          }
    
          JFrame frame = new JFrame("DrawOnLabel");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.setResizable(false);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }