Ist die GUI zu verändern ein Anti-Pattern?

Heute morgen hab ich ein Tool geschrieben, um einen Bereich eines Bilds zu verpixeln. Das ginge natürlich auch etwas umständlich mit Paint oder ganz einfach mit PS, wenn man PS hätte…

Zuerst wählt man die linke obere Ecke des Bereichs, dann die rechte untere Ecke des Bereichs, und dann kann man über einen Slider die Stärke der Verpixelung setzen. Das neue Bild wird immer automatisch gespeichert.

Das Ganze sieht dann so aus: http://www.framecompare.com/screenshotcomparison/7ZLWLNNX

Und damit auch gleich zum Problem, ich bin mit dem Design des JFrame s absolut unzufrieden. Wie macht man das richtig? Sollten sich die Komponenten eines JFrame s überhaupt ändern - oder ist das ein Anti-Pattern?

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class MyPixelateImg {
	public static void pixelate(String fn, int x1, int y1, int x2, int y2) throws IOException {
		pixelate(fn, x1, y1, x2, y2, 1);
	}

	public static void pixelate(String fn, int x1, int y1, int x2, int y2, float a) throws IOException {
		int w1 = x2 - x1;
		int h1 = y2 - y1;
		int w2 = Math.round(w1 * (1 / a / 10));
		int h2 = Math.round(h1 * (1 / a / 10));
		BufferedImage bi1 = ImageIO.read(new File(fn));
		BufferedImage bi2 = new BufferedImage(w2, h2, bi1.getType());
		Graphics2D g2d1 = bi2.createGraphics();
		g2d1.drawImage(bi1, 0, 0, w2, h2, x1, y1, x2, y2, null);
		g2d1.dispose();
		Graphics2D g2d2 = bi1.createGraphics();
		g2d2.drawImage(bi2, x1, y1, x2, y2, 0, 0, w2, h2, null);
		g2d2.dispose();
		int fe = fn.lastIndexOf('.');
		ImageIO.write(bi1, fn.substring(fe + 1), new File(fn.substring(0, fe) + "_2" + fn.substring(fe)));
	}

	public static void pixelate(BufferedImage i, int x1, int y1, int x2, int y2) {
		pixelate(i, x1, y1, x2, y2, 1);
	}

	public static void pixelate(BufferedImage i, int x1, int y1, int x2, int y2, float a) {
		int w1 = x2 - x1;
		int h1 = y2 - y1;
		int w2 = Math.round(w1 * (1 / a / 10));
		int h2 = Math.round(h1 * (1 / a / 10));
		BufferedImage bi1 = i;
		BufferedImage bi2 = new BufferedImage(w2, h2, bi1.getType());
		Graphics2D g2d1 = bi2.createGraphics();
		g2d1.drawImage(bi1, 0, 0, w2, h2, x1, y1, x2, y2, null);
		g2d1.dispose();
		Graphics2D g2d2 = bi1.createGraphics();
		g2d2.drawImage(bi2, x1, y1, x2, y2, 0, 0, w2, h2, null);
		g2d2.dispose();
	}

	public static BufferedImage deepCopy(BufferedImage img) {
		ColorModel cm = img.getColorModel();
		boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
		WritableRaster raster = img.copyData(null);
		return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
	}

	public static void main(String[] args) throws IOException {
		JFileChooser chooser = new JFileChooser();
		chooser.showOpenDialog(null);
		String fn = chooser.getSelectedFile().getAbsolutePath();
		BufferedImage[] imgs = new BufferedImage[2];
		imgs[0] = ImageIO.read(new File(fn));
		imgs[1] = deepCopy(imgs[0]);
		Canvas canvas = new Canvas() {
			private static final long serialVersionUID = 1L;

			@Override
			public void paint(Graphics g) {
				g.drawImage(imgs[1], 0, 0, null);
			}
		};
		canvas.setPreferredSize(new Dimension(imgs[1].getWidth(), imgs[1].getHeight()));
		JLabel label = new JLabel("Linke obere Ecke anklicken...");
		JSlider slider = new JSlider(1, 200, 100);
		JFrame frame = new JFrame();
		frame.setLayout(new BorderLayout());
		frame.add(canvas, BorderLayout.CENTER);
		frame.add(label, BorderLayout.SOUTH);
		frame.pack();
		frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		frame.setVisible(true);
		int[] ints = new int[5];
		canvas.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (ints[0] == 0) {
					ints[1] = e.getX();
					ints[2] = e.getY();
					ints[0]++;
					label.setText("Rechte untere Ecke anklicken...");
					label.repaint();
				} else if (ints[0] == 1) {
					ints[3] = e.getX();
					ints[4] = e.getY();
					ints[0]++;
					frame.remove(label);
					frame.add(slider, BorderLayout.SOUTH);
					frame.revalidate();
				}
			}
		});
		slider.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				JSlider js = (JSlider) e.getSource();
				if (!js.getValueIsAdjusting()) {
					float a = js.getValue() / 100f;
					imgs[1] = deepCopy(imgs[0]);
					pixelate(imgs[1], ints[1], ints[2], ints[3], ints[4], a);
					canvas.repaint();

					int fe = fn.lastIndexOf('.');
					try {
						ImageIO.write(imgs[1], fn.substring(fe + 1), new File(fn.substring(0, fe) + "_2" + fn.substring(fe)));
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}
			}
		});
	}
}