JButton being rendered twice when repaint function is called

Advertisements

I wrote a very simple paint program in Java. It isn’t the most elaborate, but it works as expected minus one flaw. Every time a line, circle, or rectangle is being positioned to be drawn and the repaint function is called, there is a duplicate rendering of the corresponding JButton that was last clicked. The artifact is being rendered on the top left-hand corner.

The relevant code is as follows:

import java.awt.*;
import java.util.HashSet;

import javax.swing.*;

public class MyPanel extends JPanel{
    
    static HashSet<Point> p2d = new HashSet<>();
    static HashSet<Rectangle> rectangles = new HashSet<>();
    static HashSet<Circle> circles = new HashSet<>();
    static HashSet<Line> lines = new HashSet<>();


MyPanel(){
  
  this.setPreferredSize(new Dimension(500,500));
 }
 
 public void paintComponent(Graphics g) {
  
  Graphics2D g2D = (Graphics2D) g;
  
  for(Point p : p2d) {
      g2D.drawLine(p.x, p.y, p.x, p.y);
  }
  
  for(Rectangle r: rectangles) {
      g2D.drawRect(r.x, r.y, r.w, r.l);
      
  }
  
  for(Circle c : circles) {
      g2D.drawOval(c.x, c.y, c.w, c.h);
  }
  
  for(Line l: lines) {
      g2D.drawLine(l.x1,l.y1, l.x2, l.y2);
      
  }
  
  
 }
 
 void addPoint(int x, int y){
     p2d.add(new Point(x,y));
 }
 
 void addRectangle(int x, int y, int l, int w) {
     rectangles.add(new Rectangle(x, y, l, w));
 }
 
 void addCircle(int x, int y, int w, int h){
     circles.add(new Circle(x, y, w, h));
 }
 
 void addLine(int x1, int y1, int x2, int y2) {
     lines.add(new Line(x1, y1, x2, y2));
 }
 
}

Defined above is the paint method for MyPanel which is the panel where the paint program draws the image.

Below is the MyPanel2 which is the panel which has the buttons where one can select which shape to draw, i.e., point, circle, rectangle, or line.

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;

import javax.swing.JButton;
import javax.swing.JPanel;

public class MyPanel2 extends JPanel{
    
    JButton point;
    JButton line;
    JButton rectangle;
    JButton circle;
    
    MyMouseAdapter mouseAdapter;

    
    public MyPanel2(MyMouseAdapter mouseAdapter) {
        super();
        this.mouseAdapter = mouseAdapter;
        
        point = new JButton("Point");
        line = new JButton("Line");
        rectangle = new JButton("Rectangle");
        circle = new JButton("Circle");
        
        point.addActionListener(e ->{mouseAdapter.setState('p');});
        line.addActionListener(e ->{mouseAdapter.setState('l');});
        rectangle.addActionListener(e ->{mouseAdapter.setState('r');});
        circle.addActionListener(e ->{mouseAdapter.setState('c');});
        
        
        this.add(point);
        this.add(line);
        this.add(rectangle);
        this.add(circle);
        
        this.setLayout(new GridLayout(4,1));
        
    }


    public MyPanel2() {
        

    }

}

Lastly, MyMouseAdapter has most of the program logic:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashSet;

public class MyMouseAdapter extends MouseAdapter{
    
      MyPanel panel;
      Graphics g;
      
        int xDragged;
        int yDragged;
        int xClicked;
        int yClicked;
        
        char state;
     
    
      public void setState(char state) {
            this.state = state;
        }



    public MyMouseAdapter(MyPanel panel) {
        super();
        this.panel = panel;
        g = panel.getGraphics();
    }



    public MyMouseAdapter() {
            super();
            panel = new MyPanel();
        }



     public void mousePressed(MouseEvent me) {
         
         xClicked = me.getX();
         yClicked = me.getY();

      }
     
     public void mouseDragged(MouseEvent me) {
         
        xDragged = me.getX();
        yDragged = me.getY();
        System.out.println("screen(X,Y) = " + xDragged + "," + yDragged);
        g = panel.getGraphics();
        
        int x, y;
        int w, h;
        
        if(xClicked > xDragged){
            x = xDragged;
            w = xClicked - xDragged;
        }else{
            x = xClicked;
            w = xDragged - xClicked;
        }
        
        if(yClicked > yDragged){
            y = yDragged;
            h = yClicked - yDragged;
        }else{
            y = yClicked;
            h = yDragged - yClicked;
        }
        
        switch(state) {
        case 'p':
            panel.addPoint(xDragged, yDragged);
            g.drawLine(xDragged, yDragged, xDragged, yDragged);
            break;
        case 'l':
            g.drawLine(xClicked, yClicked, xDragged, yDragged);
            panel.repaint();
            break;
        case 'r':

            
            g.drawRect(x, y, w, h);
            panel.repaint();
            break;
        case 'c':
            g.drawOval(x, y, w, h);
            panel.repaint();
            break;
        }


       // panel.addPoint(screenX, screenY);
       // panel.repaint();
    
       }

    @Override
      public void mouseClicked(MouseEvent me) {
        
        xClicked = me.getX();
        yClicked = me.getY();
          

        
      }
    
    public void mouseReleased(MouseEvent me) {
     
        g = panel.getGraphics();
        
        int x, y;
        int w, h;
        
        if(xClicked > xDragged){
            x = xDragged;
            w = xClicked - xDragged;
        }else{
            x = xClicked;
            w = xDragged - xClicked;
        }
        
        if(yClicked > yDragged){
            y = yDragged;
            h = yClicked - yDragged;
        }else{
            y = yClicked;
            h = yDragged - yClicked;
        }
        
        switch(state) {
        case 'p':
            break;
        case 'l':
            g.drawLine(xClicked, yClicked, xDragged, yDragged);
            panel.addLine(xClicked, yClicked, xDragged, yDragged);
            panel.repaint();
            break;
        case 'r':

            
            g.drawRect(x, y, w, h);
            panel.addRectangle(x, y, h, w);
            panel.repaint();
            break;
        case 'c':
            g.drawOval(x, y, w, h);
            panel.addCircle(x, y, w, h);
            panel.repaint();
            break;
        }
    }


}

I’ve tried eliminating the use of the repaint method which is what is causing the problem but I can’t avoid not using it when positing the shapes. I tried setting focusable to false on the JButtons but that didn’t solve the problem.

>Solution :

The first line of your paintComponent() method should be:

super.paintComponent(g);

This allows Swing to do some initialization, including erasing the current area that is going to be drawn on.

Leave a ReplyCancel reply