how to draw on an image added in the JLabel on java swing?

I want to draw lines that go from (0,0) of the image step of the JFrame to the middle of the image using g.drawline(x1,y1,x2,y2)
I tried many things but I couldn’t find the solution.
getX() and getY() are the coordinates relative to the frame, but I want the coordinates relative to the JLabel, to the JFrame.

I want when I resize my image that it remains as such, i.e. which keeps the (0,0) of the image

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class ImageExample {
    public static void main(String[] args) {
        // Créer une image
        BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);

        // Récupérer le Graphics de l'image pour dessiner
        Graphics2D g2d = image.createGraphics();
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0, 0, 400, 400);
        g2d.setColor(Color.WHITE);
        g2d.drawString("Cliquez pour afficher les coordonnées", 100, 200);
        g2d.dispose();

        // Créer un JLabel avec l'image
        JLabel imageLabel = new JLabel(new ImageIcon(image));

        // Ajouter un écouteur de clic sur l'image
        imageLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int x = e.getX();
                int y = e.getY();

                System.out.println("Coordonnées dans l'image : " + x + ", " + y);
            }
        });

        // Créer un JPanel pour contenir le JLabel
        JPanel panel = new JPanel();
        panel.add(imageLabel);

        // Créer un JFrame pour afficher le JPanel
        JFrame frame = new JFrame("Image Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}

>Solution :

MouseListener will convert the MouseEvent coordinates to the be relative to the component it is registered to. This means that when you register the MouseListener to the JLabel, all the coordinates for the MouseEvents will be relative to it (ie 0x0 will be the top left of the JLabel).

However, remember that you don’t control the position of the icon and the label may render the icon in a different location. So, when it "appears" to be 0x0, it may be offset

enter image description here
enter image description here

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {
        private BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);

        public TestPane() {
            // Récupérer le Graphics de l'image pour dessiner
            Graphics2D g2d = image.createGraphics();
            g2d.setColor(Color.BLACK);
            g2d.fillRect(0, 0, 400, 400);
            g2d.setColor(Color.WHITE);
            g2d.drawString("Cliquez pour afficher les coordonnées", 100, 200);
            g2d.dispose();

            // Créer un JLabel avec l'image
            JLabel imageLabel = new JLabel(new ImageIcon(image));

            // Ajouter un écouteur de clic sur l'image
            imageLabel.addMouseListener(new MouseAdapter() {

                private Point startPoint;

                @Override
                public void mouseClicked(MouseEvent e) {
                    Point point = e.getPoint();
                    Graphics2D g2d = image.createGraphics();
                    g2d.setColor(Color.GREEN);
                    FontMetrics fm = g2d.getFontMetrics();
                    g2d.drawString(point.x + "x" + point.y, point.x, point.y + fm.getAscent());
                    g2d.dispose();
                    
                    if (startPoint == null) {
                        startPoint = point;
                    } else {
                        g2d = image.createGraphics();
                        g2d.setColor(Color.RED);
                        g2d.draw(new Line2D.Double(startPoint, point));
                        g2d.dispose();
                        startPoint = null;
                    }
                    repaint();
                }
            });

            add(imageLabel);
        }

    }
}

A better approach…

Would be not to use a JLabel and take control of the rendering of the image, so you can control the position of the image – or at least have some way to actually determine the position of the image if you align within the component.

To this end, I’d just follow a basic custom painting route and paint the image directly to something like a JPanel, for example…

enter image description here

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new BetterPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class BetterPane extends JPanel {
        private BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);

        public BetterPane() {
            // Récupérer le Graphics de l'image pour dessiner
            Graphics2D g2d = image.createGraphics();
            g2d.setColor(Color.BLACK);
            g2d.fillRect(0, 0, 400, 400);
            g2d.setColor(Color.WHITE);
            g2d.drawString("Cliquez pour afficher les coordonnées", 100, 200);
            g2d.dispose();

            // Ajouter un écouteur de clic sur l'image
            addMouseListener(new MouseAdapter() {
                private Point startPoint;

                @Override
                public void mouseClicked(MouseEvent e) {
                    Point point = e.getPoint();
                    Graphics2D g2d = image.createGraphics();
                    g2d.setColor(Color.GREEN);
                    FontMetrics fm = g2d.getFontMetrics();
                    g2d.drawString(point.x + "x" + point.y, point.x, point.y + fm.getAscent());
                    g2d.dispose();
                    if (startPoint == null) {
                        startPoint = point;
                    } else {
                        g2d = image.createGraphics();
                        g2d.setColor(Color.RED);
                        g2d.draw(new Line2D.Double(startPoint, point));
                        g2d.dispose();
                        startPoint = null;
                    }
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(image, 0, 0, this);
        }

    }
}

Leave a Reply