Problem drawing lines when dragging with the mouse

I am working on a red applet that draws different shapes. I want to draw lines by dragging the mouse. The problem is that when the lines appear, they look like the one shown in the image below.

enter image description here

I have a class line built using one point (starting point) and it has a method called setDragPoint that takes the mouse drag points to draw lines, and also the drag and drop of the drawingImage makes too many flickers when drawing in drag and drop mode. Why is this happening?

 import java.applet.*; import java.awt.event.*; import java.awt.*; import java.util.*; public class PaintBrush extends Applet implements MouseListener, MouseMotionListener { Shape shape; Point startPoint; Point dragPoint; ArrayList<Shape> shapes; Choice shapeChoice; Choice colorChoice; Choice fillChoice; Image drawingImage; Graphics drawGraphics; String shapeString, colorString, fillString; boolean isDragMode; public void init() { shapes = new ArrayList<Shape>(); shapeChoice = new Choice(); shapeChoice.addItem("Line"); shapeChoice.addItem("Rectangle"); shapeChoice.addItem("RoundRect"); shapeChoice.addItem("Oval"); shapeChoice.addItem("FreeHand"); add(shapeChoice); colorChoice = new Choice(); colorChoice.addItem("Red"); colorChoice.addItem("Green"); colorChoice.addItem("Blue"); add(colorChoice); fillChoice = new Choice(); fillChoice.addItem("Filled"); fillChoice.addItem("Hollow"); add(fillChoice); shapeString = shapeChoice.getSelectedItem(); colorString = colorChoice.getSelectedItem(); fillString = fillChoice.getSelectedItem(); drawingImage = createImage(getSize().width, getSize().height); drawGraphics = drawingImage.getGraphics(); System.out.println("set up image"); drawGraphics.setColor(Color.black); drawGraphics.fillRect(0, 0, getSize().width, getSize().height); drawGraphics.setColor(Color.orange); drawGraphics.drawRect(0, 0, getSize().width - 1, getSize().height - 1); drawGraphics.drawRect(1, 1, getSize().width - 3, getSize().height - 3); startPoint = new Point(0, 0); dragPoint = new Point(0, 0); addMouseListener(this); addMouseMotionListener(this); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { System.out.println("Pressed"); startPoint.x = e.getX(); startPoint.y = e.getY(); repaint(); switch (shapeString) { case "Line": shape = new Line(startPoint.x, startPoint.y); //step 1 here i construct a new line using the start point (the point at which the mouse is pressed) break; case "FreeHand": shape = new FreeShape(); break; } } public void mouseReleased(MouseEvent e) { if (isDragMode) { shapes.add(shape); isDragMode = false; } repaint(); } public void mouseMoved(MouseEvent e) { } public void mouseDragged(MouseEvent e) { System.out.println("Dragged"); isDragMode = true; dragPoint.x = e.getX(); dragPoint.y = e.getY(); switch (shapeString) { case "Line": shape.setDragPoint(dragPoint.x, dragPoint.y); //here i set the drag points to the already created line at step 1 break; case "FreeHand": shape = new FreeShape(); break; } shape.drawWhileDragging(drawGraphics); // i call this method to draw while mouse is dragging repaint(); } public void paint(Graphics g) { update(g); } public void update(Graphics g) { // create an off-screen graphics drawing environment if none //existed // or if the user resized the applet drawing area to a different // size if (drawingImage == null) { System.out.println("Image is Null"); drawingImage = createImage(getSize().width,getSize().height); drawGraphics = drawingImage.getGraphics(); } // erase the previous image drawGraphics.setColor(Color.black); drawGraphics.fillRect(0,0,getSize().width,getSize().height); drawGraphics.setColor(Color.orange); drawGraphics.drawRect(0,0,getSize().width-1,getSize().height-1); drawGraphics.drawRect(1,1,getSize().width-3,getSize().height-3); for(Shape s:shapes) s.draw(drawGraphics); // paint the offscreen image to the applet viewing window g.drawImage(drawingImage,0,0,this); } } abstract class Shape { Color shapeColor; boolean filled; abstract void draw(Graphics g); void drawWhileDragging(Graphics g) { } void setDragPoint(int x, int y) { } } class Line extends Shape { private Point startPoint; private Point currentPoint; public Point getStartPoint() { return startPoint; } public Point getCurrentPoint() { return currentPoint; } public void setStartPoint(Point point) { this.startPoint = point; } public void setCurrentPoint(Point point) { this.currentPoint = point; } void drawWhileDragging(Graphics g) { g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); } public void draw(Graphics g) { g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); } Line() { startPoint = new Point(0, 0); currentPoint = new Point(0, 0); } Line(int x1, int y1) { this(); this.startPoint.x = x1; this.startPoint.y = y1; } void setDragPoint(int x, int y) { this.currentPoint.x = x; this.currentPoint.y = y; System.out.println("Current-X:" + currentPoint.x + " currentPoint-Y" + currentPoint.y); System.out.println("start-X:" + startPoint.x + " startPoint-Y" + startPoint.y); } } class FreeShape extends Shape { private ArrayList<Point> dragPoints = new ArrayList<Point>(); public ArrayList<Point> getDragPoints() { return dragPoints; } public void setDragPoints(Point point) { dragPoints.add(point); } public void draw(Graphics g) { } public FreeShape() { } } class Rectangle extends Shape { public void draw(Graphics g) { } } class Oval extends Shape { public void draw(Graphics g) { } } 
+4
source share
2 answers

I recently wrote a similar type of application. Here is a screenshot. It is not fully developed, as you can see. enter image description here

Now I am also having similar problems that you are currently facing. What do you need to do.

  • Double buffer for all drawing operations.
  • Do not clear the screen causing redrawing. Repaint actually fills the screen with the background color first, and this is the flicker that you see.

You can make a copy of the current screen canvas in Image . Image will be updated after each drawing process. Instead of clearing the screen by invoking Repaint , what you do is draw an Image on the canvas. This is like double buffering.

In code, you call Repaint every time the mouse is dragged. This is the cause of the flicker.


UPDATE

Three main questions I found in your updated code

  • In the drawWhileDragging method drawWhileDragging you do not change the color for drawing the context of the GUI. Thus, the line is drawn in black, and your background is also black. As a result, you see nothing.
  • In the same method, you pass a graphical context (for example, a link) to drawingImage . As a result, the line is actually drawn on the screen, not on the screen.
  • In mouseDragged you trigger a redraw after every drag and drop. As a result, nothing is drawn.

I ran my code on my machine and made the necessary changes. I leave only modified methods to save it.

Here is the updated mouseDragged method

  public void mouseDragged(MouseEvent e) { System.out.println("Dragged"); isDragMode = true; dragPoint.x = e.getX(); dragPoint.y = e.getY(); switch (shapeString) { case "Line": shape.setDragPoint(dragPoint.x, dragPoint.y); //here i set the drag points to the already created line at step 1 break; case "FreeHand": shape = new FreeShape(); break; } getGraphics().drawImage(drawingImage, 0,0,null); //Added this line shape.drawWhileDragging(getGraphics()); // i call this method to draw while mouse is dragging } 

Below is the updated drawWhileDragging method

  void drawWhileDragging(Graphics g) { g.setColor(Color.ORANGE); g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); g.setColor(Color.BLACK); } 

Well, I set the color to orange. You need to set the color according to the Choice menu.

You can implement a similar analogy for drawing other shapes.

+1
source

The problem you are facing is how you try to double-buffer. Instead of clearing the backup buffer when updating the line position, you just constantly draw it - a bit like a picture on a black board ....

Instead, you need to clear the graphic content and reapply the updates - surprisingly, this is part of what paint actually does, but you never call super.paint

You rarely have to redefine a top-level container, and you rarely have to redefine a paint method of a top-level container. Among other things, they do not fade there twice.

Use JPanel instead.

I updated your example excluding color. The color should actually be maintained in shape and applied when it is painted.

 public class BadPaint06 extends JApplet { public void init() { setLayout(new BorderLayout()); } @Override public void start() { add(new PaintPane()); } public class PaintPane extends JPanel implements MouseListener, MouseMotionListener { Shape shape; Point startPoint; Point dragPoint; ArrayList<Shape> shapes; Choice shapeChoice; Choice colorChoice; Choice fillChoice; Image drawingImage; Graphics drawGraphics; String shapeString, colorString, fillString; boolean isDragMode; public PaintPane() { shapes = new ArrayList<Shape>(); shapeChoice = new Choice(); shapeChoice.addItem("Line"); shapeChoice.addItem("Rectangle"); shapeChoice.addItem("RoundRect"); shapeChoice.addItem("Oval"); shapeChoice.addItem("FreeHand"); add(shapeChoice); colorChoice = new Choice(); colorChoice.addItem("Red"); colorChoice.addItem("Green"); colorChoice.addItem("Blue"); add(colorChoice); fillChoice = new Choice(); fillChoice.addItem("Filled"); fillChoice.addItem("Hollow"); add(fillChoice); shapeString = shapeChoice.getSelectedItem(); colorString = colorChoice.getSelectedItem(); fillString = fillChoice.getSelectedItem(); startPoint = new Point(0, 0); dragPoint = new Point(0, 0); addMouseListener(this); addMouseMotionListener(this); } @Override public void invalidate() { drawingImage = null; super.invalidate(); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { startPoint.x = e.getX(); startPoint.y = e.getY(); repaint(); switch (shapeString) { case "Line": shape = new Line(startPoint.x, startPoint.y); //step 1 here i construct a new line using the start point (the point at which the mouse is pressed) break; case "FreeHand": shape = new FreeShape(); break; } } public void mouseReleased(MouseEvent e) { if (isDragMode) { shapes.add(shape); isDragMode = false; } repaint(); } public void mouseMoved(MouseEvent e) { } public void mouseDragged(MouseEvent e) { System.out.println("Dragged"); isDragMode = true; dragPoint.x = e.getX(); dragPoint.y = e.getY(); switch (shapeString) { case "Line": shape.setDragPoint(dragPoint.x, dragPoint.y); //here i set the drag points to the already created line at step 1 break; case "FreeHand": shape = new FreeShape(); break; } repaint(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); System.out.println("In Paint"); if (drawingImage == null) { drawingImage = createImage(getSize().width, getSize().height); drawGraphics = drawingImage.getGraphics(); System.out.println("set up image"); drawGraphics.setColor(Color.black); drawGraphics.fillRect(0, 0, getSize().width, getSize().height); drawGraphics.setColor(Color.orange); drawGraphics.drawRect(0, 0, getSize().width - 1, getSize().height - 1); drawGraphics.drawRect(1, 1, getSize().width - 3, getSize().height - 3); drawGraphics.dispose(); } g.drawImage(drawingImage, 0, 0, this); for (Shape shape : shapes) { shape.draw(g); } if (shape != null) { shape.drawWhileDragging(g); // i call this method to draw while mouse is dragging } } } abstract class Shape { Color shapeColor; boolean filled; abstract void draw(Graphics g); void drawWhileDragging(Graphics g) { } void setDragPoint(int x, int y) { } } class Line extends Shape { private Point startPoint; private Point currentPoint; public Point getStartPoint() { return startPoint; } public Point getCurrentPoint() { return currentPoint; } public void setStartPoint(Point point) { this.startPoint = point; } public void setCurrentPoint(Point point) { this.currentPoint = point; } void drawWhileDragging(Graphics g) { if (currentPoint != null) { g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); } } public void draw(Graphics g) { if (currentPoint != null) { g.drawLine(startPoint.x, startPoint.y, currentPoint.x, currentPoint.y); } } Line() { startPoint = new Point(0, 0); // currentPoint = new Point(0, 0); } Line(int x1, int y1) { this(); this.startPoint.x = x1; this.startPoint.y = y1; } void setDragPoint(int x, int y) { currentPoint = new Point(x, y); // this.currentPoint.x = x; // this.currentPoint.y = y; System.out.println("Current-X:" + currentPoint.x + " currentPoint-Y" + currentPoint.y); System.out.println("start-X:" + startPoint.x + " startPoint-Y" + startPoint.y); } } class FreeShape extends Shape { private ArrayList<Point> dragPoints = new ArrayList<Point>(); public ArrayList<Point> getDragPoints() { return dragPoints; } public void setDragPoints(Point point) { dragPoints.add(point); } public void draw(Graphics g) { } public FreeShape() { } } class Rectangle extends Shape { public void draw(Graphics g) { } } class Oval extends Shape { public void draw(Graphics g) { } } } 
0
source

All Articles