import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
public class Zeichenbrett extends JComponent {
// Die zur Verfügung stehenden Werkzeuge
public static final int TOOL_PIXEL = 0;
public static final int TOOL_RECTANGLE = 1;
public static final int TOOL_CIRCLE = 2;
public static final int TOOL_STAMP = 3;
public static final int TOOL_FILLRECT = 4;
public static final int TOOL_FILLOVAL = 5;
// Das aktuell verwendete Werkzeug
private int usedTool;
// Dieses Bild wird gezeichnet, wenn das Werkzeug "Stempel" verwendet wird.
private Image usedStamp;
// Koordinaten der MousePressed-Events
private int pressedX = 0;
private int pressedY = 0;
// Koordinaten der MouseReleased-Events
private int releasedX = 0;
private int releasedY = 0;
// Koordinaten der MouseDragged-Events
private int draggedX = 0;
private int draggedY = 0;
// Aus den Mausbewegungen errechnete Breite und Höhe
private int width = 0;
private int height = 0;
// Breite des bemalbaren Bereichs
protected static final int IMAGE_WIDTH = 600;
// Höhe des bemalbaren Bereichs
protected static final int IMAGE_HEIGHT = 400;
// Auf dieses Bild wird gezeichnet
private BufferedImage myImageBuffer;
// Referenz auf die Zeichenfläche des Bildes.
private Graphics2D myGraphicBuffer;
// temporäres Bild für Animation
private BufferedImage tempImageBuffer;
// temporäre Zeichenfläche für Animation
private Graphics2D tempGraphicBuffer;
/**
* Initialisierung.
* @throws IOException
*/
public Zeichenbrett() throws IOException {
// Hintzergrundfarbe setzen
setBackground(Color.white);
// Vordergrundfarbe (Zeichenfarbe) setzen
setForeground(Color.red);
// Grösse der Zeichenfläche setzen
setPreferredSize(new Dimension(IMAGE_WIDTH, IMAGE_HEIGHT));
// Default-Stempel
usedStamp = ImageIO.read(new File("images/smiley-channel.gif"));
// Default-Werkzeug
usedTool = TOOL_PIXEL;
// Die Bild-Buffer erzeugen
tempImageBuffer = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
this.loescheTempZeichenflaeche();
myImageBuffer = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
this.loescheZeichenflaeche();
/*
* Beim Drücken der Maustaste wird eine Referenz auf die
* Zeichenfläche des Pufferbildes erzeugt. Anschl. wird je nach gewähltem
* Werkzeug zum ersten Mal auf den Puffer gezeichnet.
* Beim Lösen der Taste wird die Zeichenflächenreferenz wieder freigegeben.
*/
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent mpe) {
// Referenz auf die temporäre Zeichenfläche erzeugen
tempGraphicBuffer = (Graphics2D) tempImageBuffer.getGraphics();
// Referenz auf die Zeichenfläche erzeugen
myGraphicBuffer = (Graphics2D) myImageBuffer.getGraphics();
/*
* ACHTUNG!!! nicht ausserhalb der Grenzen des Pufferbildes zeichnen!
*/
pressedX = mpe.getX();
if (pressedX>=IMAGE_WIDTH) pressedX=IMAGE_WIDTH-1;
if (pressedX<0) pressedX=0;
pressedY = mpe.getY();
if (pressedY>=IMAGE_HEIGHT) pressedY=IMAGE_HEIGHT-1;
if (pressedY<0) pressedY=0;
switch (usedTool) {
case TOOL_PIXEL:
myImageBuffer.setRGB(pressedX, pressedY, getForeground().getRGB());
break;
case TOOL_RECTANGLE:
myGraphicBuffer.setColor(getForeground());
myGraphicBuffer.fillRect(pressedX-5, pressedY-5, 10, 10);
break;
case TOOL_CIRCLE:
myGraphicBuffer.setColor(getForeground());
myGraphicBuffer.fillOval(pressedX-5, pressedY-5, 10, 10);
break;
case TOOL_STAMP:
int w = usedStamp.getWidth(Zeichenbrett.this);
int h = usedStamp.getHeight(Zeichenbrett.this);
myGraphicBuffer.drawImage(usedStamp, pressedX-w/2, pressedY-h/2, Zeichenbrett.this);
break;
case TOOL_FILLRECT:
case TOOL_FILLOVAL:
break;
}
// Komponente neu zeichnen!!!!
repaint();
}
public void mouseReleased(MouseEvent mre) {
/*
* ACHTUNG!!! nicht ausserhalb der Grenzen des Pufferbildes zeichnen!
*/
releasedX = mre.getX();
if (releasedX>=IMAGE_WIDTH) releasedX=IMAGE_WIDTH-1; if (releasedX<0) releasedX=0;
releasedY = mre.getY();
if (releasedY>=IMAGE_HEIGHT) releasedY=IMAGE_HEIGHT-1; if (releasedY<0) releasedY=0;
int x = 0;
int y = 0;
if ( releasedX < pressedX ) {
x = releasedX;
width = pressedX - releasedX;
} else {
x = pressedX;
width = releasedX - pressedX;
}
if ( releasedY < pressedY ) {
y = releasedY;
height = pressedY - releasedY;
} else {
y = pressedY;
height = releasedY - pressedY;
}
loescheTempZeichenflaeche();
switch (usedTool) {
case TOOL_FILLRECT:
myGraphicBuffer.setColor(getForeground());
myGraphicBuffer.fillRect(x, y, width, height);
break;
case TOOL_FILLOVAL:
myGraphicBuffer.setColor(getForeground());
myGraphicBuffer.fillOval(x, y, width, height);
break;
}
// Komponente neu zeichnen!!!!
repaint();
// Referenzen auf die Zeichenflächen freigeben
if (myGraphicBuffer != null) {
myGraphicBuffer.dispose();
myGraphicBuffer = null;
}
if (tempGraphicBuffer != null) {
tempGraphicBuffer.dispose();
tempGraphicBuffer = null;
}
}
});
/*
* Zeichnet in Abhängigkeit zu dem verwendeten Werkzeug auf das Pufferbild.
*/
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent mde) {
/*
* ACHTUNG!!! nicht ausserhalb der Grenzen des Pufferbildes zeichnen!
*/
draggedX = mde.getX();
if (draggedX>=IMAGE_WIDTH) draggedX=IMAGE_WIDTH-1; if (draggedX<0) draggedX=0;
draggedY = mde.getY();
if (draggedY>=IMAGE_HEIGHT) draggedY=IMAGE_HEIGHT-1; if (draggedY<0) draggedY=0;
int x = 0;
int y = 0;
if ( draggedX < pressedX ) {
x = draggedX;
width = pressedX - draggedX;
} else {
x = pressedX;
width = draggedX - pressedX;
}
if ( draggedY < pressedY ) {
y = draggedY;
height = pressedY - draggedY;
} else {
y = pressedY;
height = draggedY - pressedY;
}
switch (usedTool) {
// einen Pixel manipulieren
case TOOL_PIXEL:
myImageBuffer.setRGB(draggedX, draggedY, getForeground().getRGB());
break;
// Rechteck der Grösse 10x10 um die Mausposition herum malen
case TOOL_RECTANGLE:
myGraphicBuffer.setColor(getForeground());
myGraphicBuffer.fillRect(draggedX-5, draggedY-5, 10, 10);
break;
// Kreis der Grösse 10x10 um die Mausposition herum malen
case TOOL_CIRCLE:
myGraphicBuffer.setColor(getForeground());
myGraphicBuffer.fillOval(draggedX-5, draggedY-5, 10, 10);
break;
// ein Bild (*.png) malen
case TOOL_STAMP:
int w = usedStamp.getWidth(Zeichenbrett.this);
int h = usedStamp.getHeight(Zeichenbrett.this);
myGraphicBuffer.drawImage(usedStamp, draggedX-w/2, draggedY-h/2, Zeichenbrett.this);
break;
case TOOL_FILLRECT:
loescheTempZeichenflaeche();
tempGraphicBuffer.setColor(getForeground());
tempGraphicBuffer.fillRect(x, y, width, height);
break;
case TOOL_FILLOVAL:
loescheTempZeichenflaeche();
tempGraphicBuffer.setColor(getForeground());
tempGraphicBuffer.fillOval(x, y, width, height);
break;
}
// Komponente neu zeichnen!!!!
repaint();
}
});
}
/**
* Erzeugt neuen Bildbuffer
*/
public void loescheZeichenflaeche() {
myImageBuffer = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
}
/**
* übermalt den temporären Bildbuffer
*/
public void loescheTempZeichenflaeche() {
tempGraphicBuffer = (Graphics2D) tempImageBuffer.getGraphics();
tempGraphicBuffer.setColor(getBackground());
tempGraphicBuffer.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
}
/**
* Überschreibt die geerbte Methode und zeichnet lediglich das Pufferbild
* und das temporäre Bild auf den Bildschirm.
*/
public void paintComponent(Graphics g) {
if (tempImageBuffer!=null)
g.drawImage(tempImageBuffer, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, this);
g.drawImage(myImageBuffer, 0, 0, this);
}
public int getVerwendetesWerkzeug() {
return usedTool;
}
public void setVerwendetesWerkzeug(int verwendetesWerkzeug) {
switch (verwendetesWerkzeug) {
case TOOL_PIXEL:
case TOOL_RECTANGLE:
case TOOL_CIRCLE:
case TOOL_STAMP:
case TOOL_FILLRECT:
case TOOL_FILLOVAL:
usedTool = verwendetesWerkzeug;
}
}
public void setStempelBild(Image img) {
usedStamp = img;
}
public BufferedImage getImage() {
return myImageBuffer;
}
}