-1

I am making a simple program similar to MS Paint. I create a custom Image which is blank as my 'canvas'. However, whenever I enlarge the window, the Image stays the same size. How can I make it so when I resize the window, the image fits?

My code is:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ScribblePad extends JFrame {

    // Setting GUI variables...

    public static int WIDTH = 800;
    public static int HEIGHT = 800;

    public static int X = 10;
    public static int Y = 10;

    public static String TITLE = "ScribblePad";

    // Create GUI components...

    PaintPanel paintPanel = new PaintPanel();

    JPanel buttonPanel = new JPanel();

    Container mainContainer = getContentPane();

    JButton clearButton = new JButton("Clear");

    JButton buttonBlack = new JButton();
    JButton buttonRed = new JButton();
    JButton buttonBlue = new JButton();
    JButton buttonYellow = new JButton();
    JButton buttonGreen = new JButton();

    Cursor crosshairCursor = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);

    // Run the entire program...

    public static void main(String []args) {

        new ScribblePad();

    }

    // Create ScribblePad constructor...

    public ScribblePad() {

        // Setting JFrame properties...

        super(TITLE);

        setVisible(true);

        setSize(WIDTH, HEIGHT);
        setLocation(X, Y);      

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // Setting properties of other components...

        paintPanel.setCursor(crosshairCursor);

        buttonPanel.setBackground(Color.WHITE);

        buttonPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK));

        // Adding the components...

        mainContainer.add(paintPanel, BorderLayout.CENTER);

        mainContainer.add(buttonPanel, BorderLayout.NORTH);

        // Adding ActionListeners and setting properties of the buttons..

        buttonBlack.setBackground(Color.BLACK);
        buttonBlack.setForeground(Color.BLACK);
        buttonBlack.setPreferredSize(new Dimension(32, 32));

        buttonRed.setBackground(Color.RED);
        buttonRed.setForeground(Color.RED);
        buttonRed.setPreferredSize(new Dimension(32, 32));

        buttonGreen.setBackground(Color.GREEN);
        buttonGreen.setForeground(Color.GREEN);
        buttonGreen.setPreferredSize(new Dimension(32, 32));

        buttonBlue.setBackground(Color.BLUE);
        buttonBlue.setForeground(Color.BLUE);
        buttonBlue.setPreferredSize(new Dimension(32, 32));

        buttonYellow.setBackground(Color.YELLOW);
        buttonYellow.setForeground(Color.YELLOW);
        buttonYellow.setPreferredSize(new Dimension(32, 32));

        clearButton.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.clearCanvas();

            }

        });

        buttonBlack.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setBlack();

            }

        });

        buttonGreen.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setGreen();


            }

        });

        buttonRed.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setRed();

            }

        });

        buttonYellow.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setYellow();

            }

        });

        buttonBlue.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e){

                paintPanel.setBlue();

            }

        });

        // Adding buttons to the buttonPanel...

        buttonPanel.add(buttonBlack);
        buttonPanel.add(buttonRed);
        buttonPanel.add(buttonGreen);
        buttonPanel.add(buttonBlue);
        buttonPanel.add(buttonYellow);

        buttonPanel.add(clearButton);

    }

    public class PaintPanel extends JComponent {

        Image blankCanvas;

        Graphics2D g2D;

        int mouseX, mouseY, oldX, oldY;

        String currentColour = "BLACK";

        public PaintPanel() {

            setDoubleBuffered(true);

            addMouseListener(new MouseAdapter() {

                public void mousePressed(MouseEvent e) {

                    oldX = e.getX();
                    oldY = e.getY();

                    g2D.drawOval(oldX, oldY, 1, 1);

                    System.out.println("[Debug] Point drawn at (" + oldX + ", " + oldY + ").");

                    repaint();

                }

            });

            addMouseMotionListener(new MouseMotionAdapter(){

                public void mouseDragged(MouseEvent e){

                    mouseX = e.getX();
                    mouseY = e.getY();

                    if(g2D != null)

                    g2D.drawLine(oldX, oldY, mouseX, mouseY);

                    repaint();

                    System.out.println("[Debug] Line drawn from (" + oldX + ", " + oldY + ") to (" + mouseX + ", " + mouseY + ").");

                    oldX = mouseX;
                    oldY = mouseY;

                }

            });

        }

        public void paintComponent(Graphics g) {

            if (blankCanvas == null) {

                blankCanvas = this.createImage(getWidth(), getHeight());

                g2D = (Graphics2D)blankCanvas.getGraphics();

                g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                clearCanvas();

            }

            g.drawImage(blankCanvas, 0, 0, null);   

        }

        public void clearCanvas() {

            g2D.setPaint(Color.WHITE);
            g2D.fillRect(0, 0, getSize().width, getSize().height);

            switch(currentColour) {

            case "BLACK": g2D.setColor(Color.BLACK); break;

            case "RED": g2D.setColor(Color.RED); break;

            case "GREEN": g2D.setColor(Color.GREEN); break;

            case "BLUE": g2D.setColor(Color.BLUE); break;

            case "YELLOW": g2D.setColor(Color.YELLOW); break;

            }

            System.out.println("[Debug] Canvas cleared.");

            repaint();

        }

        public void setBlack() {

            g2D.setColor(Color.BLACK);

            System.out.println("[Debug] Colour changed to black.");

            currentColour = "BLACK";

        }

        public void setRed() {

            g2D.setColor(Color.RED);

            System.out.println("[Debug] Colour changed to red.");

            currentColour = "RED";

        }

        public void setBlue() {

            g2D.setColor(Color.BLUE);

            System.out.println("[Debug] Colour changed to blue.");

            currentColour = "BLUE";

        }

        public void setYellow() {

            g2D.setColor(Color.YELLOW);

            System.out.println("[Debug] Colour changed to yellow.");

            currentColour = "YELLOW";

        }

        public void setGreen() {

            g2D.setColor(Color.GREEN);

            System.out.println("[Debug] Colour changed to green.");

            currentColour = "GREEN";

        }

    }

}
Eyenstein
  • 1
  • 1
  • 2
  • 2
    Please show what you have tried so far and only post a SSCCE not your entire program. – jzd Nov 06 '13 at 18:31
  • You could have a look at [this example](http://stackoverflow.com/questions/11959758/java-maintaining-aspect-ratio-of-jpanel-background-image/11959928#11959928) – MadProgrammer Nov 07 '13 at 06:15

3 Answers3

1

I can't tell if you question is about scaling the existing image, or making the painting area larger/smaller as the frame size changes.

Scaling is a problem because once you resize the image, you will always need to rescale mouse points to get them back to the original coordinate system.

So changing the painting area is easier, but if you use an Image, then what happens when you shrink the window size? Do you truncate any existing paintings?

For this reason I would suggest that you instead just paint directly onto the component and use a List to track the individual ovals. This way resizing doesn't affect the drawing of the ovals. All that will change is what is visible at any time.

Check out Custom Painting Approaches for an example of this approach. This example shows how you can also use different color without hardcoding specific methods to set the color.

As this is a small project to start me off with paintComponent, I would like to simply truncate the area.

For a simple solution, just make the image the screen size. Then you don't have to worry about truncating/stretching every time the frame resizes.

Otherwise you would need to add a ComponentListener to the panel and listen for the componentResized() event. Then you would need to create a new image and paint the old image onto the new image. You should note that a componentResized() event is generated for every pixel the panel is resized so this would involve a lot of background work.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thank you camickr for the lengthy reply. As this is a small project to start me off with paintComponent, I would like to simply truncate the area. Do you any ideas as to how I can do that? – Eyenstein Nov 06 '13 at 19:09
  • I have added: Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); and then blankCanvas = this.createImage(screenSize.width, screenSize.height); but this doesn't work. Am I doing something wrong? – Eyenstein Nov 06 '13 at 20:28
  • @Eyenstein, `but this doesn't work` I have no idea what that means. – camickr Nov 06 '13 at 21:09
  • Sorry I'm new here. What I mean is that it still has the same problem as before. The Image area is still the same size – Eyenstein Nov 07 '13 at 07:14
  • @Eyenstein, If you make the image the isize of the screen then that will be its size. However, you will only see whatever is visible in the viewport of the scrollpane. So as the frame resizes the visibility of the image will change. – camickr Nov 07 '13 at 15:41
  • I realised my mistake: the Image was the correct size but whenever I cleared the canvas, I was only clearing the visible part of the screen. – Eyenstein Nov 07 '13 at 18:37
0

Use g2d.scale(x, y) in your paintComponent Method. You'll need to get the current height and width and compare it to the previous height and width in order to determine the scale factor. Set it so that when the screen is at your default size your scale factors are 0.

You'll want a window listener that compute the scale factor on componentResized() events. Something like scaleX = getWidth() / WIDTH;

Dodd10x
  • 3,344
  • 1
  • 18
  • 27
0

To find current height and width of the Windows, try this code

Toolkit toolkit =  Toolkit.getDefaultToolkit ();
Dimension dim = toolkit.getScreenSize();
int width = dim.getWidth();
int height = dim.getHeight();

now use scale function scale(int x, int y), of Graphics class and this method is called repeatedly and in quick successions when the window size changes, Check it using above codes.

Better try reading https://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

sam
  • 120
  • 1
  • 8