Argh, I'm having a frustrating problem getting my JScrollPane to work the way it is supposed to... I have a feeling some code would be helpful.
Code:
// Doodler.java
package com.puttysoftware.doodler;
import java.awt.Container;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JScrollPane;
public final class Doodler {
// Fields
private Doodle drawColorImage;
private JFrame drawFrame;
private JFrame colorFrame;
private JFrame previewFrame;
private JFrame toolFrame;
private Doodle canvas;
private JLabel canvasLabel;
private JLabel currentColor;
private JLabel previewLabel;
private Container drawContainer;
private Container colorContainer;
private Container previewContainer;
private Container imageContainer;
private Container toolContainer;
private JScrollPane scrollPane;
private JComboBox zoomSelector;
private int[] loc;
private int drawMode;
private int sizeX, sizeY;
private int zoomFactor;
private Color drawColor;
private MouseEventHandler mouseHandler;
private ColorChangeEventHandler ccHandler;
private WindowEventHandler windowHandler;
private ZoomEventHandler zoomHandler;
private Doodle preview;
private boolean isActive;
private static final int WINDOW_SPACING = 10;
private static final int MIN_IMAGE_SIZE = 2;
private static final int MAX_IMAGE_SIZE = 500;
private static final int SCROLL_PANE_SIZE = 512;
private static final int COLOR_SIZE = 64;
private static final String PROGRAM_NAME = "Doodler";
public static final int DRAW_MODE_VIEW = 0;
public static final int DRAW_MODE_EDIT = 1;
// Constructors
public Doodler(int imageSizeX, int imageSizeY) {
this.sizeX = imageSizeX;
this.sizeY = imageSizeY;
this.checkImageSize();
this.drawMode = Doodler.DRAW_MODE_EDIT;
this.createPreview();
this.commonInit();
}
public Doodler(Doodle image) {
this.sizeX = image.getWidth();
this.sizeY = image.getHeight();
this.checkImageSize();
this.drawMode = Doodler.DRAW_MODE_VIEW;
this.preview = image;
this.commonInit();
}
public Doodler(Doodle image, boolean edit) {
this.sizeX = image.getWidth();
this.sizeY = image.getHeight();
this.checkImageSize();
if (edit) {
this.drawMode = Doodler.DRAW_MODE_EDIT;
} else {
this.drawMode = Doodler.DRAW_MODE_VIEW;
}
this.preview = image;
this.commonInit();
}
// Methods
private void commonInit() {
this.zoomFactor = 1;
this.drawColor = Color.BLACK;
this.initDrawFrame();
this.initPreviewFrame();
this.initColorFrame();
this.initToolFrame();
}
private void initDrawFrame() {
this.mouseHandler = new MouseEventHandler();
this.windowHandler = new WindowEventHandler();
this.drawFrame = new JFrame(Doodler.PROGRAM_NAME);
this.drawFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.drawFrame.setResizable(false);
this.drawContainer = new Container();
this.drawContainer.setLayout(new FlowLayout());
this.imageContainer = new Container();
this.imageContainer.setLayout(new FlowLayout());
this.createCanvas();
this.canvasLabel = new JLabel(this.canvas);
this.imageContainer.add(this.canvasLabel);
this.scrollPane = new JScrollPane(this.imageContainer, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.scrollPane.setAutoscrolls(true);
this.drawContainer.add(this.scrollPane);
this.drawFrame.setContentPane(this.drawContainer);
if (this.drawMode == Doodler.DRAW_MODE_EDIT) {
this.scrollPane.addMouseListener(this.mouseHandler);
this.scrollPane.addMouseMotionListener(this.mouseHandler);
}
this.scrollPane.setMaximumSize(new Dimension(Doodler.SCROLL_PANE_SIZE, Doodler.SCROLL_PANE_SIZE));
this.loc = new int[2];
this.loc[0] = 0;
this.loc[1] = 0;
this.drawFrame.pack();
this.drawFrame.setLocation(0, 0);
this.drawFrame.addWindowListener(this.windowHandler);
}
private void initColorFrame() {
this.ccHandler = new ColorChangeEventHandler();
this.colorFrame = new JFrame("Color");
this.colorContainer = new Container();
this.drawColorImage = this.createColorBox(this.drawColor);
this.currentColor = new JLabel(this.drawColorImage);
this.currentColor.addMouseListener(this.ccHandler);
this.colorContainer.setLayout(new FlowLayout());
this.colorContainer.add(this.currentColor);
this.colorFrame.setContentPane(this.colorContainer);
this.colorFrame.setResizable(false);
this.colorFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.colorFrame.setFocusableWindowState(false);
this.colorFrame.pack();
this.colorFrame.setLocation(this.drawFrame.getWidth() + Doodler.WINDOW_SPACING, this.previewFrame.getHeight() + this.previewFrame.getInsets().top + Doodler.WINDOW_SPACING);
}
private void initPreviewFrame() {
this.previewFrame = new JFrame("Preview");
this.previewContainer = new Container();
this.previewLabel = new JLabel(this.preview);
this.previewContainer.setLayout(new FlowLayout());
this.previewContainer.add(this.previewLabel);
this.previewFrame.setContentPane(this.previewContainer);
this.previewFrame.setResizable(false);
this.previewFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.previewFrame.setFocusableWindowState(false);
this.previewFrame.pack();
this.previewFrame.setLocation(this.drawFrame.getWidth() + Doodler.WINDOW_SPACING, 0);
}
private void initToolFrame() {
this.zoomHandler = new ZoomEventHandler();
this.toolFrame = new JFrame("Tools");
this.toolContainer = new Container();
String[] zoomOptions = {"100%", "200%", "400%", "800%", "1600%", "3200%"};
this.zoomSelector = new JComboBox(zoomOptions);
this.zoomSelector.setEditable(false);
this.zoomSelector.addItemListener(this.zoomHandler);
this.toolContainer.setLayout(new FlowLayout());
this.toolContainer.add(this.zoomSelector);
this.toolFrame.setContentPane(this.toolContainer);
this.toolFrame.setResizable(false);
this.toolFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.toolFrame.setFocusableWindowState(false);
this.toolFrame.pack();
this.toolFrame.setLocation(this.drawFrame.getWidth() + Doodler.WINDOW_SPACING, this.previewFrame.getHeight() + this.previewFrame.getInsets().top + this.colorFrame.getHeight() + this.colorFrame.getInsets().top + Doodler.WINDOW_SPACING);
}
private void checkImageSize() {
if (this.sizeX < Doodler.MIN_IMAGE_SIZE || this.sizeX > Doodler.MAX_IMAGE_SIZE || this.sizeY < Doodler.MIN_IMAGE_SIZE || this.sizeY > Doodler.MAX_IMAGE_SIZE) {
throw new IllegalArgumentException("Image size must be between 2x2 and 100x100!");
}
}
private void changeColor() {
Color newColor = JColorChooser.showDialog(this.drawFrame, Doodler.PROGRAM_NAME, this.drawColor);
if (newColor != null) {
this.drawColor = newColor;
this.drawColorImage = this.createColorBox(this.drawColor);
this.currentColor.setIcon(this.drawColorImage);
}
}
private void changeZoom(int newZoom) {
this.zoomFactor = newZoom;
this.createCanvas();
this.canvasLabel.setIcon(this.canvas);
this.rebuildGrid();
this.drawFrame.pack();
}
public void draw() {
this.isActive = true;
this.rebuildGrid();
this.showAllWindows();
while (this.isActive) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
// Ignore exception
}
}
}
private void showAllWindows() {
this.drawFrame.setVisible(true);
this.previewFrame.setVisible(true);
this.toolFrame.setVisible(true);
if (this.drawMode == Doodler.DRAW_MODE_EDIT) {
this.colorFrame.setVisible(true);
}
}
private void hideAllWindows() {
this.drawFrame.setVisible(false);
this.colorFrame.setVisible(false);
this.previewFrame.setVisible(false);
this.toolFrame.setVisible(false);
}
public Doodle getImage() {
return this.preview;
}
private void rebuildGrid() {
for (int x = 0; x < this.sizeX; x++) {
for (int y = 0; y < this.sizeY; y++) {
int pixel = this.preview.getRGB(x, y);
for (int z = 0; z < this.zoomFactor; z++) {
for (int t = 0; t < this.zoomFactor; t++) {
this.canvas.setRGB((x * this.zoomFactor) + z, (y * this.zoomFactor) + t, pixel);
}
}
}
}
}
private void updateGrid() {
int x = this.loc[0];
int y = this.loc[1];
this.preview.setRGB(y, x, this.drawColor.getRGB());
int pixel = this.drawColor.getRGB();
for (int z = 0; z < this.zoomFactor; z++) {
for (int t = 0; t < this.zoomFactor; t++) {
this.canvas.setRGB((y * this.zoomFactor) + z, (x * this.zoomFactor) + t, pixel);
}
}
this.previewLabel.repaint();
this.canvasLabel.repaint();
}
private void createPreview() {
Doodle image = new Doodle(this.sizeX, this.sizeY, Doodle.TYPE_INT_ARGB);
int rgb = Color.WHITE.getRGB();
for (int x = 0; x < this.sizeX; x++) {
for (int y = 0; y < this.sizeY; y++) {
image.setRGB(x, y, rgb);
}
}
this.preview = image;
}
private void createCanvas() {
Doodle image = new Doodle(this.sizeX * this.zoomFactor, this.sizeY * this.zoomFactor, Doodle.TYPE_INT_ARGB);
int rgb = Color.WHITE.getRGB();
for (int x = 0; x < this.sizeX * this.zoomFactor; x++) {
for (int y = 0; y < this.sizeY * this.zoomFactor; y++) {
image.setRGB(x, y, rgb);
}
}
this.canvas = image;
}
private Doodle createColorBox(Color color) {
Doodle image = new Doodle(Doodler.COLOR_SIZE, Doodler.COLOR_SIZE, Doodle.TYPE_INT_ARGB);
int rgb = color.getRGB();
for (int x = 0; x < Doodler.COLOR_SIZE; x++) {
for (int y = 0; y < Doodler.COLOR_SIZE; y++) {
image.setRGB(x, y, rgb);
}
}
return image;
}
private class WindowEventHandler implements WindowListener {
public void windowOpened(WindowEvent e) {
// Do nothing
}
public void windowClosing(WindowEvent e) {
Doodler.this.hideAllWindows();
Doodler.this.isActive = false;
}
public void windowClosed(WindowEvent e) {
// Do nothing
}
public void windowIconified(WindowEvent e) {
Doodler.this.hideAllWindows();
}
public void windowDeiconified(WindowEvent e) {
Doodler.this.showAllWindows();
}
public void windowActivated(WindowEvent e) {
// Do nothing
}
public void windowDeactivated(WindowEvent e) {
// Do nothing
}
}
private class MouseEventHandler implements MouseListener, MouseMotionListener {
public void mouseClicked(MouseEvent e) {
this.handleClickAndDrag(e);
}
public void mousePressed(MouseEvent e) {
// Do nothing
}
public void mouseReleased(MouseEvent e) {
// Do nothing
}
public void mouseEntered(MouseEvent e) {
// Do nothing
}
public void mouseExited(MouseEvent e) {
// Do nothing
}
public void mouseDragged(MouseEvent e) {
this.handleClickAndDrag(e);
}
public void mouseMoved(MouseEvent e) {
// Do nothing
}
public void handleClickAndDrag(MouseEvent e) {
Doodler d = Doodler.this;
int x = e.getX();
int y = e.getY();
int xLoc = x / d.zoomFactor;
int yLoc = y / d.zoomFactor;
if (xLoc >= 0 && xLoc < d.sizeX && yLoc >= 0 && yLoc < d.sizeY) {
d.loc[1] = xLoc;
d.loc[0] = yLoc;
d.updateGrid();
}
}
}
private class ColorChangeEventHandler implements MouseListener {
public void mouseClicked(MouseEvent e) {
Doodler d = Doodler.this;
d.changeColor();
}
public void mousePressed(MouseEvent e) {
// Do nothing
}
public void mouseReleased(MouseEvent e) {
// Do nothing
}
public void mouseEntered(MouseEvent e) {
// Do nothing
}
public void mouseExited(MouseEvent e) {
// Do nothing
}
}
private class ZoomEventHandler implements ItemListener {
public void itemStateChanged(ItemEvent e) {
String cmd = (String) e.getItem();
int newZoom = 1;
if (cmd.equals("100%")) {
newZoom = 1;
} else if (cmd.equals("200%")) {
newZoom = 2;
} else if (cmd.equals("400%")) {
newZoom = 4;
} else if (cmd.equals("800%")) {
newZoom = 8;
} else if (cmd.equals("1600%")) {
newZoom = 16;
} else if (cmd.equals("3200%")) {
newZoom = 32;
}
Doodler.this.changeZoom(newZoom);
}
}
}
Code:
// Doodle.java
package com.puttysoftware.doodler;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.Icon;
/**
*
* @author wrldwzrd89
*/
public class Doodle extends BufferedImage implements Icon {
// Constructor
public Doodle(int w, int h, int type) {
super(w, h, type);
}
public void paintIcon(Component c, Graphics g, int x, int y) {
g.drawImage(this, x, y, c);
}
public int getIconWidth() {
return this.getWidth();
}
public int getIconHeight() {
return this.getHeight();
}
}
Code:
// Main.java
package doodlertest;
import com.puttysoftware.doodler.Doodler;
import com.puttysoftware.doodler.Doodle;
/**
*
* @author wrldwzrd89
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Doodler d = new Doodler(128, 128);
d.draw();
Doodle doodle = d.getImage();
if (doodle != null) {
Doodler d2 = new Doodler(doodle);
d2.draw();
}
System.exit(0);
}
}