0
votes

I have a java application that i have been coding, it is an application that can allow me to draw shapes like a rectangle. My application can draw shapes but I cannot save them because when i try to draw a new shape and I click somewhere else the previously drawn shape disappears and is replaced by a new one. I tried array list to save my shapes but it does not work.

here is my code:

    public class Toile extends JPanel {

    Vector<Forme> forme = new Vector<Forme>();
    private Color couleur;
    private int x;
    private int y;
    private int x2;
    private int y2;
    private Oval oval;
    private Rectangl rect;


    public Toile(){
    initComponents();
    }

    public void initComponents(){
   addMouseListener(new java.awt.event.MouseAdapter() { 
   public void mousePressed(java.awt.event.MouseEvent evt) { 
    formMousePressed(evt); } 
     public void mouseReleased(java.awt.event.MouseEvent evt) { 
    formMouseReleased(evt); } }); 
   addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { 
      public void mouseDragged(java.awt.event.MouseEvent evt) { 
    formMouseDragged(evt); } });
    }
    public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    g.setColor(couleur);
    drawfillRect(g, x, y, x2, y2);
    }


    public void setStartPoint(int x, int y) {
    this.x = x;
    this.y = y;
    }

    public void setEndPoint(int x, int y) {
    x2 = (x);
    y2 = (y);
    }

    public void drawfillRect(Graphics g, int x, int y, int x2, int y2) {
        int px = Math.min(x,x2);
        int py = Math.min(y,y2);
        int pw=Math.abs(x-x2);
        int ph=Math.abs(y-y2);
        //g.fillRect(px, py, pw, ph);
        Rectangl rect = new Rectangl(px,y,x2,py,pw,ph,couleur,true);
        rect.dessinerfrect(g);
        forme.add(rect);
      }
 }

       private void formMousePressed(java.awt.event.MouseEvent evt) { 
       setStartPoint(evt.getX(), evt.getY());
      repaint(); 
       }

      private void formMouseReleased(java.awt.event.MouseEvent evt) {{
      setEndPoint(evt.getX(), evt.getY());
      repaint(); 
      //dessiner(this.getGraphics());
      }
      }

      private void formMouseDragged(java.awt.event.MouseEvent evt){{
      setEndPoint(evt.getX(), evt.getY());
      repaint(); 
      //dessiner(this.getGraphics()); 
      }
      }

As you can see this is the class that does the drawings, the rectangle that will be drawn is an object from a class that I created and this class is a subclass of a super class Forme. As I said previously, the application can draw shapes but the shapes that are drawn are not saved. Also I removed the getters and setters from my post because I wanted to keep only what was essential and I wanted to make my post clearer.

Here is the class Rectangl:

  public class Rectangl extends Forme {
  private int largeur;
  private int hauteur;
  private Rectangle rectangle;
  public Rectangl(int x1,int y1, int x2 ,int y2,int largeur,int hauteur,Color couleur,Boolean plein){
  super(x1,y1,x2,y2,couleur,plein);
  this.largeur = largeur;
  this.hauteur = hauteur;
}

  public void dessinerrect(Graphics g){
  g.setColor(couleur); 
  g.drawRect((int)point1.getX(), (int)point2.getY(), largeur, hauteur);
 }
  public void dessinerfrect(Graphics g){
  g.setColor(couleur); 
  g.fillRect((int)point1.getX(), (int)point2.getY(), largeur, hauteur);
 }

   }
2
Painting is destructive, you are expected to, when ever paintComponent is called, to repaint the entire state from scratch. This means you need some way to store the shapes you want to be painted, probably in some kind of List - MadProgrammer

2 Answers

0
votes

You'll need to implement a display list. This is a data structure that represents all the items currently in the drawing. The component painter just traverses the list and draws each item (usually after erasing the screen so that deleted objects don't appear in the new drawing). It also optionally draws the "rubberband cursor" if the mouse has been pressed and not yet released. The mouse actions (usually releasing the mouse button just modify status variables including display list (add, select, delete, etc.) and then repaint the drawing surface so the component painter is called.

A Java ArrayList is a reasonable way to implement a simple display list. The items themselves are a classical use of interfaces and/or inheritance:

interface DisplayListItem {
  void draw(Graphics g);
}

abstract class AbstractRectangle implements DisplayListItem {
  protected int x, y, w, h;
  protected Color color;
  Rectangle(int x, int y, int w, int h, Color color) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.color = color;
  }
}

class Rectangle extends AbstractRectangle {
  Rectangle(int x, int y, int w, int h, Color color) { 
    super(x, y, w, h, color);
  }
  @Override
  void draw(Graphic g) {
    g.setColor(color);
    g.drawRect(x, y, w, h);
  }
}
class FilledRectangle extends AbstractRectangle {
  FilledRectangle(int x, int y, int w, int h, Color color) { 
    super(x, y, w, h, color);
  }
  @Override
  void draw(Graphic g) {
    g.setColor(color);
    g.fillRect(x, y, w, h);
  }
}

private List<DisplayListItem> displayList = new ArrayList<>();
private int xPress, yPress, xDrag, yDrag;
private boolean mousePressed = false;

@Override
public void paintComponent(Graphics g) { 
  super.paintComponent(g);
  for (DisplayListItem item : displayList) {
    item.draw(g);
  }
  if (mousePressed) {
   // Draw the click-and-drag cursor.
   g.setColor(Color.RED);
   g.drawRect(xPress, yPress, xDrag - xPress, yDrag - yPress);
  }
}

private void formMousePressed(MouseEvent evt) { 
  xPress = evt.getX();
  yPress = evt.getY();
  mousePressed = true;
}

private void formMouseDragged(MouseEvent evt) {
  if (!mousePressed) return;
  xDrag = evt.getX();
  yDrag = evt.getY();
  repaint();
} 

private void formMouseReleased(MouseEvent evt) {
  if (!mousePressed) return;
  xDrag = evt.getX();
  yDrag = evt.getY();
  // Adding a rectangle to the display list makes it permanent.
  displayList.add(new Rectangle(xPress, yPress, xDrag - xPress, yDrag - yPress));
  mousePressed = false;
  repaint();
}

Caveat: This is uncompiled, untested code. Use at your own risk.

0
votes

Swing has the useful Shape interface which has been implemented into several concrete classes that could serve your purpose well.

There are several different Shapes (Ellipse2D, Rectangle2D, RoundRectangle2D) are stored in an ArrayList of Shape objects, and then these are drawn within the JPanel's paintComponent method after first casting the Graphics object into a Graphics2D.