Dies lässt sich mit Hilfe eines MouseListeners und
eines MouseMotionListeners realisieren.
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.