Wie kann man eine Linie zeichnen, deren Endpunkt dem Mauscursor folgt, die jedoch nur waagerecht oder senkrecht verläuft?

Der Code baut auf 'Linie ziehen' auf. Ein KeyListener sorgt zusätzlich dafür, dass diese nur waagerecht oder senkrecht verläuft.

Der Trick besteht darin, ein KeyEvent abzufangen und dies beim Bewegen der Maus abzufragen. Hierzu wird zunächst eine Instanz eines KeyEvent gebildet. Ihr werden 5 Parameter übergeben:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class GeradeLinieZiehen extends JPanel implements MouseListener, MouseMotionListener, KeyListener {

    private static final long serialVersionUID = 1L;

    private int startX, startY, tempX, tempY;

    private KeyEvent kEvent = new KeyEvent(this, KeyEvent.KEY_PRESSED, 0, 0, 0, KeyEvent.CHAR_UNDEFINED);

    public GeradeLinieZiehen() {
        this.setFocusable(true);
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        this.addKeyListener(this);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaintMode();
        g2.drawLine(startX, startY, tempX, tempY);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.add(new GeradeLinieZiehen());
        frame.setSize(400, 300);
        frame.setTitle("Gerade Linien ziehen");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        startX = e.getX();
        startY = e.getY();
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mouseDragged(MouseEvent e) {
        tempX = e.getX();
        tempY = e.getY();
        if (kEvent != null && kEvent.getKeyCode() == KeyEvent.VK_SHIFT) {
            tempX = startX;
        }
        if (kEvent != null && kEvent.getKeyCode() == KeyEvent.VK_CONTROL) {
            tempY = startY;
        }
        this.repaint();
    }

    public void mouseMoved(MouseEvent e) {
    }

    public void keyPressed(KeyEvent e) {
        kEvent = e;
    }

    public void keyReleased(KeyEvent e) {
        kEvent = null;
    }

    public void keyTyped(KeyEvent e) {
    }
}

Im Konstruktor muss die Klasse beim KeyListener angemeldet und durch den Code

this.setFocusable(true);

explizit fokussierbar gesetzt werden, da dies ein JPanel nicht von alleine ist.
Der KeyListener macht nun zweierlei:

  1. In der Methode keyPressed(KeyEvent e) weist er der neu erzeugten Ereignis-Instanz sein KeyEvent zu
  2. In der Methode keyReleased(KeyEvent e) setzt er diese wieder auf null

In der MouseMotionListener-Methode mouseDragged(MouseEvent e) wird nun - vorausgesetzt die Ereignis-Instanz ist ungleich null - der Endpunkt der zu zeichnenden Linie abhängig von der gedrückten Linie auf den x- oder y-Wert der Startposition gesetzt.
Der Rest des Codes entspricht 'Linie_ziehen'.