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 MouseEvent
s 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
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…
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);
}
}
}