How to Draw a Line on a Bufferedimage in Java

The most practical method is at the end of the response after the Update

What happens is that you save all the coordinates in the list, and each time you finish and start a new line, paintComponent() redraws the screen using all the stored coordinates, including the final coordinate of a line and the initial coordinate of another, since he does not know how to differentiate it.

An interesting way to solve this is to insert "negative coordinates", so that you can check when a line has finished and when another line has started.

To make it easier to work with coordinates, we recommend that you work with the Point , so there is no need to create 2 lists to store each coordinate axis.

Create a variable in your main class that represents a list of coordinates:

          private ArrayList<Point> points = new ArrayList<>();                  

it is where we store the coordinates, including the "null".

In the mouseDragged() ", add each coordinate where the mouse drags within the component area to the list, and then forces the redraw. Changing in your code, it looks like this:

          draft.addMouseMotionListener(new MouseMotionAdapter() {      @Override     public void mouseDragged(MouseEvent e) {         setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));          points.add(e.getPoint());         draft.repaint();     }  });                  

In the mouseReleased() ", add the final coordinate and the" negative "coordinate to the list. This point with negative coordinates is what will serve as a reference to identify that a line has ended.

          draft.addMouseListener(new MouseAdapter() {     @Override     public void mouseReleased(MouseEvent e) {         //adiciona uma coordenada "nula" para ignorarmos         //no paintComponent         points.add(e.getPoint());         points.add(new Point(-1, -1));         setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));     } });                  

Now, in paintComponent() , we need to control how lines are drawn. The form I used was similar to yours, taking a point and its successor to create each segment of the lines. The "cat leap" is to check if the next coordinate of the current iteration is "negative", if it is, skip 2 iterations, since we do not want to connect the end of a line with the beginning of the other:

          @Override protected void paintComponent(Graphics g) {     // TODO Auto-generated method stub     super.paintComponent(g);      int i = 0;     while (i < points.size() - 1) {         Point currentPoint = points.get(i);         Point nextPoint = points.get(i + 1);          if (nextPoint.x != -1 && nextPoint.y != -1) {             Graphics2D g1 = (Graphics2D) g;             RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,                     RenderingHints.VALUE_ANTIALIAS_ON);             g1.setRenderingHints(rh);             g1.drawLine(currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y);             i++;          } else {             // quando as coordenadas do ponto seguinte forem (-1, -1),             // pulamos essa iteração para evitar que a linha anterior             // seja ligada a nova linha que está sendo desenhada             i += 2;         }     } }                  

In this way, the loop will jump between the end point of a line and the negative point, going straight to the starting point of the other line.

Your class with the changes will be much cleaner and simpler, see:

          import java.awt.BorderLayout; import java.awt.Cursor; import java.awt.EventQueue; 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.event.MouseMotionAdapter; import java.util.ArrayList;  import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder;  //Essa classe tem o objetivo de imitar o recurso de desenhar linhas do softwere paint, da Microsoft.  public class DrawingSketch extends JFrame {      private static final long serialVersionUID = 5661286812709693531L;     private JPanel contentPane;     private JPanel draft;      private ArrayList<Point> points = new ArrayList<>();      /**      * Launch the application.      */     public static void main(String[] args) {         EventQueue.invokeLater(new Runnable() {             public void run() {                 try {                     DrawingSketch frame = new DrawingSketch();                     frame.setVisible(true);                 } catch (Exception e) {                     e.printStackTrace();                 }             }         });     }      /**      * Create the frame.      */     public DrawingSketch() {         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         setBounds(100, 100, 900, 700);         setLocationRelativeTo(null);         contentPane = new JPanel();         contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));         contentPane.setLayout(new BorderLayout(0, 0));         setContentPane(contentPane);          draft = new Draft();         draft.addMouseMotionListener(new MouseMotionAdapter() {              @Override             public void mouseDragged(MouseEvent e) {                 setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));                  points.add(e.getPoint());                 draft.repaint();             }          });         draft.addMouseListener(new MouseAdapter() {             @Override             public void mouseReleased(MouseEvent e) {                 // adiciona uma coordenada nula para ignorarmos                 // no paintComponent                 points.add(e.getPoint());                 points.add(new Point(-1, -1));                 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));             }         });         contentPane.add(draft, BorderLayout.CENTER);         draft.setLayout(null);     }      public class Draft extends JPanel {          /**          *           */         private static final long serialVersionUID = 4886600019364448097L;          public Draft() {          }          @Override         protected void paintComponent(Graphics g) {             // TODO Auto-generated method stub             super.paintComponent(g);              int i = 0;             while (i < points.size() - 1) {                 Point currentPoint = points.get(i);                 Point nextPoint = points.get(i + 1);                  if (nextPoint.x != -1 && nextPoint.y != -1) {                     Graphics2D g1 = (Graphics2D) g;                     RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,                             RenderingHints.VALUE_ANTIALIAS_ON);                     g1.setRenderingHints(rh);                     g1.drawLine(currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y);                     i++;                  } else {                     // quando as coordenadas do ponto seguinte forem (-1, -1),                     // pulamos essa iteração para evitar que a linha anterior                     // seja ligada a nova linha que está sendo desenhada                     i += 2;                 }             }         }     } }                  

Running:

Update

Thereisamucheasierandmorepracticalwayofdoingthis,withouthavingtostoreandredrawalistofpointsonthescreen.Theworkaroundistouse BufferedImage , which is nothing more an image representation of the drawing. Thus, paintComponent() work is much smaller than iterating through a list with many points.

I leave the code below with comments on the changes:

          import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; 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.event.MouseMotionAdapter; import java.awt.image.BufferedImage;  import javax.swing.JPanel;  public class Draft extends JPanel {      //usaremos para armazenar e desenhar novas imagens     private BufferedImage bfImage;     //usaremos para desenhar as linhas conforme movimentacao     //do mouse na tela     private Point oldPoint = null;     private Point newPoint = null;      private static final long serialVersionUID = 4886600019364448097L;      public Draft() {          //crio uma instancia de bufferedimage do mesmo tamanho do painel         bfImage = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_ARGB);          addMouseMotionListener(new MouseMotionAdapter() {              @Override             public void mouseDragged(MouseEvent e) {                 setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));                 //armazenamos o novo ponto arrastado                 //atualizamos a imagem na tela                 //invertemos os pontos, pois após tela desenhada                 //o ponto atual passa a ser antigo                 newPoint = e.getPoint();                 updateImage();                 oldPoint = newPoint;             }          });         addMouseListener(new MouseAdapter() {             @Override             public void mouseReleased(MouseEvent e) {                 //ao liberar o mouse, armazenamos o ponto atual para finalizar                 //o desenho da atual linha e "limpamos" as duas referencias de pontos                                    newPoint = e.getPoint();                 updateImage();                 newPoint = null;                 oldPoint = null;                 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));             }              @Override             public void mousePressed(MouseEvent e) {                 //ao pressionar o mouse, verificamos se o ponto antigo existe                 //pois ele é o ponto de partida para desenhar o primeiro segmento                 //da nova linha                 if (oldPoint == null) {                     oldPoint = e.getPoint();                 }             }          });     }      //sobrescrevi o método getSize para que o tamanho do painel possa     //ser informado corretamente ao bufferedImage     @Override     public Dimension getSize() {         return new Dimension(500, 350);     }      private void updateImage() {         //se o ponto atual não for nulo, criamos um grafico no buffer e desenhamos o         //segmento da linha atual, forçando o redesenho da tela com repaint()         if (newPoint != null) {              Graphics2D g2 = bfImage.createGraphics();             g2.setColor(Color.BLACK);             g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);             g2.drawLine(oldPoint.x, oldPoint.y, newPoint.x, newPoint.y);             g2.dispose();             repaint();         }     }      @Override     protected void paintComponent(Graphics g) {         super.paintComponent(g);         //apenas passamos o buffer para o paintcomponent desenhar         //o que está nele.         g.drawImage(bfImage, 0, 0, null);     } }                  

And to use, just add an instance to your screen:

          seuFrame.add(new Draft());                  

With these changes, the possibilities increase, including saving an image as a file, recovering a saved drawing, among others that msPaint already does. :)

How to Draw a Line on a Bufferedimage in Java

Source: https://itqna.net/questions/39596/how-draw-lines-following-mouse-movement

0 Response to "How to Draw a Line on a Bufferedimage in Java"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel