JScrollPane won't show scroll bars, even if content is too big

Discussion in 'Mac Programming' started by wrldwzrd89, Aug 14, 2008.

  1. wrldwzrd89 macrumors G5

    wrldwzrd89

    Joined:
    Jun 6, 2003
    Location:
    Solon, OH
    #1
    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);
        }
    }
    
     
  2. wrldwzrd89 thread starter macrumors G5

    wrldwzrd89

    Joined:
    Jun 6, 2003
    Location:
    Solon, OH
    #2
    I've fiddled some more with the code, but for the life of me, don't understand why this behaves the way it does... I've attached a binary of the offending program. It only does it when the size of the image times the zoom factor exceeds the screen size - it won't show the scroll bars but it "leaks" outside its container.
     

Share This Page