Auf einem JPanel gezeichnete Linie auswählen

propra

Aktives Mitglied
Hallo zusammen,

wie kann ich eine, auf einem JPanel, gezeichnete Linie auswählen bzw. testen, ob sie angeklickt wurde.
Bei anderen Symbolen, wie einem Kreis oder Rechteck, kann man ja ein Objekt vom Typ Shape "drüber legen" und dann mit der Methode
Code:
contains()
prüfen, ob die Koordinaten innerhalb der Form sind.
In der API für Line2D steht allerdings, dass die Methode hier immer false zurück liefert, weil eine Linie keine Area besitzt.
Kann ich der Linie eine Area hinzufügen? Was könnte man sonst noch machen, damit eine Linie anklickbar/auswählbar ist.
Bin für jeden Tipp dankbar.

Viele Grüße
propra
 
Du kannst z.B abfragen ob ptLineDist(double px, double py) unter einem gewissen Wert liegt (Entfernung von Punkt zur Linie) oder mithilfe von intersects(double x, double y, double w, double h) quasi überprüfen, ob die Linie ein Rechteck von 1 Pixel rund um den geklickten Punkt kreuzt.
 
Guckst Du hier: How to select a line 🙂.

Gruß,
André

Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

public class LineSelecting {

    private final JPanel panel;
    // Width and height of rectangular region around mouse
    // pointer to use for hit detection on lines
    private static final int HIT_BOX_SIZE = 2;
    private Shape[] lines = new Shape[]{
        new Line2D.Double(100, 100, 200, 200),
        new Line2D.Double(100, 150, 200, 250)};
    private int xHit, yHit;

    public LineSelecting() {
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);
        panel = new JPanel() {

            @Override
            protected void paintComponent(final Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                Shape selectedLine = getClickedLine(xHit, yHit);
                for (final Shape shape : lines) {
                    if (shape == selectedLine) {
                        g2.setColor(Color.RED);
                    } else {
                        g2.setColor(Color.BLACK);
                    }
                    g2.draw(shape);
                }
            }
        };
        panel.setFocusable(true);
        frame.add(panel);
        frame.setVisible(true);
        panel.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseReleased(final MouseEvent e) {
                xHit = e.getX();
                yHit = e.getY();
                panel.repaint();
            }
        });
    }

    /**
     * Returns the first line in the collection of lines that
     * is close enough to where the user clicked, or null if
     * no such line exists
     *
     */
    public Shape getClickedLine(final int x, final int y) {
        int boxX = x - HIT_BOX_SIZE / 2;
        int boxY = y - HIT_BOX_SIZE / 2;
        int width = HIT_BOX_SIZE;
        int height = HIT_BOX_SIZE;
        for (Shape shape : lines) {
            if (shape.intersects(boxX, boxY, width, height)) {
                return shape;
            }
        }
        return null;
    }

    public static void main(final String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                LineSelecting test = new LineSelecting();
            }
        });
    }
}
 
Zuletzt bearbeitet:
Hallo zusammen,

ich danke Euch für die Tipps.
Habe es mit intersects() und ptLineDist() ausprobiert. Hat beides funktioniert.
Ich glaube die Lösung mit ptLineDist() ist die für mich bessere, weshalb ich mich hierfür entschieden habe.
 

Neue Themen


Zurück
Oben