1

I'm making a program that has an image that you scroll around on, and I can't figure out how to update the image if a button is pressed (For example: Adds a Green Ellipse to the image.) It already draws the image into the JScrollPane and you can scroll around, but when you click a button it doesn't refresh the image. (more details in code) Here is the code:

public class PegMaster extends JPanel implements ActionListener {

    //Note: not complete code
    public PegBox[] pegbox = new PegBox[9];

    public static Dimension size = new Dimension(520, 500);

    public BufferedImage canvas;
    public Graphics2D g2d;
    public JScrollPane scroller;
    JPanel panel;
    private Canvas window;

    JScrollPane pictureScrollPane;

    public PegMaster() {
        JButton button = new JButton("test");
        button.addActionListener(this);
        add(button);

        canvas = new BufferedImage((int)size.getWidth()-30, 75 * GUESSES, BufferedImage.TYPE_INT_RGB);
        g2d = canvas.createGraphics();
        for(int i = 0;i<=pegbox.length-1;i++) {
           pegbox[i] = new PegBox(i, g2d);
        }
        window = new Canvas(new ImageIcon(toImage(canvas)), 1);
        //Class Canvas is a Scrollable JLabel to draw to (the image)
        pictureScrollPane = new JScrollPane(window);
        pictureScrollPane.setPreferredSize(new Dimension((int)size.getWidth()-10, (int)size.getHeight()-20));
        pictureScrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.black));
        add(pictureScrollPane);

        //adds the scrollpane, but can't update the image in it
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createGUI();
                //just adds the scrollpane
            }
        });
    }

    public void paint(Graphics g) {
        super.paint(g);

        for(int i = 0;i<=pegbox.length-1;i++) {
            //pegbox[i] = new PegBox(i);
            pegbox[i].draw(g2d);
        }
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }   
        //tried re-making the scrollpane, didn't work.
        //window = new Canvas(new ImageIcon(toImage(canvas)), 1);
        //pictureScrollPane = new JScrollPane(window);
        //pictureScrollPane.setPreferredSize(new Dimension((int)size.getWidth()-10 (int)size.getHeight()-20));
        //pictureScrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.black));
        //tried imageupdate: pictureScrollPane.imageUpdate(canvas, 0, 0, 0 (int)size.getWidth()-10, (int)size.getHeight()-20);
        //remove(pictureScrollPane);
        //tried this: pictureScrollPane.revalidate();
        repaint();
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Spencer H
  • 450
  • 1
  • 6
  • 17
  • As an aside, see [this answer](http://stackoverflow.com/a/12216139/418556) which uses an image as the drawing surface. – Andrew Thompson Sep 15 '12 at 00:01
  • I removed most of the non-releavant code, and the Canvas isn't java.awt.canvas, its My own code Canvas.java that extends JLabel and implements Scrollable – Spencer H Sep 15 '12 at 01:55

3 Answers3

6

Firstly, don't use Canvas it's a heavy weight component, it will only cause you issues in the long run, use either JComponent or JPanel

Secondly, don't override paint, use paintComponent instead. paint does a lot of work, including painting things like the border and child components. It's better if you use paintComponent as it's at the right layer within the paint hierarchy for what you want do to.

Thirdly, NEVER call something like Thread.sleep while in the Event Dispatching Thread. This will cause the event queue to pause and stop responding to events, making you program look like it's stalled.

Fourthly, NEVER call repaint (invalidate, revalidate or any method that might cause a repaint request to occur) within a paint method. You will simply end up maxing out your CPU and you will be forced to kill the process.

Fifthly, you didn't provide the actionPerformed method, which is probably where all the action (and problems) are. I'd imagin you need to call window.repaint() and possibly window.invalidate() (in reverse order), but since you didn't provided use with this code, that's simply speculation...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
3

Try this class which displays an Image. This can be added to a JScrollPane

public class ImagePanel extends JPanel {

    public Image img;

    public ImagePanel(Image img){
        this.img = img;
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(img, 0, 0, this);
    }

}

Now add this class to the JScrollPane. To update it, just change the image reference and call the repaint() method on the component

Sri Harsha Chilakapati
  • 11,744
  • 6
  • 50
  • 91
0

The above solution didn't solved my purpose so I researched and found this. Please follow the link for whole example. I have added the code to refer in case the link changes.

public class ScrollablePicture extends JLabel
                           implements Scrollable,
                                      MouseMotionListener {

private int maxUnitIncrement = 1;
private boolean missingPicture = false;

public ScrollablePicture(ImageIcon i, int m) {
    super(i);
    if (i == null) {
        missingPicture = true;
        setText("No picture found.");
        setHorizontalAlignment(CENTER);
        setOpaque(true);
        setBackground(Color.white);
    }
    maxUnitIncrement = m;

    //Let the user scroll by dragging to outside the window.
    setAutoscrolls(true); //enable synthetic drag events
    addMouseMotionListener(this); //handle mouse drags
}

//Methods required by the MouseMotionListener interface:
public void mouseMoved(MouseEvent e) { }
public void mouseDragged(MouseEvent e) {
    //The user is dragging us, so scroll!
    Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
    scrollRectToVisible(r);
}

public Dimension getPreferredSize() {
    if (missingPicture) {
        return new Dimension(320, 480);
    } else {
        return super.getPreferredSize();
    }
}

public Dimension getPreferredScrollableViewportSize() {
    return getPreferredSize();
}

public int getScrollableUnitIncrement(Rectangle visibleRect,
                                      int orientation,
                                      int direction) {
    //Get the current position.
    int currentPosition = 0;
    if (orientation == SwingConstants.HORIZONTAL) {
        currentPosition = visibleRect.x;
    } else {
        currentPosition = visibleRect.y;
    }

    //Return the number of pixels between currentPosition
    //and the nearest tick mark in the indicated direction.
    if (direction < 0) {
        int newPosition = currentPosition -
                         (currentPosition / maxUnitIncrement)
                          * maxUnitIncrement;
        return (newPosition == 0) ? maxUnitIncrement : newPosition;
    } else {
        return ((currentPosition / maxUnitIncrement) + 1)
               * maxUnitIncrement
               - currentPosition;
    }
}

public int getScrollableBlockIncrement(Rectangle visibleRect,
                                       int orientation,
                                       int direction) {
    if (orientation == SwingConstants.HORIZONTAL) {
        return visibleRect.width - maxUnitIncrement;
    } else {
        return visibleRect.height - maxUnitIncrement;
    }
}

public boolean getScrollableTracksViewportWidth() {
    return false;
}

public boolean getScrollableTracksViewportHeight() {
    return false;
}

public void setMaxUnitIncrement(int pixels) {
    maxUnitIncrement = pixels;
}
singularity
  • 147
  • 1
  • 11