Wie kann man eine Linie zeichnen, deren Endpunkt dem Mauscursor folgt?
Die Klasse wird von JPanel abgeleitet, einem Container, auf
den durch Überschreiben der Methode paintComponent(Graphics
g) gezeichnet werden kann. Zunächst werden vier
Instanzvariablen deklariert, die die x- und y-Positionen des
Startpunktes der Linie und der aktuellen Position der Maus
speichern.
Im Konstruktor wird die Klasse jeweils bei einem MouseListener1 und einem MouseMotionListener
angemeldet. Die Klasse implementiert die Listener selber. Die
Listener müssen die folgenden Methoden implementieren:
MouseListener:
- mouseClicked(MouseEvent e)
- mouseEntered(MouseEvent e)
- mouseExited(MouseEvent e)
- mousePressed(MouseEvent e)
- mouseReleased(MouseEvent e)
MouseMotionListener:
- mouseDragged(MouseEvent e)
- mouseMoved(MouseEvent e)
Prinzipiell sollten die Methoden-Bezeichner selbsterklärend sein.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
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 LinieZiehen2 extends JPanel implements MouseListener, MouseMotionListener {
private static final long serialVersionUID = 1L;
private int startX, startY, tempX, tempY;
private Image img = null;
private static final Color BGCOLOR = new Color(170, 100, 100);
private static final Color FGCOLOR = new Color(10, 200, 10);
public LinieZiehen2() {
this.setBackground(BGCOLOR);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaintMode();
g.drawImage(img, 0, 0, this);
g2.setColor(FGCOLOR);
g2.drawLine(startX, startY, tempX, tempY);
}
public void zeichne(){
if(img == null){
img = createImage(this.getWidth(), this.getHeight());
}
Graphics2D g2d = (Graphics2D)img.getGraphics();
this.paint(g2d);
g2d.dispose();
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new LinieZiehen2());
frame.setBackground(BGCOLOR);
frame.setSize(400, 300);
frame.setTitle("Eine gerade Linie 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) {
zeichne();
}
public void mouseDragged(MouseEvent e) {
tempX = e.getX();
tempY = e.getY();
this.repaint();
}
public void mouseMoved(MouseEvent e) {
}
}
In der Methode mousePressed(MouseEvent e) wird der
Startpunkt der Linie durch Initialisieren der Variablen festgelegt,
in mouseDragged(MouseEvent e) wird die aktuelle
Mausposition in die Variablen geladen, die den Endpunkt der Linie
bestimmen. So ist gewährleistet, dass die jeweils aktuelle
Mausposition das Ende der Linie angibt. repaint() bewirkt
schließlich ein Neuzeichnen der Oberfläche, sodass
verhindert wird, dass während der Mausbewegung eine Schar von
Linien gezeichnet wird.
Der Zeichenvorgang selber findet in
der Methode paintComponent(Graphics g) statt. Hier wird das
als Parameter übergebene Graphics-Objekt zunächst in ein
(mächtigeres) Graphics2D-Objekt gecastet. Nach Setzen des
Paint-Modes wird schließlich mit der Methode drawLine(int
startX, int startY, int endX, int endY) die Linie gezeichnet.
Die Methode erwartet vier Parameter: jeweils einen x- und y-Wert
für den Start- und Endpunkt.
Möchte man, dass bereits gezeichnete Linien beim Erzeugen einer
neuen Linie erhalten bleiben, so muss nach dem Zeichnen einer Linie
der Zustand des Panels zwischengespeichert werden. Hierzu erzeugt
man eine Methode zeichne(), in der ein sog. Offscreen-Image
erzeugt wird, dessen Grafikkontext an die paint()-Methode
des JPanels übergeben wird. Diese Methode wird jedes Mal beim
Beenden eines Zeichenvorgangs, also in mouseReleased(MouseEvent
e), aufgerufen. Das Offscreen-Image muss schließlich
jedes Mal in paintComponent(Graphics g) vor dem Ziehen der
Linie gezeichnet werden.
Möchte man gleichzeitig die
Hintergrundfarbe steuern ist ein kleiner Trick notwendig, da dieser
nicht einfach mit fillRect() in paintComponent(Graphics
g) erzeugt werden kann: Man weist sowohl dem JPanel, als auch
dem Hauptfenster die gleiche Hintergrundfarbe zu.
1) Die Funktionsweise eines Listeners kann hier etwas genauer nachgelesen werden.
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.