import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
// Ein Interface für alle Objekte, die gezeichnet werden können.
interface Paintable
{
void paintObject(Graphics2D g);
}
// Ein Interface für alle Objekte, die gezeichnet und angeklickt
// werden können: Bietet eine Methode, die überprüft, ob das
// Objekt durch einen Mausklick an einer bestimmten Stelle
// getroffen wurde.
interface Clickable extends Paintable
{
boolean isHitBy(int mx, int my);
}
// Ein Smiley, der gezeichnet und angeklickt werden kann.
class Smiley implements Clickable
{
private int x;
private int y;
public Smiley(int x, int y)
{
this.x = x;
this.y = y;
}
// Implementierung des Paintable-Interfaces
@Override
public void paintObject(Graphics2D g)
{
int x0 = x - 25;
int y0 = y - 25;
g.setColor(Color.YELLOW);
g.fillOval(x0, y0, 50, 50);
g.setColor(Color.BLACK);
g.fillOval(x0 + 15, y0 + 15, 8, 8);
g.fillOval(x0 + 30, y0 + 15, 8, 8);
g.draw(new Arc2D.Double(x0 + 10, y0 + 10, 30, 30, 190, 160, Arc2D.OPEN));
}
// Implementierung des Clickable-Interfaces
@Override
public boolean isHitBy(int mx, int my)
{
// Gib zurück, ob dieser Smiley (beschrieben durch
// einen Kreis) den angeklickten Punkt enthält
Shape smileyShape = new Ellipse2D.Double(x - 25, y - 25, 50, 50);
return smileyShape.contains(mx, my);
}
@Override
public String toString()
{
return "Smiley an Position (" + x + "," + y + ")";
}
}
// Ein JPanel, bei dem die paintComponent-Methode überschrieben ist, und
// das eine Liste von Objekten speichert, die gezeichnet und angeklickt
// werden können
class PaintPanel extends JPanel
{
// Die Liste der Clickablen Objekte, und Methoden um solche
// Objekte hinzuzufügen oder zu entfernen.
private List<Clickable> clickables = new ArrayList<Clickable>();
public void addClickable(Clickable clickable)
{
clickables.add(clickable);
repaint();
}
public void removeClickable(Clickable clickable)
{
clickables.remove(clickable);
repaint();
}
// Gibt eine unveränderliche Liste aller anklickbaren
// Objekte zurück
public List<Clickable> getClickables()
{
return Collections.unmodifiableList(clickables);
}
// Die paintComponent-Methode wird immer aufgerufen,
// wenn das Panel neu gezeichnet wird
@Override
protected void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
// Schalte Antialiasing ein (damit wirkt die
// Zeichnung glatter)
Graphics2D g = (Graphics2D) graphics;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// Zeichne alle Objekte
for (Paintable paintable : clickables)
{
paintable.paintObject(g);
}
}
}
// Die Hauptklasse für das GUI: Ein Panel, das die weiteren
// GUI-Komponenten enthält
class MainPanel extends JPanel
{
public MainPanel()
{
setLayout(new BorderLayout());
// PaintPanel erstellen und in die Mitte legen
final PaintPanel paintPanel = new PaintPanel();
paintPanel.setPreferredSize(new Dimension(400, 400));
add(paintPanel, BorderLayout.CENTER);
// Erstelle einen MouseListener, der aufgerufen wird,
// wenn man auf das PaintPanel klickt:
MouseListener mouseListener = new PaintMouseListener(paintPanel);
paintPanel.addMouseListener(mouseListener);
}
}
// Ein MouseListener, der bei einem Mausklick alle
// anklickbaren Objekte eines PaintPanels überprüft,
// ob sie durch den Mausklick getroffen wurden.
class PaintMouseListener implements MouseListener
{
private PaintPanel paintPanel;
public PaintMouseListener(PaintPanel paintPanel)
{
this.paintPanel = paintPanel;
}
@Override
public void mouseClicked(MouseEvent e)
{
System.out.println("Maus wurde geklickt an Position "+e.getPoint());
if (e.getButton() == MouseEvent.BUTTON1)
{
Clickable clickable = new Smiley(e.getX(), e.getY());
System.out.println("Linke Maustaste - füge hinzu: " + clickable);
paintPanel.addClickable(clickable);
}
else if (e.getButton() == MouseEvent.BUTTON3)
{
List<Clickable> clickedObjects = new ArrayList<Clickable>();
for (Clickable clickable : paintPanel.getClickables())
{
if (clickable.isHitBy(e.getX(), e.getY()))
{
clickedObjects.add(clickable);
}
}
System.out.println("Rechte Maustaste - entferne: " + clickedObjects);
for (Clickable clickable : clickedObjects)
{
paintPanel.removeClickable(clickable);
}
}
}
@Override
public void mouseEntered(MouseEvent e)
{}
@Override
public void mouseExited(MouseEvent e)
{}
@Override
public void mousePressed(MouseEvent e)
{}
@Override
public void mouseReleased(MouseEvent e)
{}
}
// Die Hauptklasse mit der main-Methode.
public class SwingPaintAndClick
{
public static void main(String args[])
{
// Das Erzeugen des GUIs muss auf dem
// Event-Dispatch-Thread ausgeführt
// werden:
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
// Erzeugt ein Fenster, das ein MainPanel enthält,
// und macht das Fenster sichtbar
private static void createAndShowGUI()
{
// Fenster erstellen
JFrame frame = new JFrame("Paint and click");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Haupt-Panel erstellen und in das Fenster legen
MainPanel mainPanel = new MainPanel();
mainPanel.setPreferredSize(new Dimension(500, 500));
frame.getContentPane().add(mainPanel);
// Fenster zentrieren und anzeigen
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}