import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.Observable;
import java.util.Observer;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String... args) {
SwingUtilities.invokeLater(Test::new);
}
public Test() {
JFrame frame = new JFrame("MyRectangles");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setSize(800, 600);
MyRectangleModel model = new MyRectangleModel();
JPanel mainPanel = new JPanel(new GridLayout(1, 2));
MyEditingView editingView = new MyEditingView(model);
editingView.setBorder(BorderFactory.createLineBorder(Color.BLACK));
mainPanel.add(editingView);
MyBlackWhiteView blackWhiteView = new MyBlackWhiteView(model);
blackWhiteView.setBorder(BorderFactory.createLineBorder(Color.BLACK));
mainPanel.add(blackWhiteView);
frame.add(mainPanel);
frame.setVisible(true);
}
}
final class MyEditingView extends JComponent implements Observer {
private static final long serialVersionUID = 125470717104438986L;
private static final int RECTANGLE_WIDTH = 50;
private static final int RECTANGLE_HEIGHT = 30;
private final MyRectangleModel model;
public MyEditingView(MyRectangleModel model) {
this.model = model;
this.model.addObserver(this);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (SwingUtilities.isLeftMouseButton(e)) {
MyRectangle rectangle = new MyRectangle(e.getX() - RECTANGLE_WIDTH / 2, e.getY() - RECTANGLE_HEIGHT / 2,
RECTANGLE_WIDTH, RECTANGLE_HEIGHT,
new Color((float) Math.random(), (float) Math.random(), (float) Math.random(), (float) Math.random()));
model.add(rectangle);
} else if (SwingUtilities.isRightMouseButton(e)) {
MyRectangle rectangle = model.getRectangleAt(e.getX(), e.getY());
if (rectangle != null) {
model.remove(rectangle);
}
}
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Drawable rectangle : model.getRectangles()) {
rectangle.draw(g);
}
}
@Override
public void update(Observable o, Object arg) {
repaint();
}
}
final class MyBlackWhiteView extends JComponent implements Observer {
private static final long serialVersionUID = 4962950651952911221L;
private final MyRectangleModel model;
public MyBlackWhiteView(MyRectangleModel model) {
this.model = model;
this.model.addObserver(this);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (MyRectangle rectangle : model.getRectangles()) {
BlackAndWhiteAdapter.adapt(rectangle).draw(g);
}
}
@Override
public void update(Observable o, Object arg) {
repaint();
}
}
interface Drawable {
void draw(Graphics g);
}
final class MyRectangleModel extends Observable {
private final Collection<MyRectangle> rectangles;
public MyRectangleModel() {
this.rectangles = new ArrayList<>();
}
public void add(MyRectangle rectangle) {
rectangles.add(rectangle);
setChanged();
notifyObservers(rectangle);
}
public void remove(MyRectangle rectangle) {
rectangles.remove(rectangle);
setChanged();
notifyObservers(rectangle);
}
public Collection<MyRectangle> getRectangles() {
return new ArrayList<>(rectangles);
}
public MyRectangle getRectangleAt(int x, int y) {
for (MyRectangle rectangle : rectangles) {
if (rectangle.contains(x, y)) {
return rectangle;
}
}
return null;
}
}
final class MyRectangle implements Drawable {
private final int x, y;
private final int width, height;
private final Color color;
public MyRectangle(int x, int y, int width, int height, Color color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Color getColor() {
return color;
}
public boolean contains(int x, int y) {
return this.x <= x && x <= this.x + this.width && this.y <= y && y <= this.y + this.height;
}
@Override
public void draw(Graphics g) {
Color old = g.getColor();
g.setColor(color);
g.fillRect(x, y, width, height);
g.setColor(old);
}
@Override
public int hashCode() {
return Objects.hash(x, y, width, height, color);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
MyRectangle other = (MyRectangle) obj;
if (!Objects.equals(color, other.color)) {
return false;
}
if (height != other.height) {
return false;
}
if (width != other.width) {
return false;
}
if (x != other.x) {
return false;
}
if (y != other.y) {
return false;
}
return true;
}
@Override
public String toString() {
return "MyRectangle [x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + ", color=" + color + "]";
}
}
final class BlackAndWhiteAdapter {
private BlackAndWhiteAdapter() {
}
public static Drawable adapt(MyRectangle rectangle) {
return new Drawable() {
@Override
public void draw(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(rectangle.getX(), rectangle.getY(), rectangle.getWidth(), rectangle.getHeight());
}
};
/*
* Könnte auch so aussehen mit Lambdaexpressions:
* return e -> {
* g.setColor(Color.BLACK);
* g.fillRect(rectangle.getX(), rectangle.getY(), rectangle.getWidth(), rectangle.getHeight());
* };
*/
}
}